Qt Gui 第十九章
1、Qt样式表
.qss文件;跟html的css文件格式差不多。
例如:selector1, selector2。。。 {property1: value1; property2: value2; 。。。。} 表示多个选择器,对应多个属性值;
也可以在代码中直接编写;例如:
// 指向全局的设置QLineEdit的背景色为黄色; qApp->setStyleSheet("QLineEdit{background-color:yellow;}"); // 要使用的dialog设置QLineEdit的背景色为黄色; CandyDialog w; w.setStyleSheet("QLineEdit{background-color:yellow;}");
当要使用文件导入的时候
CandyDialog w; QFile file(":/qss/candy.qss"); file.open(QIODevice::ReadOnly); w.setStyleSheet(file.readAll());
因为candy.qss是资源文件,则需要在qrc文件中指明;
<RCC> <qresource> <file>qss/candy.qss</file> </qresource> </RCC>
qss的编写
1、颜色
可以使用rgb()、rgba()、 #RRGGBB;也可以使用调色板:palette(Base) ;渐进的调色:QLinearGradient、QRadialGradient、QConicalGradient;例如:
background-color:qlineargradient(x1:0,y1:0,x2:1,y2:1,
stop:0 white,stop:0.4 gray,
stop:1 green);
2、图片
image: url(:/images/down-arrow.png); 或者 border-image: url(:/images/button.png) 4 8 12 16; 模型即:url(image.png) top right bottom left; 即上面的横切线、右边的竖切线,下面的横切线,左边的竖切线;如果没有指定竖直,则表明边界均为0;即0 0 0 0
当切割完之后,长方形的四个角被固定;从而在拉伸的时候以这四个角进行拉伸;如图所示
当只指定一个数值的时候,则表示上下左右都是那个数值,而不是只指top是那个数值;
3、padding
padding是指文字要放的位子偏移;模型是:padding: top right bottom left; 如果要单独指定的话,则是padding-top 或者其他的方位;如上图所示;如果要将contents rectangle的区域覆盖到border rectangle 则需要将padding的值设置为负数;
即移动contents rectangle通过padding来完成;
4、indicator的使用;例如
QLineEdit, QListView { color: rgb(127,0,63); background-color: rgb(255,255,241); }
如上qss所示,有两个indicator(QLineEdit和QListView)共同使用花括号里面的属性值;
indicator也可以是:control:subcontrol的方式如:QComboBox:editable、QCheckBox:checked:hover、QCheckBox:!checked:hover 也可以是如上所示的逻辑非
5、杂项
当使用圆角的时候,可以使用
border-radius: 10px; 表示半径为10像素的圆作为圆角
border: 2px groove gray; 表示两像素的灰色凹槽
font: bold 10pt; 使用10号加粗的字体
QComboBox * {font: 9pt;} 表示QComboBox的子项用的字号是9
二、子类化QStyle
当使用到custom style的时候,则需要在使用到这个子类化控件之前,先设置进qapplication; 例如:要将BronzeStyle这个子类化的控件加到程序中,则需要在用到这个控件之前先操作:QApplication::setStyle(new BronzeStyle);
1、 drawComplexControl和drawControl
drawComplexControl和drawControl 两个函数都是用于绘制控件的;具体看要绘制的控件是简单控件还是复杂控件。比如:PushButton、PushButtonBevel、PushButtonLabel、RadioButton等简单的控件用drawControl即可;复杂的控件绘制则用drawComplexControl;具体看qcommonstyle.cpp里面对这两个函数的实现。
在这两个函数的使用时候,尽量不要用widget这个参数。
最好使用如下类似的标记红色的方式进行操作;
case CE_PushButton: if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { 。。。。。。 } break;
2、polish
在绘制窗口之前,会先调用polish(QPalette &pal)进行初始化画板;如果要对画板进行特殊的设置,则可以重写该函数。
void BronzeStyle::polish(QPalette &palette) { QPixmap backgroundImage(":/images/background.png"); QColor bronze(207, 155, 95); QColor veryLightBlue(239, 239, 247); QColor lightBlue(223,223,239); QColor darkBlue(95, 95, 191); palette = QPalette(bronze); palette.setBrush(QPalette::Window, backgroundImage); palette.setBrush(QPalette::BrightText, Qt::white); palette.setBrush(QPalette::Base, veryLightBlue); palette.setBrush(QPalette::AlternateBase, lightBlue); palette.setBrush(QPalette::Highlight, darkBlue); palette.setBrush(QPalette::Disabled, QPalette::Highlight, Qt::darkGray); }
当具体到某个控件的时候,也可以调用polish(同函数,不同参数)polish(QWidget *widget)
比如:当想对鼠标进入指定控件时候产生重绘事件
void BronzeStyle::polish(QWidget *widget) { if (qobject_cast<QAbstractButton*>(widget) || qobject_cast<QAbstractSpinBox*>(widget) ) widget->setAttribute(Qt::WA_Hover, true); }
当绘制完成之后,则需要将刚才产生重绘的属性设置回false;
void BronzeStyle::unpolish(QWidget *widget) { if (qobject_cast<QAbstractButton*>(widget) || qobject_cast<QAbstractSpinBox*>(widget)) widget->setAttribute(Qt::WA_Hover, false); }
3、standardIconImplementation
获取用户界面上的标准图标;通过这个函数则可以调整标准图标的一些颜色,透明度等。
4、subControlRect和subElementRect
subControlRect是获取控件当中各个部件的尺寸;例如:SpinBoxDown、SpinBoxUp、SpinBoxEditField等。。。都是具体的控件的子部件;

QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget) const { QRect ret; switch (cc) { #ifndef QT_NO_SLIDER case CC_Slider: if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget); int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget); switch (sc) { case SC_SliderHandle: { int sliderPos = 0; int len = proxy()->pixelMetric(PM_SliderLength, slider, widget); bool horizontal = slider->orientation == Qt::Horizontal; sliderPos = sliderPositionFromValue(slider->minimum, slider->maximum, slider->sliderPosition, (horizontal ? slider->rect.width() : slider->rect.height()) - len, slider->upsideDown); if (horizontal) ret.setRect(slider->rect.x() + sliderPos, slider->rect.y() + tickOffset, len, thickness); else ret.setRect(slider->rect.x() + tickOffset, slider->rect.y() + sliderPos, thickness, len); break; } case SC_SliderGroove: if (slider->orientation == Qt::Horizontal) ret.setRect(slider->rect.x(), slider->rect.y() + tickOffset, slider->rect.width(), thickness); else ret.setRect(slider->rect.x() + tickOffset, slider->rect.y(), thickness, slider->rect.height()); break; default: break; } ret = visualRect(slider->direction, slider->rect, ret); } break; ......... default: qWarning("QCommonStyle::subControlRect: Case %d not handled", cc); } return ret;
subElementRect则是获取子元素的尺寸;例如:PushButtonContents、PushButtonFocusRect、CheckBoxIndicator、HeaderLabel等元素
QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, const QWidget *widget) const { Q_D(const QCommonStyle); QRect r; switch (sr) { case SE_PushButtonContents: if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { int dx1, dx2; dx1 = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget); if (btn->features & QStyleOptionButton::AutoDefaultButton) dx1 += proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget); dx2 = dx1 * 2; r.setRect(opt->rect.x() + dx1, opt->rect.y() + dx1, opt->rect.width() - dx2, opt->rect.height() - dx2); r = visualRect(opt->direction, opt->rect, r); } break; .................. default: break; } return r; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!