selectwidget.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. #pragma execution_character_set("utf-8")
  2. #include "selectwidget.h"
  3. SelectWidget::SelectWidget(QWidget *parent) : QWidget(parent)
  4. {
  5. drawPoint = false;
  6. padding = 5;
  7. borderWidth = 1;
  8. pointSize = 8;
  9. pointColor = QColor(34, 163, 168);
  10. pointStyle = PointStyle:: PointStyle_Rect;
  11. pressed = false;
  12. pressedLeft = false;
  13. pressedRight = false;
  14. pressedTop = false;
  15. pressedBottom = false;
  16. pressedLeftTop = false;
  17. pressedRightTop = false;
  18. pressedLeftBottom = false;
  19. pressedRightBottom = false;
  20. widget = 0;
  21. // 增加:控件的类型的和指针
  22. m_Type = VALUE_TYPE::Type_Unknown;
  23. m_pProperty = nullptr;
  24. // 扩展属性
  25. m_pPropertyEx = nullptr;
  26. //设置鼠标追踪为真,并绑定事件过滤器,可以获取焦点用于按键移动位置
  27. this->setMouseTracking(true);
  28. //安装事件过滤器,识别鼠标拖动和拉伸大小
  29. this->installEventFilter(this);
  30. //设置焦点策略,以便鼠标按下获取焦点并手柄可见
  31. this->setFocusPolicy(Qt::StrongFocus);
  32. }
  33. /// <summary>
  34. /// 拦截所属的控件事件
  35. /// </summary>
  36. /// <param name="watched"></param>
  37. /// <param name="event"></param>
  38. /// <returns></returns>
  39. bool SelectWidget::eventFilter(QObject *watched, QEvent *event)
  40. {
  41. // 拦截键盘事件
  42. if (event->type() == QEvent::KeyPress)
  43. {
  44. QKeyEvent *keyEvent = dynamic_cast<QKeyEvent *>(event);
  45. if (keyEvent->key() == Qt::Key_Left)
  46. {
  47. this->move(this->pos() - QPoint(1, 0));
  48. } else if (keyEvent->key() == Qt::Key_Right)
  49. {
  50. this->move(this->pos() + QPoint(1, 0));
  51. } else if (keyEvent->key() == Qt::Key_Up)
  52. {
  53. this->move(this->pos() - QPoint(0, 1));
  54. } else if (keyEvent->key() == Qt::Key_Down)
  55. {
  56. this->move(this->pos() + QPoint(0, 1));
  57. } else if (keyEvent->key() == Qt::Key_Delete)
  58. {
  59. emit widgetDelete(widget);
  60. widget->deleteLater();
  61. this->deleteLater();
  62. widget = 0;
  63. }
  64. //重新设置附带窗体的位置和大小
  65. if (widget != 0) {
  66. widget->setGeometry(this->x() + padding, this->y() + padding, this->width() - padding * 2, this->height() - padding * 2);
  67. }
  68. return QWidget::eventFilter(watched, event);
  69. }
  70. QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
  71. if (mouseEvent->type() == QEvent::MouseButtonPress)
  72. {
  73. //记住当前控件坐标和宽高以及鼠标按下的坐标
  74. rectX = this->x();
  75. rectY = this->y();
  76. rectW = this->width();
  77. rectH = this->height();
  78. lastPos = mouseEvent->pos();
  79. //判断按下的手柄的区域位置
  80. if (rectLeft.contains(lastPos)) {
  81. pressedLeft = true;
  82. } else if (rectRight.contains(lastPos)) {
  83. pressedRight = true;
  84. } else if (rectTop.contains(lastPos)) {
  85. pressedTop = true;
  86. } else if (rectBottom.contains(lastPos)) {
  87. pressedBottom = true;
  88. } else if (rectLeftTop.contains(lastPos)) {
  89. pressedLeftTop = true;
  90. } else if (rectRightTop.contains(lastPos)) {
  91. pressedRightTop = true;
  92. } else if (rectLeftBottom.contains(lastPos)) {
  93. pressedLeftBottom = true;
  94. } else if (rectRightBottom.contains(lastPos)) {
  95. pressedRightBottom = true;
  96. } else {
  97. pressed = true;
  98. }
  99. if (widget != 0)
  100. {
  101. emit widgetPressed(widget);
  102. }
  103. }
  104. else if (mouseEvent->type() == QEvent::MouseMove)
  105. {
  106. //根据当前鼠标位置,计算XY轴移动了多少
  107. QPoint pos = mouseEvent->pos();
  108. int dx = pos.x() - lastPos.x();
  109. int dy = pos.y() - lastPos.y();
  110. //根据按下处的位置判断是否是移动控件还是拉伸控件
  111. if (pressed)
  112. {
  113. this->move(this->x() + dx, this->y() + dy);
  114. }
  115. else if (pressedLeft)
  116. {
  117. int resizeW = this->width() - dx;
  118. if (this->minimumWidth() <= resizeW)
  119. {
  120. this->setGeometry(this->x() + dx, rectY, resizeW, rectH);
  121. }
  122. }
  123. else if (pressedRight)
  124. {
  125. this->setGeometry(rectX, rectY, rectW + dx, rectH);
  126. }
  127. else if (pressedTop)
  128. {
  129. int resizeH = this->height() - dy;
  130. if (this->minimumHeight() <= resizeH)
  131. {
  132. this->setGeometry(rectX, this->y() + dy, rectW, resizeH);
  133. }
  134. }
  135. else if (pressedBottom)
  136. {
  137. this->setGeometry(rectX, rectY, rectW, rectH + dy);
  138. }
  139. else if (pressedLeftTop)
  140. {
  141. int resizeW = this->width() - dx;
  142. int resizeH = this->height() - dy;
  143. if (this->minimumWidth() <= resizeW) {
  144. this->setGeometry(this->x() + dx, this->y(), resizeW, resizeH);
  145. }
  146. if (this->minimumHeight() <= resizeH) {
  147. this->setGeometry(this->x(), this->y() + dy, resizeW, resizeH);
  148. }
  149. }
  150. else if (pressedRightTop)
  151. {
  152. int resizeW = rectW + dx;
  153. int resizeH = this->height() - dy;
  154. if (this->minimumHeight() <= resizeH) {
  155. this->setGeometry(this->x(), this->y() + dy, resizeW, resizeH);
  156. }
  157. }
  158. else if (pressedLeftBottom)
  159. {
  160. int resizeW = this->width() - dx;
  161. int resizeH = rectH + dy;
  162. if (this->minimumWidth() <= resizeW) {
  163. this->setGeometry(this->x() + dx, this->y(), resizeW, resizeH);
  164. }
  165. if (this->minimumHeight() <= resizeH) {
  166. this->setGeometry(this->x(), this->y(), resizeW, resizeH);
  167. }
  168. }
  169. else if (pressedRightBottom)
  170. {
  171. int resizeW = rectW + dx;
  172. int resizeH = rectH + dy;
  173. this->setGeometry(this->x(), this->y(), resizeW, resizeH);
  174. }
  175. //重新设置附带窗体的位置和大小
  176. if (widget != 0)
  177. {
  178. widget->setGeometry(this->x() + padding, this->y() + padding, this->width() - padding * 2, this->height() - padding * 2);
  179. }
  180. // 2022-3-20修改,如果和上次的区域区域有变化,则发出控件移动信号,用于向属性表同步
  181. if( this->geometry()!= oldGeometry )
  182. {
  183. // emit widgetMove(widget);
  184. oldGeometry = this->geometry();
  185. }
  186. }
  187. else if (mouseEvent->type() == QEvent::MouseButtonRelease)
  188. {
  189. pressed = false;
  190. pressedLeft = false;
  191. pressedRight = false;
  192. pressedTop = false;
  193. pressedBottom = false;
  194. pressedLeftTop = false;
  195. pressedRightTop = false;
  196. pressedLeftBottom = false;
  197. pressedRightBottom = false;
  198. if (widget != 0)
  199. {
  200. emit widgetRelease(widget);
  201. }
  202. }
  203. return QWidget::eventFilter(watched, event);
  204. }
  205. void SelectWidget::resizeEvent(QResizeEvent *)
  206. {
  207. // qDebug() << "SelectWidget::resizeEvent";
  208. //重新计算八个描点的区域,描点区域的作用还有就是计算鼠标坐标是否在某一个区域内
  209. double width = this->width();
  210. double height = this->height();
  211. //左侧描点区域
  212. rectLeft = QRectF(0, int( height / 2.0 - pointSize / 2.0), pointSize, pointSize);
  213. //上侧描点区域
  214. rectTop = QRectF(int(width / 2 - pointSize / 2), 0, pointSize, pointSize);
  215. //右侧描点区域
  216. rectRight = QRectF(int(width - pointSize),int( height / 2 - pointSize / 2), pointSize, pointSize);
  217. //下侧描点区域
  218. rectBottom = QRectF(int(width / 2 - pointSize / 2), height - pointSize, pointSize, pointSize);
  219. //左上角描点区域
  220. rectLeftTop = QRectF(0, 0, pointSize, pointSize);
  221. //右上角描点区域
  222. rectRightTop = QRectF(int(width - pointSize), 0, pointSize, pointSize);
  223. //左下角描点区域
  224. rectLeftBottom = QRectF(0, int(height - pointSize), pointSize, pointSize);
  225. //右下角描点区域
  226. rectRightBottom = QRectF(width - pointSize, height - pointSize, pointSize, pointSize);
  227. }
  228. void SelectWidget::mouseMoveEvent(QMouseEvent *e)
  229. {
  230. // qDebug() << "SelectWidget::mouseMoveEvent";
  231. //计算当前鼠标位置是否在某个区域内,自动更新鼠标形状
  232. QPoint p = e->pos();
  233. if (rectLeft.contains(p)) {
  234. this->setCursor(Qt::SizeHorCursor);
  235. } else if (rectTop.contains(p)) {
  236. this->setCursor(Qt::SizeVerCursor);
  237. } else if (rectRight.contains(p)) {
  238. this->setCursor(Qt::SizeHorCursor);
  239. } else if (rectBottom.contains(p)) {
  240. this->setCursor(Qt::SizeVerCursor);
  241. } else if (rectLeftTop.contains(p)) {
  242. this->setCursor(Qt::SizeFDiagCursor);
  243. } else if (rectRightTop.contains(p)) {
  244. this->setCursor(Qt::SizeBDiagCursor);
  245. } else if (rectLeftBottom.contains(p)) {
  246. this->setCursor(Qt::SizeBDiagCursor);
  247. } else if (rectRightBottom.contains(p)) {
  248. this->setCursor(Qt::SizeFDiagCursor);
  249. } else {
  250. this->setCursor(Qt::ArrowCursor);
  251. }
  252. }
  253. void SelectWidget::paintEvent(QPaintEvent *)
  254. {
  255. if (!drawPoint) {
  256. return;
  257. }
  258. QPainter painter(this);
  259. painter.setRenderHints(QPainter::Antialiasing);
  260. painter.setPen(Qt::NoPen);
  261. painter.setBrush(pointColor);
  262. if (pointStyle == PointStyle::PointStyle_Rect)
  263. {
  264. drawRect(&painter);
  265. } else if (pointStyle == PointStyle:: PointStyle_Circle)
  266. {
  267. drawCircle(&painter);
  268. }
  269. if (borderWidth > 0)
  270. {
  271. drawBorder(&painter);
  272. }
  273. }
  274. void SelectWidget::drawRect(QPainter *painter)
  275. {
  276. //逐个绘制 左上角点+顶边中间点+右上角点+左边中间点+右边中间点+左下角点+底边中间点+右下角点
  277. painter->save();
  278. painter->drawRect(rectLeft);
  279. painter->drawRect(rectRight);
  280. painter->drawRect(rectTop);
  281. painter->drawRect(rectBottom);
  282. painter->drawRect(rectLeftTop);
  283. painter->drawRect(rectRightTop);
  284. painter->drawRect(rectLeftBottom);
  285. painter->drawRect(rectRightBottom);
  286. painter->restore();
  287. }
  288. void SelectWidget::drawCircle(QPainter *painter)
  289. {
  290. //逐个绘制 左上角点+顶边中间点+右上角点+左边中间点+右边中间点+左下角点+底边中间点+右下角点
  291. painter->save();
  292. painter->drawEllipse(rectLeft);
  293. painter->drawEllipse(rectRight);
  294. painter->drawEllipse(rectTop);
  295. painter->drawEllipse(rectBottom);
  296. painter->drawEllipse(rectLeftTop);
  297. painter->drawEllipse(rectRightTop);
  298. painter->drawEllipse(rectLeftBottom);
  299. painter->drawEllipse(rectRightBottom);
  300. painter->restore();
  301. }
  302. void SelectWidget::drawBorder(QPainter *painter)
  303. {
  304. painter->save();
  305. QPen pen;
  306. pen.setWidth(borderWidth);
  307. pen.setColor(pointColor);
  308. painter->setPen(pen);
  309. painter->setBrush(Qt::NoBrush);
  310. QRectF borderRect( int( pointSize / 2), int(pointSize / 2), int(width() - pointSize), int (height() - pointSize));
  311. painter->drawRect(borderRect);
  312. painter->restore();
  313. }
  314. bool SelectWidget::getDrawPoint() const
  315. {
  316. return this->drawPoint;
  317. }
  318. int SelectWidget::getPadding() const
  319. {
  320. return this->padding;
  321. }
  322. int SelectWidget::getBorderWidth() const
  323. {
  324. return this->borderWidth;
  325. }
  326. int SelectWidget::getPointSize() const
  327. {
  328. return this->pointSize;
  329. }
  330. QColor SelectWidget::getPointColor() const
  331. {
  332. return this->pointColor;
  333. }
  334. SelectWidget::PointStyle SelectWidget::getPointStyle() const
  335. {
  336. return this->pointStyle;
  337. }
  338. QWidget *SelectWidget::getWidget() const
  339. {
  340. return widget;
  341. }
  342. QSize SelectWidget::sizeHint() const
  343. {
  344. return QSize(200, 200);
  345. }
  346. QSize SelectWidget::minimumSizeHint() const
  347. {
  348. return QSize(30, 30);
  349. }
  350. void SelectWidget::setDrawPoint(bool drawPoint)
  351. {
  352. if (this->drawPoint != drawPoint) {
  353. this->drawPoint = drawPoint;
  354. update();
  355. }
  356. }
  357. void SelectWidget::setPadding(int padding)
  358. {
  359. if (this->padding != padding) {
  360. this->padding = padding;
  361. update();
  362. }
  363. }
  364. void SelectWidget::setBorderWidth(int borderWidth)
  365. {
  366. if (this->borderWidth != borderWidth) {
  367. this->borderWidth = borderWidth;
  368. update();
  369. }
  370. }
  371. void SelectWidget::setPointSize(int pointSize)
  372. {
  373. if (this->pointSize != pointSize) {
  374. this->pointSize = pointSize;
  375. update();
  376. }
  377. }
  378. void SelectWidget::setPointColor(const QColor &pointColor)
  379. {
  380. if (this->pointColor != pointColor) {
  381. this->pointColor = pointColor;
  382. update();
  383. }
  384. }
  385. void SelectWidget::setPointStyle(const SelectWidget::PointStyle &pointStyle)
  386. {
  387. if (this->pointStyle != pointStyle) {
  388. this->pointStyle = pointStyle;
  389. update();
  390. }
  391. }
  392. void SelectWidget::setWidget(QWidget *widget)
  393. {
  394. this->widget = widget;
  395. this->widget->setVisible(true);
  396. this->setVisible(true);
  397. //设置最小尺寸
  398. this->setMinimumSize(30, 30);
  399. //设置当前窗体大小为跟随窗体的大小增加部分
  400. this->resize(this->widget->size() + QSize(padding * 2, padding * 2));
  401. //将当前窗体移到偏移位置
  402. this->move(this->widget->pos() - QPoint(padding, padding));
  403. }