前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Qt】QSS

【Qt】QSS

作者头像
YoungMLet
发布2024-08-15 14:37:27
940
发布2024-08-15 14:37:27
举报
文章被收录于专栏:C++/Linux

一、QSS

1. QSS

对于 QSS 来说, 基本的语法结构非常简单:

代码语言:javascript
复制
			选择器 {
			 	属性名: 属性值; 
			}

其中:

  • 选择器 描述了 “哪个 widget 要应⽤样式规则”.
  • 属性 则是⼀个键值对, 属性名表⽰要设置哪种样式, 属性值表⽰了设置的样式的值.

例如:

代码语言:javascript
复制
			QPushButton { color: red; }

上述代码的含义表示,针对界⾯上所有的 QPushButton , 都把⽂本颜⾊设置为红色。

代码示例: QSS 基本使用:

代码语言:javascript
复制
			1 Widget::Widget(QWidget *parent)
			2 : QWidget(parent)
			3 , ui(new Ui::Widget)
			4 {
			5 		ui->setupUi(this);
			6
			7 		ui->pushButton->setStyleSheet("QPushButton { color: red; }");
			8 }

2. QSS 设置方式

(1)指定控件样式设置

QWidget 中包含了 setStyleSheet ⽅法, 可以直接设置样式。上述代码我们已经演⽰了上述设置⽅式。

另⼀⽅⾯, 给指定控件设置样式之后, 该控件的⼦元素也会受到影响。

代码⽰例: ⼦元素受到影响

在界⾯上创建⼀个按钮

修改 widget.cpp, 这次我们不再给按钮设置样式, ⽽是给 Widget 设置样式 (Widget 是 QPushButton 的⽗控件).

代码语言:javascript
复制
 			Widget::Widget(QWidget *parent)
 			 : QWidget(parent)
 			 , ui(new Ui::Widget)
 			{
 				 ui->setupUi(this);
 				 // 给 Widget 本⾝设置样式.
 				 this->setStyleSheet("QWidget { color: red;} ");
 			}

运⾏程序, 可以看到样式对于⼦控件按钮同样会⽣效.

(2)全局样式设置

还可以通过 QApplicationsetStyleSheet ⽅法设置整个程序的全局样式. 全局样式优点:

  • 使同⼀个样式针对多个控件⽣效, 代码更简洁.
  • 所有控件样式内聚在⼀起, 便于维护和问题排查

代码⽰例1: 使⽤全局样式

在界⾯上创建三个按钮.

编辑 main.cpp, 设置全局样式

代码语言:javascript
复制
 		int main(int argc, char *argv[])
 		{
 			 QApplication a(argc, argv);
 			 // 设置全局样式
 			 a.setStyleSheet("QPushButton { color: red; }");
 			 Widget w;
 			 w.show();
 			 return a.exec();
 		}

运⾏程序, 可以看到此时三个按钮的颜⾊都设置为红⾊了.

代码⽰例2: 样式的层叠特性

如果通过全局样式给某个控件设置了属性1, 通过指定控件样式给控件设置属性2, 那么这两个属性都会产⽣作⽤.

在界⾯上创建两个按钮

编写 main.cpp, 设置全局样式, 把按钮⽂本设置为红⾊

代码语言:javascript
复制
 		int main(int argc, char *argv[])
 		{
 			 QApplication a(argc, argv);
 			 // 设置全局样式
 			 a.setStyleSheet("QPushButton { color: red; }");
 			 Widget w;
 			 w.show();
 			 return a.exec();
 		}

编写 widget.cpp, 给第⼀个按钮设置字体⼤⼩.

代码语言:javascript
复制
 		Widget::Widget(QWidget *parent)
 		 : QWidget(parent)
 		 , ui(new Ui::Widget)
 		{
 			ui->setupUi(this);
 			
 			// 设置指定控件样式
 			ui->pushButton->setStyleSheet("QPushButton { font-size: 50px} ");
 		}

