经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
Qt 圆角按钮,面版自动布局
来源:cnblogs  作者:凉天满月  时间:2021/5/24 10:58:26  对本文有异议

一、前言

  在部分界面开发中,有时需要动态添加控件或按钮到面板中,在不需要时又需要删除该控件,故模仿视频开发中的设置屏蔽词,通过自己绘制的按钮与排布面板控件实现。

  实现效果如下:

  

  说明:

  1、输入框可设置背景色、圆角角度、颜色高亮等

  2、采用圆角输入框输入字符,回车或点击“添加”可触发信号,获取输入字符串

  3、字符以圆角按钮控件显示,点击“X”可删除该按钮

  4、面版自动排布,删除中间的圆角按钮,后续的会往前移

  5、添加的屏蔽词都放在后面,已有屏蔽词会提示已存在,删除屏蔽词后可再次添加

二、实现过程

  1、运行环境Qt5.5 VS2013

  2、制作圆角按钮

  1)继承QWidget,封装KeyButton控件

  1. 1 #ifndef KEYBUTTON
  2. 2 #define KEYBUTTON
  3. 3
  4. 4 #include <QEvent>
  5. 5 #include <QWidget>
  6. 6 #include <QMouseEvent>
  7. 7 #include <QResizeEvent>
  8. 8
  9. 9 class KeyButton : public QWidget
  10. 10 {
  11. 11 Q_OBJECT
  12. 12
  13. 13 public:
  14. 14 KeyButton(QWidget *parent = 0);
  15. 15
  16. 16 public:
  17. 17 void setBorderColor(const QString &);
  18. 18 void setHoverColor(const QString &);
  19. 19
  20. 20 void setText(const QString &);
  21. 21 QString getText();
  22. 22
  23. 23 signals:
  24. 24 void closeSig();
  25. 25
  26. 26 protected:
  27. 27 bool eventFilter(QObject *, QEvent *);
  28. 28 void paintEvent(QPaintEvent *event);
  29. 29 void leaveEvent(QEvent *);
  30. 30 void resizeEvent(QResizeEvent *);
  31. 31 void mouseReleaseEvent(QMouseEvent *e);
  32. 32 void mouseMoveEvent(QMouseEvent *e);
  33. 33
  34. 34 private:
  35. 35 void drawIcon(QPainter *painter, const QRect &rect, int icon);
  36. 36
  37. 37 private:
  38. 38 bool m_IsHover;
  39. 39 QString bgColor; //背景色
  40. 40 QString borderColor; //边框颜色
  41. 41 QString hoverColor; //高亮字体颜色
  42. 42 QString text; //字体文本
  43. 43 QString textColor; //文本正常颜色
  44. 44 int padding; //左侧右侧间距
  45. 45 int iconSize; //图标大小
  46. 46 QRect rightRect; //右侧图标区域
  47. 47 bool pressed; //鼠标是否按下
  48. 48 QPoint lastPoint; //鼠标按下处的坐标
  49. 49
  50. 50 QPoint m_Point;
  51. 51 QPixmap m_Pixmap;
  52. 52 };
  53. 53
  54. 54 #endif // KEYBUTTON
