DragAbleWidget.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. /**
  2. * 叶海辉
  3. * QQ群321159586
  4. * http://blog.yundiantech.com/
  5. */
  6. #include "DragAbleWidget.h"
  7. #include "ui_DragAbleWidget.h"
  8. #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
  9. #include <QScreen>
  10. #else
  11. #include <QDesktopWidget>
  12. #endif
  13. #include <QMouseEvent>
  14. #include <QTimer>
  15. #include <QDebug>
  16. #define MARGINS 2 //窗体边框
  17. DragAbleWidget::DragAbleWidget(QWidget *parent) :
  18. QWidget(parent),
  19. ui(new Ui::DragAbleWidget)
  20. {
  21. ui->setupUi(this);
  22. ///定时器用于定制检测鼠标位置,防止鼠标快速移入窗口,没有检测到,导致鼠标箭头呈现拖拉的形状
  23. mTimer = new QTimer;
  24. mTimer->setInterval(1000);
  25. connect(mTimer, &QTimer::timeout, this, &DragAbleWidget::slotTimerTimeOut);
  26. mTimer->start();
  27. ///改变窗体大小相关
  28. isMax = false;
  29. int w = this->width();
  30. int h = this->height();
  31. #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
  32. QRect screenRect = QApplication::primaryScreen()->availableGeometry();//获取设备屏幕大小
  33. #else
  34. QRect screenRect = QApplication::desktop()->screenGeometry();//获取设备屏幕大小
  35. #endif
  36. int x = (screenRect.width() - w) / 2;
  37. int y = (screenRect.height() - h) / 2;
  38. mLocation = this->geometry();
  39. // mLocation = QRect(x, y, w, h);
  40. // this->setGeometry(mLocation);
  41. isLeftPressDown = false;
  42. this->dir = NONE;
  43. this->setMouseTracking(true);// 追踪鼠标
  44. ui->widget_frame->setMouseTracking(true);
  45. ui->widget_back->setMouseTracking(true);
  46. ui->widget_container->setMouseTracking(true);
  47. // ui->widget_center->setMouseTracking(true);
  48. this->setFocusPolicy(Qt::ClickFocus);
  49. ui->widget_frame->setContentsMargins(MARGINS,MARGINS,MARGINS,MARGINS);
  50. showBorderRadius(true);
  51. // ui->widget_frame->setContentsMargins(1, 1, 1, 1);
  52. //安装事件监听器,让标题栏识别鼠标双击
  53. // ui->widget_beingClass_back->installEventFilter(this);
  54. }
  55. DragAbleWidget::~DragAbleWidget()
  56. {
  57. }
  58. QWidget *DragAbleWidget::getContainWidget()
  59. {
  60. return ui->widget_container;
  61. }
  62. void DragAbleWidget::setTitle(QString str)
  63. {
  64. ui->label_titleName->setText(str);
  65. this->setWindowTitle(str);
  66. }
  67. ////////////改变窗体大小相关
  68. void DragAbleWidget::mouseReleaseEvent(QMouseEvent *event)
  69. {
  70. if(event->button() == Qt::LeftButton)
  71. {
  72. isLeftPressDown = false;
  73. if(dir != NONE)
  74. {
  75. this->releaseMouse();
  76. this->setCursor(QCursor(Qt::ArrowCursor));
  77. }
  78. }
  79. }
  80. void DragAbleWidget::mousePressEvent(QMouseEvent *event)
  81. {
  82. // qDebug()<<__FUNCTION__;
  83. if (event->type() == QEvent::MouseButtonDblClick)
  84. {
  85. if (event->button() == Qt::LeftButton)
  86. {
  87. // if(QApplication::keyboardModifiers() == (Qt::ControlModifier|Qt::ShiftModifier|Qt::AltModifier))
  88. {
  89. doChangeFullScreen(); //ctrl + 左键
  90. }
  91. }
  92. }
  93. switch(event->button())
  94. {
  95. case Qt::LeftButton:
  96. if (isMax || this->isFullScreen()) break;
  97. isLeftPressDown = true;
  98. checkCursorDirect(event->globalPos());
  99. if(dir != NONE)
  100. {
  101. this->mouseGrabber();
  102. mIsResizeMode = true;
  103. }
  104. else
  105. {
  106. dragPosition = event->globalPos() - this->frameGeometry().topLeft();
  107. mIsResizeMode = false;
  108. }
  109. break;
  110. // case Qt::RightButton:
  111. // if (!this->isFullScreen())
  112. // mAction_FullScreen->setText(tr("show fullscreen"));
  113. // else
  114. // mAction_FullScreen->setText(tr("quit fullscreen"));
  115. // mPopMenu->exec(QCursor::pos());
  116. // break;
  117. default:
  118. QWidget::mousePressEvent(event);
  119. }
  120. }
  121. void DragAbleWidget::mouseMoveEvent(QMouseEvent *event)
  122. {
  123. // qDebug()<<__FUNCTION__;
  124. if (isMax || this->isFullScreen()) return;
  125. QPoint gloPoint = event->globalPos();
  126. QRect rect = this->rect();
  127. QPoint tl = mapToGlobal(rect.topLeft());
  128. QPoint rb = mapToGlobal(rect.bottomRight());
  129. if (isMax || this->isFullScreen()) return;
  130. if (!isLeftPressDown)
  131. {
  132. checkCursorDirect(gloPoint);
  133. return;
  134. }
  135. // if(!isLeftPressDown)
  136. // {
  137. // checkCursorDirect(gloPoint);
  138. // }
  139. // else
  140. {
  141. // if(dir != NONE)
  142. if (mIsResizeMode)
  143. {
  144. QRect rMove(tl, rb);
  145. switch(dir) {
  146. case LEFT:
  147. if(rb.x() - gloPoint.x() <= this->minimumWidth())
  148. rMove.setX(tl.x());
  149. else
  150. rMove.setX(gloPoint.x());
  151. break;
  152. case RIGHT:
  153. rMove.setWidth(gloPoint.x() - tl.x());
  154. break;
  155. case UP:
  156. if(rb.y() - gloPoint.y() <= this->minimumHeight())
  157. rMove.setY(tl.y());
  158. else
  159. rMove.setY(gloPoint.y());
  160. break;
  161. case DOWN:
  162. rMove.setHeight(gloPoint.y() - tl.y());
  163. break;
  164. case LEFTTOP:
  165. if(rb.x() - gloPoint.x() <= this->minimumWidth())
  166. rMove.setX(tl.x());
  167. else
  168. rMove.setX(gloPoint.x());
  169. if(rb.y() - gloPoint.y() <= this->minimumHeight())
  170. rMove.setY(tl.y());
  171. else
  172. rMove.setY(gloPoint.y());
  173. break;
  174. case RIGHTTOP:
  175. rMove.setWidth(gloPoint.x() - tl.x());
  176. rMove.setY(gloPoint.y());
  177. break;
  178. case LEFTBOTTOM:
  179. rMove.setX(gloPoint.x());
  180. rMove.setHeight(gloPoint.y() - tl.y());
  181. break;
  182. case RIGHTBOTTOM:
  183. rMove.setWidth(gloPoint.x() - tl.x());
  184. rMove.setHeight(gloPoint.y() - tl.y());
  185. break;
  186. default:
  187. break;
  188. }
  189. this->setGeometry(rMove);
  190. // emit sig_WindowMoved(rMove);
  191. } else {
  192. checkCursorDirect(event->globalPos());
  193. if (dir == NONE && !isMax)
  194. {
  195. QPoint point = event->globalPos() - dragPosition;
  196. #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
  197. QRect mLimitRect = QApplication::primaryScreen()->availableGeometry();
  198. #else
  199. QRect mLimitRect = QApplication::desktop()->availableGeometry();
  200. #endif
  201. if (point.x() < mLimitRect.x())
  202. point.setX(mLimitRect.x());
  203. if (point.x() > (mLimitRect.x()+mLimitRect.width()-this->width()))
  204. point.setX(mLimitRect.x()+mLimitRect.width()-this->width());
  205. if (point.y() < mLimitRect.y())
  206. point.setY(mLimitRect.y());
  207. if (point.y() > (mLimitRect.y()+mLimitRect.height()-this->height()))
  208. point.setY(mLimitRect.y()+mLimitRect.height()-this->height());
  209. move(point);
  210. }
  211. event->accept();
  212. }
  213. }
  214. // QWidget::mouseMoveEvent(event);、
  215. event->accept();
  216. }
  217. void DragAbleWidget::checkCursorDirect(const QPoint &cursorGlobalPoint)
  218. {
  219. // 获取窗体在屏幕上的位置区域,tl为topleft点,rb为rightbottom点
  220. QRect rect = this->rect();
  221. QPoint tl = mapToGlobal(rect.topLeft());
  222. QPoint rb = mapToGlobal(rect.bottomRight());
  223. int x = cursorGlobalPoint.x();
  224. int y = cursorGlobalPoint.y();
  225. if(tl.x() + PADDING >= x && tl.x() <= x && tl.y() + PADDING >= y && tl.y() <= y) {
  226. // 左上角
  227. dir = LEFTTOP;
  228. this->setCursor(QCursor(Qt::SizeFDiagCursor)); // 设置鼠标形状
  229. } else if(x >= rb.x() - PADDING && x <= rb.x() && y >= rb.y() - PADDING && y <= rb.y()) {
  230. // 右下角
  231. dir = RIGHTBOTTOM;
  232. this->setCursor(QCursor(Qt::SizeFDiagCursor));
  233. } else if(x <= tl.x() + PADDING && x >= tl.x() && y >= rb.y() - PADDING && y <= rb.y()) {
  234. //左下角
  235. dir = LEFTBOTTOM;
  236. this->setCursor(QCursor(Qt::SizeBDiagCursor));
  237. } else if(x <= rb.x() && x >= rb.x() - PADDING && y >= tl.y() && y <= tl.y() + PADDING) {
  238. // 右上角
  239. dir = RIGHTTOP;
  240. this->setCursor(QCursor(Qt::SizeBDiagCursor));
  241. } else if(x <= tl.x() + PADDING && x >= tl.x()) {
  242. // 左边
  243. dir = LEFT;
  244. this->setCursor(QCursor(Qt::SizeHorCursor));
  245. } else if( x <= rb.x() && x >= rb.x() - PADDING) {
  246. // 右边
  247. dir = RIGHT;
  248. this->setCursor(QCursor(Qt::SizeHorCursor));
  249. }else if(y >= tl.y() && y <= tl.y() + PADDING){
  250. // 上边
  251. dir = UP;
  252. this->setCursor(QCursor(Qt::SizeVerCursor));
  253. } else if(y <= rb.y() && y >= rb.y() - PADDING) {
  254. // 下边
  255. dir = DOWN;
  256. this->setCursor(QCursor(Qt::SizeVerCursor));
  257. }else {
  258. // 默认
  259. dir = NONE;
  260. this->setCursor(QCursor(Qt::ArrowCursor));
  261. }
  262. }
  263. void DragAbleWidget::doShowFullScreen()
  264. {
  265. this->show();
  266. this->showFullScreen();
  267. this->raise();
  268. ui->widget_frame->setContentsMargins(0,0,0,0); //隐藏边框
  269. showBorderRadius(false);
  270. ui->btnMenu_Max->setIcon(QIcon(":/image/shownormalbtn.png"));
  271. ui->widget_title->hide(); //隐藏标题栏
  272. // ui->verticalLayout_titleWidget_Back->removeWidget(ui->widget_title);
  273. // ui->widget_title->setParent(NULL);
  274. // ui->widget_title->setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint|Qt::Tool|Qt::X11BypassWindowManagerHint);
  275. // ui->widget_title->resize(QApplication::desktop()->screen()->width(), ui->widget_title->height());
  276. // ui->widget_title->move(0,0);
  277. // ui->widget_title->show();
  278. }
  279. void DragAbleWidget::doShowNormal()
  280. {
  281. qDebug()<<__FUNCTION__;
  282. this->show();
  283. this->showNormal();
  284. this->raise();
  285. if (!isMax)
  286. {
  287. ui->widget_frame->setContentsMargins(MARGINS,MARGINS,MARGINS,MARGINS);
  288. showBorderRadius(true);
  289. } else {
  290. ui->widget_frame->setContentsMargins(0,0,0,0);
  291. showBorderRadius(false);
  292. }
  293. ui->btnMenu_Max->setIcon(QIcon(":/image/showmaxsizebtn.png"));
  294. QTimer::singleShot(20,this,[&]()
  295. {
  296. ui->verticalLayout_titleWidget_Back->addWidget(ui->widget_title);
  297. ui->widget_title->show();
  298. });
  299. }
  300. void DragAbleWidget::showBorderRadius(bool isShow)
  301. {
  302. QString str;
  303. if (isShow)
  304. {
  305. str = QString("QWidget#widget_frame\
  306. {\
  307. border:3px solid rgb(46, 165, 255);\
  308. background-color: rgba(255, 255, 255, 0);\
  309. border-radius:5px;\
  310. }\
  311. QWidget#widget_back\
  312. {\
  313. border-radius:3px;\
  314. }\
  315. QWidget#widget_title\
  316. {\
  317. border-top-right-radius:5px;\
  318. border-top-left-radius:5px;\
  319. }\
  320. QWidget#widget_container\
  321. {\
  322. border-bottom-right-radius:5px;\
  323. border-bottom-left-radius:5px;\
  324. }\
  325. QStackedWidget\
  326. {\
  327. border-bottom-right-radius:5px;\
  328. border-bottom-left-radius:5px;\
  329. }\
  330. QWidget#page_courseList\
  331. {\
  332. border-bottom-right-radius:5px;\
  333. border-bottom-left-radius:5px;\
  334. }");
  335. }
  336. else
  337. {
  338. str = QString("QWidget#widget_frame\
  339. {\
  340. border:3px solid rgb(46, 165, 255);\
  341. background-color: rgba(255, 255, 255, 0);\
  342. border-radius:0px;\
  343. }\
  344. QWidget#widget_back\
  345. {\
  346. border-radius:0px;\
  347. }\
  348. QWidget#widget_title\
  349. {\
  350. border-top-right-radius:0px;\
  351. border-top-left-radius:0px;\
  352. }\
  353. QWidget#widget_container\
  354. {\
  355. border-bottom-right-radius:0px;\
  356. border-bottom-left-radius:0px;\
  357. }\
  358. QStackedWidget\
  359. {\
  360. border-bottom-right-radius:0px;\
  361. border-bottom-left-radius:0px;\
  362. }\
  363. QWidget#page_courseList\
  364. {\
  365. border-bottom-right-radius:0px;\
  366. border-bottom-left-radius:0px;\
  367. }");
  368. }
  369. ui->widget_frame->setStyleSheet(str);
  370. }
  371. void DragAbleWidget::doChangeFullScreen()
  372. {
  373. if (this->isFullScreen())
  374. {
  375. this->doShowNormal();
  376. // mAction_FullScreen->setText(tr("show fullscreen"));
  377. }
  378. else
  379. {
  380. this->doShowFullScreen();
  381. // mAction_FullScreen->setText(tr("quit fullscreen"));
  382. }
  383. }
  384. void DragAbleWidget::on_btnMenu_Close_clicked()
  385. {
  386. qDebug()<<__FUNCTION__;
  387. close();
  388. // QTimer::singleShot(500,this,[&]()
  389. // {
  390. // QPoint pt(0, 0);
  391. // QMouseEvent evt(QEvent::Leave, pt, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
  392. // qApp->sendEvent(ui->btnMenu_Close, &evt);
  393. // });
  394. }
  395. void DragAbleWidget::on_btnMenu_Max_clicked()
  396. {
  397. doChangeFullScreen();
  398. }
  399. void DragAbleWidget::on_btnMenu_Min_clicked()
  400. {
  401. if (this->isFullScreen())
  402. {
  403. // mAnimation->stop();
  404. // mTimer_CheckTitle->stop();
  405. ui->widget_title->move(ui->widget_title->x(), 0 - ui->widget_title->height());
  406. ui->widget_title->hide();
  407. }
  408. this->showMinimized();
  409. QTimer::singleShot(500,this,[&]()
  410. {
  411. QPoint pt(0, 0);
  412. QMouseEvent evt(QEvent::Leave, pt, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
  413. qApp->sendEvent(ui->btnMenu_Min, &evt);
  414. });
  415. }
  416. void DragAbleWidget::slotTimerTimeOut()
  417. {
  418. if (QObject::sender() == mTimer)
  419. {
  420. checkCursorDirect(QCursor::pos());
  421. }
  422. }