一、前言
在部分界面开发中,有时需要动态添加控件或按钮到面板中,在不需要时又需要删除该控件,故模仿视频开发中的设置屏蔽词,通过自己绘制的按钮与排布面板控件实现。
实现效果如下:
说明:
1、输入框可设置背景色、圆角角度、颜色高亮等
2、采用圆角输入框输入字符,回车或点击“添加”可触发信号,获取输入字符串
3、字符以圆角按钮控件显示,点击“X”可删除该按钮
4、面版自动排布,删除中间的圆角按钮,后续的会往前移
5、添加的屏蔽词都放在后面,已有屏蔽词会提示已存在,删除屏蔽词后可再次添加
二、实现过程
1、运行环境Qt5.5 VS2013
2、制作圆角按钮
1)继承QWidget,封装KeyButton控件
1 #ifndef KEYBUTTON
2 #define KEYBUTTON
3
4 #include
5 #include
6 #include
7 #include
8
9 class KeyButton : public QWidget
10 {
11 Q_OBJECT
12
13 public:
14 KeyButton(QWidget *parent = 0);
15
16 public:
17 void setBorderColor(const QString &);
18 void setHoverColor(const QString &);
19
20 void setText(const QString &);
21 QString getText();
22
23 signals:
24 void closeSig();
25
26 protected:
27 bool eventFilter(QObject *, QEvent *);
28 void paintEvent(QPaintEvent *event);
29 void leaveEvent(QEvent *);
30 void resizeEvent(QResizeEvent *);
31 void mouseReleaseEvent(QMouseEvent *e);
32 void mouseMoveEvent(QMouseEvent *e);
33
34 private:
35 void drawIcon(QPainter *painter, const QRect &rect, int icon);
36
37 private:
38 bool m_IsHover;
39 QString bgColor; //背景色
40 QString borderColor; //边框颜色
41 QString hoverColor; //高亮字体颜色
42 QString text; //字体文本
43 QString textColor; //文本正常颜色
44 int padding; //左侧右侧间距
45 int iconSize; //图标大小
46 QRect rightRect; //右侧图标区域
47 bool pressed; //鼠标是否按下
48 QPoint lastPoint; //鼠标按下处的坐标
49
50 QPoint m_Point;
51 QPixmap m_Pixmap;
52 };
53
54 #endif // KEYBUTTON
圆角按钮
2)重写paintEvent事件,绘制按钮圆角按钮,包括字符
1 void KeyButton::paintEvent(QPaintEvent *event)
2 {
3 QPainter painter(this);
4 painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
5
6 //绘制背景+边框
7 painter.setPen(borderColor);
8 painter.setBrush(QColor(bgColor));
9 int min = qMin(this->rect().width(), this->rect().height());
10 int radius = min / 2;
11 //画圆角矩形
12 QPainterPath path;
13 QRect rect = this->rect();
14 path.moveTo(rect.bottomRight() - QPointF(0, radius));
15 path.lineTo(rect.topRight() + QPointF(0, radius));
16 path.arcTo(QRectF(QPointF(rect.topRight() - QPointF(radius * 2, 0)), QSize(radius * 2, radius *2)), 0, 90);
17 path.lineTo(rect.topLeft() + QPointF(radius, 0));
18 path.arcTo(QRectF(QPointF(rect.topLeft()), QSize(radius * 2, radius * 2)), 90, 90);
19 path.lineTo(rect.bottomLeft() - QPointF(0, radius));
20 path.arcTo(QRectF(QPointF(rect.bottomLeft() - QPointF(0, radius * 2)), QSize(radius * 2, radius * 2)), 180, 90);
21 path.lineTo(rect.bottomLeft() + QPointF(radius, 0));
22 path.arcTo(QRectF(QPointF(rect.bottomRight() - QPointF(radius * 2, radius * 2)), QSize(radius * 2, radius * 2)), 270, 90);
23 painter.drawPath(path);
24
25 QFont font = qApp->font();
26 font.setPixelSize(12);
27 painter.setFont(font);
28
29 //绘制文字
30 if (!text.isEmpty())
31 {
32 if(m_IsHover)
33 painter.setPen(hoverColor);
34 else
35 painter.setPen(textColor);
36 QRect textRect(padding * 1.5, 0, this->width(), this->height());
37 painter.drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text);
38 }
39 //绘制右侧图标
40 font.setPixelSize(15);
41 painter.setFont(font);
42 painter.drawText(rightRect, Qt::AlignHCenter | Qt::AlignVCenter, "X");
43 }
绘制事件
3)继承resizeEvent事件,计算“X”的绘制位置
1 void KeyButton::resizeEvent(QResizeEvent *)
2 {
3 //重新计算图标位置区域
4 int height = this->height() / 2 - m_Pixmap.height() / 2;
5 m_Point = QPoint(this->width() - (iconSize * 1) - padding, height);
6 rightRect = QRect(this->width() - (iconSize * 1) - padding, 0, iconSize, this->height());
7 }
绘制位置
4)继承mouseReleaseEvent事件,用户点击“X”后触发删除信号
1 void KeyButton::mouseReleaseEvent(QMouseEvent *e)
2 {
3 pressed = true;
4 lastPoint = e->pos();
5 this->update();
6
7 if (rightRect.contains(lastPoint))
8 emit closeSig();
9 }
信号触发
3、面板自动布局
1)继承QWidget,自定义PanelWidget控件
1 #ifndef PANEL_WIDGET_H
2 #define PANEL_WIDGET_H
3
4 #include
5
6 class QScrollArea;
7 class QFrame;
8 class QVBoxLayout;
9 class QGridLayout;
10 class QSpacerItem;
11
12 class PanelWidget : public QWidget
13 {
14 Q_OBJECT
15 public:
16 explicit PanelWidget(QWidget *parent = 0);
17
18 protected:
19 void resizeEvent(QResizeEvent *);
20 void showEvent(QShowEvent *event);
21
22 public:
23 QSize sizeHint() const;
24 QSize minimumSizeHint() const;
25
26 void setWidgets(QList
27 void setWidget(QWidget *widget);
28 void delWidget(QWidget *widget);
29 void setColumnCount(int nColumn);
30 void setMargin(int left, int top, int right, int bottom);
31 void setMargin(int margin);
32 void setSpacing(int space);
33 void resetLayout();
34
35 private:
36 void initFrom();
37 void hideWidget();
38 void showPanel();
39
40 private:
41 QList
42 int m_nColumn{ 0 };
43
44 private:
45 QScrollArea *scrollArea;
46 QWidget *scrollAreaWidgetContents;
47 QFrame *frame;
48 QVBoxLayout *verticalLayout;
49 QGridLayout *gridLayout;
50
51 QSpacerItem *m_HorizontalSpacer;
52 QSpacerItem *m_VerticalSpacer;
53
54 bool m_IsShow;
55 };
56
57 #endif // PANEL_WIDGET_H
面版类
2)考虑增加的控件可能比较多,采用QScrollArea控件(存储不下时可左右拉动显示)
1 void PanelWidget::initFrom()
2 {
3 scrollArea = new QScrollArea(this);
4 scrollArea->setObjectName("scrollAreaMain");
5 scrollArea->setWidgetResizable(true);
6
7 scrollAreaWidgetContents = new QWidget();
8 scrollAreaWidgetContents->setGeometry(QRect(0, 0, 100, 100));
9 scrollAreaWidgetContents->setStyleSheet("border:none;");
10
11 verticalLayout = new QVBoxLayout(scrollAreaWidgetContents);
12 verticalLayout->setSpacing(0);
13 verticalLayout->setContentsMargins(0, 0, 0, 0);
14
15 frame = new QFrame(scrollAreaWidgetContents);
16 frame->setObjectName("panelWidget");
17
18 gridLayout = new QGridLayout(frame);
19 gridLayout->setSpacing(6);
20
21 verticalLayout->addWidget(frame);
22 scrollArea->setWidget(scrollAreaWidgetContents);
23 }
创建面板
3)通过setWidget和setWidgets,更新面板内的控件
1 void PanelWidget::setWidgets(QList
2 {
3 m_widgets = widgets;
4 //先清空原有所有元素
5 QList
6 foreach(QWidget *w, widgetList)
7 w->hide();
8
9 resetLayout();
10 }
11
12 void PanelWidget::setWidget(QWidget *widget)
13 {
14 if (!m_widgets.contains(widget))
15 {
16 m_widgets << widget;
17 resetLayout();
18 }
19 }
面板更新
4)更新面版内容后,通过QGridLayout更新控件的布局
1 void PanelWidget::resetLayout()
2 {
3 int row = 0;
4 int column = 0;
5 int index = 0;
6
7 for (QWidget *widget : m_widgets)
8 {
9 gridLayout->addWidget(widget, row, column);
10 widget->setVisible(true);
11 column++;
12 index++;
13
14 if (index % m_nColumn == 0) {
15 row++;
16 column = 0;
17 }
18 }
19 if (NULL == m_HorizontalSpacer)
20 m_HorizontalSpacer = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum);
21 if(1 == m_widgets.count())
22 gridLayout->addItem(m_HorizontalSpacer, 0, m_nColumn);
23 row++;
24 if (NULL == m_VerticalSpacer)
25 m_VerticalSpacer = new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding);
26 gridLayout->addItem(m_VerticalSpacer, row, 0);
27 }
面板布局
手机扫一扫
移动阅读更方便
你可能感兴趣的文章