圆角按钮

  2)重写paintEvent事件,绘制按钮圆角按钮,包括字符

  1. 1 void KeyButton::paintEvent(QPaintEvent *event)
  2. 2 {
  3. 3 QPainter painter(this);
  4. 4 painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
  5. 5
  6. 6 //绘制背景+边框
  7. 7 painter.setPen(borderColor);
  8. 8 painter.setBrush(QColor(bgColor));
  9. 9 int min = qMin(this->rect().width(), this->rect().height());
  10. 10 int radius = min / 2;
  11. 11 //画圆角矩形
  12. 12 QPainterPath path;
  13. 13 QRect rect = this->rect();
  14. 14 path.moveTo(rect.bottomRight() - QPointF(0, radius));
  15. 15 path.lineTo(rect.topRight() + QPointF(0, radius));
  16. 16 path.arcTo(QRectF(QPointF(rect.topRight() - QPointF(radius * 2, 0)), QSize(radius * 2, radius *2)), 0, 90);
  17. 17 path.lineTo(rect.topLeft() + QPointF(radius, 0));
  18. 18 path.arcTo(QRectF(QPointF(rect.topLeft()), QSize(radius * 2, radius * 2)), 90, 90);
  19. 19 path.lineTo(rect.bottomLeft() - QPointF(0, radius));
  20. 20 path.arcTo(QRectF(QPointF(rect.bottomLeft() - QPointF(0, radius * 2)), QSize(radius * 2, radius * 2)), 180, 90);
  21. 21 path.lineTo(rect.bottomLeft() + QPointF(radius, 0));
  22. 22 path.arcTo(QRectF(QPointF(rect.bottomRight() - QPointF(radius * 2, radius * 2)), QSize(radius * 2, radius * 2)), 270, 90);
  23. 23 painter.drawPath(path);
  24. 24
  25. 25 QFont font = qApp->font();
  26. 26 font.setPixelSize(12);
  27. 27 painter.setFont(font);
  28. 28
  29. 29 //绘制文字
  30. 30 if (!text.isEmpty())
  31. 31 {
  32. 32 if(m_IsHover)
  33. 33 painter.setPen(hoverColor);
  34. 34 else
  35. 35 painter.setPen(textColor);
  36. 36 QRect textRect(padding * 1.5, 0, this->width(), this->height());
  37. 37 painter.drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text);
  38. 38 }
  39. 39 //绘制右侧图标
  40. 40 font.setPixelSize(15);
  41. 41 painter.setFont(font);
  42. 42 painter.drawText(rightRect, Qt::AlignHCenter | Qt::AlignVCenter, "X");
  43. 43 }
绘制事件

  3)继承resizeEvent事件,计算“X”的绘制位置

  1. 1 void KeyButton::resizeEvent(QResizeEvent *)
  2. 2 {
  3. 3 //重新计算图标位置区域
  4. 4 int height = this->height() / 2 - m_Pixmap.height() / 2;
  5. 5 m_Point = QPoint(this->width() - (iconSize * 1) - padding, height);
  6. 6 rightRect = QRect(this->width() - (iconSize * 1) - padding, 0, iconSize, this->height());
  7. 7 }
绘制位置

  4)继承mouseReleaseEvent事件,用户点击“X”后触发删除信号

  1. 1 void KeyButton::mouseReleaseEvent(QMouseEvent *e)
  2. 2 {
  3. 3 pressed = true;
  4. 4 lastPoint = e->pos();
  5. 5 this->update();
  6. 6
  7. 7 if (rightRect.contains(lastPoint))
  8. 8 emit closeSig();
  9. 9 }
信号触发

  3、面板自动布局

  1)继承QWidget,自定义PanelWidget控件

  1. 1 #ifndef PANEL_WIDGET_H
  2. 2 #define PANEL_WIDGET_H
  3. 3
  4. 4 #include <QWidget>
  5. 5
  6. 6 class QScrollArea;
  7. 7 class QFrame;
  8. 8 class QVBoxLayout;
  9. 9 class QGridLayout;
  10. 10 class QSpacerItem;
  11. 11
  12. 12 class PanelWidget : public QWidget
  13. 13 {
  14. 14 Q_OBJECT
  15. 15 public:
  16. 16 explicit PanelWidget(QWidget *parent = 0);
  17. 17
  18. 18 protected:
  19. 19 void resizeEvent(QResizeEvent *);
  20. 20 void showEvent(QShowEvent *event);
  21. 21
  22. 22 public:
  23. 23 QSize sizeHint() const;
  24. 24 QSize minimumSizeHint() const;
  25. 25
  26. 26 void setWidgets(QList<QWidget *> widgets);
  27. 27 void setWidget(QWidget *widget);
  28. 28 void delWidget(QWidget *widget);
  29. 29 void setColumnCount(int nColumn);
  30. 30 void setMargin(int left, int top, int right, int bottom);
  31. 31 void setMargin(int margin);
  32. 32 void setSpacing(int space);
  33. 33 void resetLayout();
  34. 34
  35. 35 private:
  36. 36 void initFrom();
  37. 37 void hideWidget();
  38. 38 void showPanel();
  39. 39
  40. 40 private:
  41. 41 QList<QWidget *> m_widgets;
  42. 42 int m_nColumn{ 0 };
  43. 43
  44. 44 private:
  45. 45 QScrollArea *scrollArea;
  46. 46 QWidget *scrollAreaWidgetContents;
  47. 47 QFrame *frame;
  48. 48 QVBoxLayout *verticalLayout;
  49. 49 QGridLayout *gridLayout;
  50. 50
  51. 51 QSpacerItem *m_HorizontalSpacer;
  52. 52 QSpacerItem *m_VerticalSpacer;
  53. 53
  54. 54 bool m_IsShow;
  55. 55 };
  56. 56
  57. 57 #endif // PANEL_WIDGET_H