运⾏程序, 可以看到, 对于第⼀个按钮来说, 同时具备了颜⾊和字体⼤⼩样式. ⽽第⼆个按钮只有颜⾊样式.说明针对第⼀个按钮, 两种设置⽅式设置的样式, 叠加起来了.

注意:如果全局样式, 和指定控件样式冲突, 则指定控件样式优先展⽰.

(3)从文件加载样式表

上述代码都是把样式通过硬编码的⽅式设置的. 这样使 QSS 代码和 C++ 代码耦合在⼀起了, 并不⽅便代码的维护.

因此更好的做法是把样式放到单独的⽂件中, 然后通过读取⽂件的⽅式来加载样式.

代码⽰例: 从⽂件加载全局样式:

  1. 在界⾯上创建⼀个按钮
  2. 创建 resource.qrc ⽂件, 并设定前缀为 / .
  3. 创建 style.qss ⽂件, 并添加到 resource.qrc 中.
  • style.qss 是需要程序运⾏时加载的. 为了规避绝对路径的问题, 仍然使⽤ qrc 的⽅式来组 织 (即把资源⽂件内容打包到 cpp 代码中).
  • Qt Creator 没有提供创建 qss ⽂件的选项. 咱们直接 右键 -> 新建⽂件 -> ⼿动设置⽂件扩展名 为 qss 即可.

使⽤ Qt Creator 打开 style.qss , 编写内容:

代码语言:javascript
复制
 		QPushButton {
 		 color: red;
 		}

修改 main.cpp, 新增⼀个函数⽤来加载样式

代码语言:javascript
复制
 		QString loadQSS() {
 			 QFile file(":/style.qss");
 			 // 打开⽂件
 			 file.open(QFile::ReadOnly);
 			 // 读取⽂件内容. 虽然 readAll 返回的是 QByteArray, 但是 QString 提供了QByteArray 版本的构造函数.
 			 QString style = file.readAll();
 			 // 关闭⽂件
 			 file.close();
 			 return style;
 		}

修改 main.cpp, 在 main 函数中调⽤上述函数, 并设置样式.

代码语言:javascript
复制
 		int main(int argc, char *argv[])
 		{
 			 QApplication a(argc, argv);
 			 // 调⽤上述函数加载样式
 			 const QString& style = loadQSS();
 			 a.setStyleSheet(style);
 			 Widget w;
 			 w.show();
 			 return a.exec();
 		}

运⾏程序, 可以看到样式已经⽣效了.

(4)使用 Qt Designer 编辑样式

QSS 也可以通过 Qt Designer 直接编辑, 从⽽起到实时预览的效果. 同时也能避免 C++ 和 QSS 代码的耦合.

代码⽰例: 使⽤ Qt Designer 编辑样式

  1. 在界⾯上创建⼀个按钮
  1. 右键按钮, 选择 “改变样式表”
  1. 在弹出的样式表编辑器中, 可以直接填写样式. 填写完毕, 点击 OK 即可.
  1. 此时 Qt Designer 的预览界⾯就会实时显⽰出样式的变化.

3. 选择器

(1)选择器介绍

代码示例:使⽤ id 选择器

  1. 在界⾯上创建 3 个按钮, objectName 为 pushButton , pushButton_2 , pushButton_3
  1. 编写 main.cpp, 设置全局样式

先通过 QPushButton 设置所有的按钮为⻩⾊.

再通过 #pushButton 和 #pushButton_2 分别设置这两个按钮为红⾊和绿⾊.

代码语言:javascript
复制
  		int main(int argc, char *argv[])
  		{
  			 QApplication a(argc, argv);
  			 // 设置全局样式
  			 QString style = "";
  			 style += "QPushButton { color: yellow; }";
  			 style += "#pushButton { color: red; }";
  			 style += "#pushButton_2 { color: green; }";
  			 a.setStyleSheet(style);
  			 Widget w;
  			 w.show();
  			 return a.exec();
  		}
  1. 执⾏程序, 观察效果
(2)子控件选择器 (Sub-Controls)

