Qt 圆角按钮,面版自动布局
一、前言
在部分界面开发中,有时需要动态添加控件或按钮到面板中,在不需要时又需要删除该控件,故模仿视频开发中的设置屏蔽词,通过自己绘制的按钮与排布面板控件实现。
实现效果如下:
说明:
1、输入框可设置背景色、圆角角度、颜色高亮等
2、采用圆角输入框输入字符,回车或点击“添加”可触发信号,获取输入字符串
3、字符以圆角按钮控件显示,点击“X”可删除该按钮
4、面版自动排布,删除中间的圆角按钮,后续的会往前移
5、添加的屏蔽词都放在后面,已有屏蔽词会提示已存在,删除屏蔽词后可再次添加
二、实现过程
1、运行环境Qt5.5 VS2013
2、制作圆角按钮
1)继承QWidget,封装KeyButton控件


1 #ifndef KEYBUTTON
2 #define KEYBUTTON
3
4 #include <QEvent>
5 #include <QWidget>
6 #include <QMouseEvent>
7 #include <QResizeEvent>
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 <QWidget>
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<QWidget *> widgets);
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<QWidget *> m_widgets;
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<QWidget *> widgets)
2 {
3 m_widgets = widgets;
4 //先清空原有所有元素
5 QList<QWidget *> widgetList = frame->findChildren<QWidget *>();
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 }
面板布局
Qt 圆角按钮,面版自动布局的更多相关文章
- Qt设置按钮为圆形
通过Qt 的样式表实现圆形按钮,其也可以实现圆角按钮,当然也可以使用其他的方式,比如说,通过派生按钮类使用绘图事件,进行一个图形的绘制,或者是通过自定义一个类,通过信号与槽的机制与绘图事件的配合也能实 ...
- android 圆角按钮和按钮颜色
1. android 设置圆角按钮后,按下按钮后,还能改变按钮的颜色 <?xml version="1.0" encoding="UTF-8"?> ...
- win10 uwp 圆角按钮
本文讲的是如何做圆角按钮,我们在UWP本来的按钮都是矩形,圆角Radius没有,所以本文就用简单方法去做圆角按钮. 我们按钮需要圆角,而自带没有,其实做一个很简单,把原来的按钮变为背景透明,然后使用矩 ...
- iOS中创建自定义的圆角按钮
iOS中很多时候都需要用到指定风格的圆角按钮,尽管UIButton提供了一个方式创建圆角按钮: + (id)buttonWithType:(UIButtonType)buttonType;//指定bu ...
- Qt浮动按钮的实现(使用窗口背景透明、实现只显示浮动按钮的目的)
Qt浮动按钮的实现 效果如下: 图3 估计很多做Qt有一定经验的朋友会觉得这个效果不难,但是这是一个需求奇葩的实际业务中做出的效果.笔者会想讲下客户的需求和整体框架的矛盾. 整个项目主要是由Qt搭建的 ...
- xamarin UWP自定义圆角按钮
uwp自带的button本身不支持圆角属性,所以要通过自定义控件实现. 通过设置Button的Background=“{x:Null}”设置为Null使背景为空,再设置Button.Content中的 ...
- Android Shape自定义纯色圆角按钮
版权声明:分享技术,传播快乐.如果本博客对你有帮助,请在我的博客首页为我打赏吧! 在Android开发中,为响应美化应用中控件的效果,使用Shape定义图形效果,可以解决图片过多的问题. 首先看一下效 ...
- android 带边框的圆角按钮
新建buttonstyle.xml 代码如下 <?xml version="1.0" encoding="UTF-8"?> <layer-li ...
- 无需图片,使用CSS3实现圆角按钮[转]
首先来看看效果: 事例HTML代码: <a href="#" class="button green">button</a> < ...
随机推荐
- shell脚本 4 函数与正则
shell函数 shell中允许将一组命令集合或语句形成一段可用代码,这些代码块称为shell函数.给这段代码起个名字称为函数名,后续可以直接调用该段代码. 格式 func() { #指定函数名 ...
- matlab map容器类型
matlab map容器类型 map容器类型以及map类概述 map是将一个量映射到另一个量上,此是前面的量就是map的键(key),后面的量就是map的数据(value).map的键和对应的数据都储 ...
- vim 中文乱码解决
问题如下: 在vim中编辑一个中文文本时 出现中文乱码情况 问题解决: 修改vimrc的脚本配置 编辑~/.vimrc文件,加上如下几行即可: set fileencodings=utf-8,ucs- ...
- Average Score39届亚洲赛牡丹江站A题
题意: A班有n个人,B班有m个人,然后现在给你n-1个A班人的成绩,和m个B班人的成绩,然后题目要求求出A班剩下的没给成绩那个人的成绩范围,要求是这个人从A班转到B班后能使A,B的平均分 ...
- POJ1611基础带权并查集
题意: 有一个人生病了,和他一个社团或者间接和他有联系的人都会生病,问一共有多少人生病了. 思路: 比较简单和基础的题,带权并查集中的一种,就是记录更新集合元素个数,这个题目我 ...
- JSON对象与字符串的互换——JSON.parse()和JSON.stringify()
parse用于从一个字符串中解析出json对象,如 var str = '{"name":"huangxiaojian","age":&qu ...
- 【js】Leetcode每日一题-解码异或后数组
[js]Leetcode每日一题-解码异或后数组 [题目描述] 未知 整数数组 arr 由 n 个非负整数组成. 经编码后变为长度为 n - 1 的另一个整数数组 encoded ,其中 encode ...
- 【SpringMVC】添加操作时返回400
本博客老魏原创,如需转载请留言 问题描述: springmvc向数据库添加新的记录时,发生400错误,控制台没有抛出异常. 问题原因: 视图中的提交数据的某一个字段不不匹配导致. 解决方法: 不要怀疑 ...
- 在 Linux 如何优雅的统计程序运行时间?恕我直言,你运行的可能是假 time
最近在使用 time 命令时,无意间发现了一些隐藏的小秘密和强大功能,今天分享给大家. time 在 Linux 下是比较常用的命令,可以帮助我们方便的计算程序的运行时间,对比采用不同方案时程序的运行 ...
- .NET平台系列5 .NET Core 简介
系列目录 [已更新最新开发文章,点击查看详细] 自1995年互联网战略日以来最雄心勃勃的事业 -- 微软.NET战略, 2000年6月30日. 微软公司于2002年2月13日正式推出第一代.N ...