面版类

  2)考虑增加的控件可能比较多,采用QScrollArea控件(存储不下时可左右拉动显示)

  1. 1 void PanelWidget::initFrom()
  2. 2 {
  3. 3 scrollArea = new QScrollArea(this);
  4. 4 scrollArea->setObjectName("scrollAreaMain");
  5. 5 scrollArea->setWidgetResizable(true);
  6. 6
  7. 7 scrollAreaWidgetContents = new QWidget();
  8. 8 scrollAreaWidgetContents->setGeometry(QRect(0, 0, 100, 100));
  9. 9 scrollAreaWidgetContents->setStyleSheet("border:none;");
  10. 10
  11. 11 verticalLayout = new QVBoxLayout(scrollAreaWidgetContents);
  12. 12 verticalLayout->setSpacing(0);
  13. 13 verticalLayout->setContentsMargins(0, 0, 0, 0);
  14. 14
  15. 15 frame = new QFrame(scrollAreaWidgetContents);
  16. 16 frame->setObjectName("panelWidget");
  17. 17
  18. 18 gridLayout = new QGridLayout(frame);
  19. 19 gridLayout->setSpacing(6);
  20. 20
  21. 21 verticalLayout->addWidget(frame);
  22. 22 scrollArea->setWidget(scrollAreaWidgetContents);
  23. 23 }
创建面板

  3)通过setWidget和setWidgets,更新面板内的控件

  1. 1 void PanelWidget::setWidgets(QList<QWidget *> widgets)
  2. 2 {
  3. 3 m_widgets = widgets;
  4. 4 //先清空原有所有元素
  5. 5 QList<QWidget *> widgetList = frame->findChildren<QWidget *>();
  6. 6 foreach(QWidget *w, widgetList)
  7. 7 w->hide();
  8. 8
  9. 9 resetLayout();
  10. 10 }
  11. 11
  12. 12 void PanelWidget::setWidget(QWidget *widget)
  13. 13 {
  14. 14 if (!m_widgets.contains(widget))
  15. 15 {
  16. 16 m_widgets << widget;
  17. 17 resetLayout();
  18. 18 }
  19. 19 }
面板更新

  4)更新面版内容后,通过QGridLayout更新控件的布局

  1. 1 void PanelWidget::resetLayout()
  2. 2 {
  3. 3 int row = 0;
  4. 4 int column = 0;
  5. 5 int index = 0;
  6. 6
  7. 7 for (QWidget *widget : m_widgets)
  8. 8 {
  9. 9 gridLayout->addWidget(widget, row, column);
  10. 10 widget->setVisible(true);
  11. 11 column++;
  12. 12 index++;
  13. 13
  14. 14 if (index % m_nColumn == 0) {
  15. 15 row++;
  16. 16 column = 0;
  17. 17 }
  18. 18 }
  19. 19 if (NULL == m_HorizontalSpacer)
  20. 20 m_HorizontalSpacer = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum);
  21. 21 if(1 == m_widgets.count())
  22. 22 gridLayout->addItem(m_HorizontalSpacer, 0, m_nColumn);
  23. 23 row++;
  24. 24 if (NULL == m_VerticalSpacer)
  25. 25 m_VerticalSpacer = new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding);
  26. 26 gridLayout->addItem(m_VerticalSpacer, row, 0);
  27. 27 }
面板布局

 

原文链接:http://www.cnblogs.com/liangtianmanyue/p/14802377.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号