有些控件内部包含了多个 “⼦控件” . ⽐如 QComboBox 的下拉后的⾯板, ⽐如 QSpinBox 的上下按钮等.

可以通过⼦控件选择器 :: , 针对上述⼦控件进⾏样式设置

代码⽰例: 修改进度条的颜⾊

  1. 在界⾯上创建⼀个进度条.
  1. 在 Qt Designer 右侧的属性编辑器中, 找到 QWidget 的 styleSheet 属性.

编辑如下内容:

其中的 chunk 是选中进度条中的每个 “块” . 使⽤ QProgressBar::text 则可以选中⽂本.

代码语言:javascript
复制
			QProgressBar::chunk {background-color: #FF0000;}

同时把 QProcessBar 的 alignment 属性设置为垂直⽔平居中.

  • 此处如果不设置 alignment , 进度条中的数字会跑到左上⻆. 这个怀疑是 Qt 本⾝的 bug, 暂时只能先使⽤ alignment 来⼿动调整下.
  1. 执⾏程序, 可以看到如下效果. 我们就得到了⼀个红⾊的进度条.

通过上述⽅式, 也可以修改⽂字的颜⾊, 字体⼤⼩等样式。

(3)伪类选择器 (Pseudo-States)

伪类选择器, 是根据控件所处的某个状态被选择的. 例如按钮被按下, 输⼊框获取到焦点, ⿏标移动到某个控件上等.

  • 当状态具备时, 控件被选中, 样式⽣效
  • 当状态不具备时, 控件不被选中, 样式失效

使⽤ : 的⽅式定义伪类选择器

常⽤的伪类选择器:

在这里插入图片描述
在这里插入图片描述

这些状态可以使⽤ ! 来取反. ⽐如 :!hover 就是⿏标离开控件时, :!pressed 就是⿏标松开时, 等等.

代码⽰例: 设置按钮的伪类样式.

在界⾯上创建⼀个按钮

编写 main.cpp, 创建全局样式

代码语言:javascript
复制
 			int main(int argc, char *argv[])
 			{
 				QApplication a(*argc*, argv);
 				QString style = "";
 				style += "QPushButton { color: red; }";
 				style += "QPushButton:hover { color: green; }";
 				style += "QPushButton:pressed { color: blue; }";
 				a.setStyleSheet(style);
 				Widget w;
 				w.show();
 				return a.exec();
 			}

运⾏程序, 可以看到, 默认情况下按钮⽂字是红⾊, ⿏标移动上去是绿⾊, ⿏标按下按钮是蓝⾊.

4. 样式属性

QSS 中的样式属性⾮常多, 不需要都记住. 核⼼原则还是⽤到了就去查.

⼤部分的属性和 CSS 是⾮常相似的.

  • ⽂档的 Qt Style Sheets Reference 章节详细介绍了哪些控件可以设置属性, 每个控 件都能设置哪些属性等.
盒模型 (Box Model)

在⽂档的 Customizing Qt Widgets Using Style Sheets 的 The Box Model 章节介绍了盒模型.

⼀个遵守盒模型的控件, 由上述⼏个部分构成.

  • Content 矩形区域: 存放控件内容. ⽐如包含的⽂本/图标等.
  • Border 矩形区域: 控件的边框.
  • Padding 矩形区域: 内边距. 边框和内容之间的距离.
  • Margin 矩形区域: 外边距. 边框到控件 geometry 返回的矩形边界的距离

默认情况下, 外边距, 内边距, 边框宽度都是 0

可以通过⼀些 QSS 属性来设置上述的边距和边框的样式.

代码⽰例: 设置边框和内边距

在界⾯上创建⼀个 label

修改 main.cpp, 设置全局样式

代码语言:javascript
复制
 		int main(int argc, char *argv[])
 		{
 			 QApplication a(argc, argv);
 			 a.setStyleSheet("QLabel { border: 5px solid red; padding-left: 10px; }");
 			 Widget w;
 			 w.show();
 			 return a.exec();
 		}
  • border: 5px solid red 相当于 border-style: solid; border-width: 5px
  • border-color: red; 三个属性的简写形式
  • padding-left: 10px; 是给左侧设置内边距
  1. 运⾏程序, 可以看到样式发⽣了变化

代码⽰例: 设置外边距

为了⽅便确定控件位置, 演⽰外边距效果, 我们使⽤代码创建⼀个按钮

修改 widget.cpp, 创建按钮, 并设置样式

代码语言:javascript
复制
 		Widget::Widget(QWidget *parent)
 		 : QWidget(parent)
 		 , ui(new Ui::Widget)
 		{
 			 ui->setupUi(this);
 			 QPushButton* btn = new QPushButton(this);
 			 btn->setGeometry(0, 0, 100, 100);
 			 btn->setText("hello");
 			 btn->setStyleSheet("QPushButton { border: 5px solid red; margin: 20px; }");
 			 const QRect& rect = btn->geometry();
 			 qDebug() << rect;
 		}

运⾏程序, 可以看到, 当前按钮的边框被外边距挤的缩⼩了. 但是获取到的按钮的 Geometry 是不变的.

5. 控件样式示例

(1)按钮

代码⽰例: ⾃定义按钮

  1. 界⾯上创建⼀个按钮

右键 -> 改变样式表, 使⽤ Qt Designer 设置样式

代码语言:javascript
复制
 		QPushButton {
 			 font-size: 20px;
 			 border: 2px solid #8f8f91;
 			 border-radius: 15px;
 			 background-color: #dadbde;
 		}
 		QPushButton:pressed {
 		 	background-color: #f6f7fa;
 		}

执⾏程序, 可以看到效果

(2)复选框

代码⽰例: ⾃定义复选框

  1. 创建⼀个 resource.qrc ⽂件, 并导⼊以下图⽚
  • 使⽤⿊⾊作为默认形态.
  • 使⽤蓝⾊作为 hover 形态.
  • 使⽤红⾊作为 pressed 形态.

创建⼀个复选框

代码语言:javascript
复制
 		QCheckBox {
 		    font-size : 20px;
 		}
 		
 		QCheckBox::indicator {
 		    width: 20px;
 		    height: 20px;
 		}
 		
 		QCheckBox::indicator : unchecked {
 		    image: url(:/checkbox - unchecked.png);
 		}
 		QCheckBox::indicator : unchecked : hover {
 		    image:url(:/checkbox - unchecked_hover.png);
 		}

 		QCheckBox::indicator:unchecked:pressed {
 		 	image: url(:/checkbox-unchecked_pressed.png);
 		}
 		QCheckBox::indicator:checked {
 		 	image: url(:/checkbox-checked.png);
 		}
 		QCheckBox::indicator:checked:hover {
 		 	image: url(:/checkbox-checked_hover.png);
 		}
 		QCheckBox::indicator:checked:pressed {
 		 	image: url(:/checkbox-checked_pressed.png);
 		}

运⾏程序, 可以看到此时的复选框就变的丰富起来了

(3)单选框

参考复选框,用法基本一样。

(4)输入框

代码⽰例: ⾃定义单⾏编辑框

  1. 在界⾯上创建⼀个单⾏编辑框

在 Qt Designer 中编写样式.

代码语言:javascript
复制
 		QLineEdit {
 			 border-width: 1px; 
 			 border-radius: 10px;
 			 border-color: rgb(58, 58, 58);
 			 border-style: inset;
 			 padding: 0 8px;
 			 color: rgb(255, 255, 255);
 			 background:rgb(100, 100, 100);
 			 selection-background-color: rgb(187, 187, 187);
 			 selection-color: rgb(60, 63, 65);
 		}

执⾏程序观察效果.

在这里插入图片描述
在这里插入图片描述
(5)列表

代码⽰例: ⾃定义列表框

  1. 在界⾯上创建⼀个 ListView

编写代码

代码语言:javascript
复制
 		QListView::item:hover {
 			 background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #FAFBFE, stop: 1 #DCDEF1);
 		}


 		QListView::item:selected {
 			 border: 1px solid #6a6ea9;
 			 background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6a6ea9, stop: 1 #888dd9);
 		}

执⾏程序, 观察效果

(6)菜单栏

代码⽰例: ⾃定义菜单栏

  1. 创建菜单栏

编写样式

代码语言:javascript
复制
 		QMenuBar {
 			 background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,
 			 stop:0 lightgray, stop:1 darkgray);
 			 spacing: 3px; /* spacing between menu bar items */
 		}
 		QMenuBar::item {
 			 padding: 1px 4px;
 			 background: transparent;
 			 border-radius: 4px;
 		}
 		QMenuBar::item:selected { /* when selected using mouse or keyboard */
 			 background: #a8a8a8;
 		}
 		QMenuBar::item:pressed {
 			 background: #888888;
 		}
 		QMenu {
 			 background-color: white;
 			 margin: 0 2px; /* some spacing around the menu */
 	    }
 		QMenu::item {
 			 padding: 2px 25px 2px 20px;
 			 border: 3px solid transparent; /* reserve space for selection border */
 		}
 		QMenu::item:selected {
 			 border-color: darkblue;
 			 background: rgba(100, 100, 100, 150);
 		}
 		QMenu::separator {
 			 height: 2px;
 			 background: lightblue;
 			 margin-left: 10px;
 			 margin-right: 5px;
 		}

执⾏程序, 观察效果

(7)登录界面

基于上述学习过的 QSS 样式, 制作⼀个美化版本的登录界⾯

  1. 在界⾯上创建元素
  2. 使⽤布局管理器, 把上述元素包裹⼀下.
  • 使⽤ QVBoxLayout 来管理上述控件.
  • 两个输⼊框和按钮的 minimumHeight 均设置为 50. (元素在布局管理器中⽆法直接设置 width 和 height, 使⽤ minimumWidth 和 minimumHeight 代替, 此时垂直⽅向的 sizePolicy 要设为 fixed).
  • 右键 QCheckBox , 选择 Layout Alignment 可以设置 checkbox 的对⻬⽅式(左对⻬, 居中对⻬, 右对⻬).
  1. 设置背景图⽚.

把上述控件添加⼀个⽗元素 QFrame, 并设置 QFrame 和 窗⼝⼀样⼤.

  • 顶层窗⼝的 QWidget ⽆法设置背景图⽚. 因此我们需要再套上⼀层 QFrame. 背景图⽚就设置到 QFrame 上即可.

创建 resource.qrc, 并导⼊图片,编写 QSS 样式.

使⽤ border-image 设置背景图⽚, ⽽不是 background-image . 主要是因为 border-image 是可以⾃动缩放的. 这⼀点在窗⼝⼤⼩发⽣改变时是⾮常有意义的.

代码语言:javascript
复制
			QFrame {
			 	border-image: url(:/picture.jpg);
			}
  1. 设置输⼊框样式

编写 QSS 代码

代码语言:javascript
复制
			QLineEdit {
				 color: #8d98a1;
				 background-color: #405361;
				 padding: 0 5px;
				 font-size: 20px;
				 border-style: none;
				 border-radius: 10px;
			}
  1. 设置 checkbox 样式

背景⾊使⽤ transparent 表⽰完全透明 (应⽤⽗元素的背景).

代码语言:javascript
复制
			QCheckBox {
				 color: white;
				 background-color: transparent;
			}

设置按钮样式

代码语言:javascript
复制
 		QPushButton {
 			font-size: 20px;
 			color: white;
 			background-color: #555;
 			border-style: outset;
 			border-radius: 10px;
 		}
 		
 		QPushButton:pressed {
 			color: black;
 			background-color: #ced1db;
 			border-style: inset;
 		}

最终完整样式代码. 这些代码设置到 QFrame 的属性中即可。通常我们建议把样式代码集中放置, ⽅便调整和排查

代码语言:javascript
复制
			QFrame {
				border-image: url(:/cat.jpg);
			}
			
			QLineEdit {
				color: #8d98a1;
				background-color: #405361;
				padding: 0 5px;
				font-size: 20px;
				border-style: none;
				border-radius: 10px;
			}
			
			QCheckBox {
				 color: white;
				 background-color: transparent;
			}
			QPushButton {
				 font-size: 20px;
				 color: white;
				 background-color: #555;
				 border-style: outset;
				 border-radius: 10px;
			}
			QPushButton:pressed {
				 color: black;
				 background-color: #ced1db;
				 border-style: inset;
			}

二、绘图

1. 基本概念

虽然 Qt 已经内置了很多的控件, 但是不能保证现有控件就可以应对所有场景。很多时候我们需要更强的 “⾃定制” 能⼒。

Qt 提供了画图相关的 API, 可以允许我们在窗⼝上绘制任意的图形形状, 来完成更复杂的界⾯设计.

绘图 API 核⼼类

绘图 API 的使⽤, ⼀般不会在 QWidget 的构造函数中使⽤, ⽽是要放到 paintEvent 事件中.

因此, 如果把绘图 api 放到构造函数中调⽤, 那么⼀旦出现上述的情况, 界⾯的绘制效果就⽆法确保符合预期了.

2. 绘制各种形状

(1)绘制线段
代码语言:javascript
复制
			void drawLine(const QPoint &p1, const QPoint &p2);
			 参数:
			 p1:绘制起点坐标
			 p2:绘制终点坐标

1、在 “widget.h” 头⽂件中声明绘图事件

2、在 “widget.cpp” ⽂件中重写 paintEvent() ⽅法

实现效果如下:

(2)绘制矩形
代码语言:javascript
复制
			void QPainter::drawRect(int x, int y, int width, int height);
			参数:
			 x:窗⼝横坐标;
			 y:窗⼝纵坐标;
			 width:所绘制矩形的宽度;
			 height:所绘制矩形的⾼度;
(3)绘制圆形
代码语言:javascript
复制
			void QPainter::drawEllipse(const QPoint &center, int rx, int ry)
			参数:
			 center:中⼼点坐标
			 rx:横坐标
			 ry:纵坐标

实现效果:

(4)设置画笔

QPainter 在绘制时,是有⼀个默认的画笔的。在使⽤时也可以⾃定义画笔。在 Qt 中,QPen类中定义了 QPainter 应该如何绘制形状、线条和轮廓。同时通过 QPen类 可以设置画笔的线宽、颜⾊、样式、画刷等。

画笔的颜⾊可以在实例化画笔对象时进⾏设置,画笔的宽度是通过 setWidth() ⽅法进⾏设置,画笔的风格是通过setStyle()⽅法进⾏设置,设置画刷主要是通过 setBrush() ⽅法。

  • 设置画笔颜⾊:QPen::QPen(const QColor &color) 画笔的颜⾊主要是通过 QColor 类设置;
  • 设置画笔宽度:void QPen::setWidth(int width)
  • 设置画笔⻛格:void QPen::setStyle(Qt::PenStyle style)

画笔的⻛格有:

⽰例:画笔的使⽤

实现效果如下:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-08-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、QSS
    • 1. QSS
      • 2. QSS 设置方式
        • (1)指定控件样式设置
        • (2)全局样式设置
        • (3)从文件加载样式表
        • (4)使用 Qt Designer 编辑样式
      • 3. 选择器
        • (1)选择器介绍
        • (2)子控件选择器 (Sub-Controls)
        • (3)伪类选择器 (Pseudo-States)
      • 4. 样式属性
        • 盒模型 (Box Model)
      • 5. 控件样式示例
        • (1)按钮
        • (2)复选框
        • (3)单选框
        • (4)输入框
        • (5)列表
        • (6)菜单栏
        • (7)登录界面
    • 二、绘图
      • 1. 基本概念
        • 2. 绘制各种形状
          • (1)绘制线段
          • (2)绘制矩形
          • (3)绘制圆形
          • (4)设置画笔
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档