QT界面 理解QStyle和QStyleOption以及QStyleFactory
QStyleOption类和QStyle类简介
QStyleOption类存储QStyle函数使用的参数。QStyleOption及其子类包含了QStyle函数绘制图形元素所需的所有信息。 由于性能原因,成员函数很少,并且对成员变量的访问是直接的(即。,使用。或- >操作符)。这种低级的感觉使结构易于使用,并强调这些只是样式函数使用的参数。 QStyle函数的调用者通常在堆栈上创建QStyleOption对象。结合Qt对QString、QPalette和QColor等类型的隐式共享的广泛使用,可以确保没有不必要的内存分配。 |
QStyle类是一个抽象基类,它封装GUI的外观和感觉。 Qt包含一组QStyle子类,它们模拟Qt支持的不同平台的样式(QWindowsStyle、QMacStyle等)。默认情况下,这些样式构建在Qt GUI模块中。样式也可以作为插件提供。 Qt的内置小部件使用QStyle来执行几乎所有的绘图,确保它们看起来与等效的本地小部件完全相同。 |
QStyle类
设置风格:
可以使用QApplication::setStyle(QStyle *style)函数设置整个应用程序的样式。它也可以由应用程序的用户指定,使用样式命令行选项: 。
./myapplication -style windows
如果没有指定样式,Qt将为用户的平台或桌面环境选择最合适的样式。还可以使用QWidget::setStyle(QStyle *style)函数在单个小部件上设置样式。
QStyle类的简要:
如果您正在开发自定义小部件,并希望它们在所有平台上看起来都很好,那么可以使用QStyle函数来执行小部件绘图的部分,例如drawItemText()、drawItemPixmap()、drawPrimitive()、drawControl()和drawComplexControl()。
大多数QStyle绘制函数有四个参数:
1.枚举值,指定要绘制哪个图形元素
2.QStyleOption,指定如何和在哪里呈现该元素
3.用于绘制元素的QPainter
4.执行绘图的QWidget(可选)
QStyle从QStyleOption中获取呈现图形元素所需的所有信息。如果样式需要小部件执行特殊效果(比如macOS上的动画默认按钮),则将小部件作为最后一个参数传递,但这不是必须的。实际上,通过正确设置QPainter,您可以使用QStyle来绘制任何绘图设备,而不仅仅是控件。QStyleOption为可以绘制的各种图形元素类型有不同的子类。例如,PE_FrameFocusRect需要一个QStyleOptionFocusRect参数。为了确保绘图操作尽可能快,QStyleOption及其子类具有公共数据成员。有关如何使用的详细信息,请参阅QStyleOption类文档。
为了方便,Qt提供了QStylePainter类,它结合了QStyle、QPainter和QWidget。这使得下面写作替换原有的成为可能:
QStylePainter painter(this);
...
painter.drawPrimitive(QStyle::PE_FrameFocusRect, option);
取代下面代码
QPainter painter(this);
...
style()->drawPrimitive(QStyle::PE_FrameFocusRect, &option, &painter, this);
自定义界面:
通过创建自定义样式,您可以为应用程序创建自定义外观。创建自定义样式有两种方法。在静态方法中,您要么选择一个现有的QStyle类,子类化它,并重新实现虚拟函数来提供自定义行为,或者从头创建一个完整的QStyle类。在动态方法中,您可以在运行时修改系统样式的行为。下面描述静态方法。动态方法描述在QProxyStyle中。
静态方法的第一步是选择Qt提供的一种样式,您将从中构建自定义样式。您对QStyle类的选择将取决于哪个样式与您所期望的样式最相似。您可以使用的最普通的类是QCommonStyle(不是QStyle)。这是因为Qt要求它的样式是QCommonStyles。
根据您想要更改的基本样式的哪些部分,您必须重新实现用于绘制接口部分的函数。为了说明这一点,我们将修改QWindowsStyle绘制的旋转框箭头的外观。箭头是由draw原语()函数绘制的基本元素,因此我们需要重新实现该函数。
我们需要以下类声明:
class CustomStyle : public QProxyStyle
{
Q_OBJECT public:
CustomStyle();
~CustomStyle() {} void drawPrimitive(PrimitiveElement element, const QStyleOption *option,
QPainter *painter, const QWidget *widget) const;
};
要绘制上下箭头,QSpinBox使用PE_IndicatorSpinUp和PE_IndicatorSpinDown原始元素。下面介绍如何重新实现draw原语()函数,以便以不同的方式绘制它们:
void CustomStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
QPainter *painter, const QWidget *widget) const
{
if (element == PE_IndicatorSpinUp || element == PE_IndicatorSpinDown) {
QPolygon points();
int x = option->rect.x();
int y = option->rect.y();
int w = option->rect.width() / ;
int h = option->rect.height() / ;
x += (option->rect.width() - w) / ;
y += (option->rect.height() - h) / ; if (element == PE_IndicatorSpinUp) {
points[] = QPoint(x, y + h);
points[] = QPoint(x + w, y + h);
points[] = QPoint(x + w / , y);
} else { // PE_SpinBoxDown
points[] = QPoint(x, y);
points[] = QPoint(x + w, y);
points[] = QPoint(x + w / , y + h);
} if (option->state & State_Enabled) {
painter->setPen(option->palette.mid().color());
painter->setBrush(option->palette.buttonText());
} else {
painter->setPen(option->palette.buttonText().color());
painter->setBrush(option->palette.mid());
}
painter->drawPolygon(points);
} else {
QProxyStyle::drawPrimitive(element, option, painter, widget);
}
}
注意:我们不使用小部件参数,除非将其传递给QWindowStyle::drawPrimitive()函数。如前所述,关于要绘制什么以及应该如何绘制的信息是由QStyleOption对象指定的,因此不需要询问小部件。
如果您需要使用小部件参数来获取其他信息,请小心确保它不是0,并且在使用它之前它是正确的类型。例如:
const QSpinBox *spinBox = qobject_cast<const QSpinBox *>(widget);
if (spinBox) {
...
}
**在实现自定义样式时,您不能仅仅因为枚举值被称为PE_IndicatorSpinUp或PE_IndicatorSpinDown就认为小部件是一个QSpinBox。
警告:Qt样式表目前不支持自定义QStyle子类。在将来的某个版本会解决这个问题。
在Qt应用程序中有几种使用自定义样式的方法。最简单的方法是在创建QApplication对象之前将自定义样式传递给QApplication::setStyle()静态函数:
#include <QtWidgets> #include "customstyle.h" int main(int argc, char *argv[])
{
QApplication::setStyle(new CustomStyle);
QApplication app(argc, argv);
QSpinBox spinBox;
spinBox.show();
return app.exec();
}
在项视图中使用样式
视图中的项的绘制是由委托执行的。Qt的默认委托QStyledItemDelegate也用于计算项目的边界矩形,以及QStyledItemDelegate支持的各种项目数据角色的子元素。查看QStyledItemDelegate类描述,以找出支持哪些数据类型和角色。您可以在模型/视图编程中阅读更多关于项目数据角色的内容。
当QStyledItemDelegate绘制项时,它会绘制CE_ItemViewItem,并使用CT_ItemViewItem计算它们的大小。还要注意,它使用SE_ItemViewItemText设置编辑器的大小。在实现自定义项目视图绘制样式时,需要检查QCommonStyle的实现(以及样式继承的任何其他子类)。通过这种方式,您可以发现哪些和如何绘制其他样式元素,然后您可以重新实现应该以不同方式绘制的元素的绘制。
下面使用一个小例子来说明:
switch (element) {
case (PE_PanelItemViewItem): {
painter->save(); QPoint topLeft = option->rect.topLeft();
QPoint bottomRight = option->rect.topRight();
QLinearGradient backgroundGradient(topLeft, bottomRight);
backgroundGradient.setColorAt(0.0, QColor(Qt::yellow).lighter());
backgroundGradient.setColorAt(1.0, Qt::white);
painter->fillRect(option->rect, QBrush(backgroundGradient)); painter->restore();
break;
}
default:
QProxyStyle::drawPrimitive(element, option, painter, widget);
}
原始元素PE_PanelItemViewItem负责绘制项目的背景,它来自QCommonStyle的CE_ItemViewItem实现。
要添加对绘制新数据类型和项数据角色的支持,需要创建一个自定义委托。但是,如果您只需要支持由默认委托实现的数据类型,则自定义样式不需要附带的委托。QStyledItemDelegate类描述提供了关于自定义委托的更多信息。项目视图标题的绘制也由样式完成,对标题项的大小以及行和列的大小进行控制。
QStyleOption子类:
QStyleOptionButton, QStyleOptionComplex, QStyleOptionDockWidget, QStyleOptionFocusRect, QStyleOptionFrame, QStyleOptionGraphicsItem, QStyleOptionHeader, QStyleOptionMenuItem, QStyleOptionProgressBar, QStyleOptionRubberBand, QStyleOptionTab, QStyleOptionTabBarBase, QStyleOptionTabWidgetFrame, QStyleOptionToolBar, QStyleOptionToolBox, and QStyleOptionViewItem
QT界面 理解QStyle和QStyleOption以及QStyleFactory的更多相关文章
- 嵌入式Linux学习笔记(六) 上位机QT界面实现和串口通讯实现
目录 (1).参考资料 (2).QT界面布局实现 (3).数据和操作逻辑 在上一章我们实现了下位机的协议制定,并通过串口通讯工具完成了对设备内外设(LED)的状态修改,下面就要进行上位机软件的实现了( ...
- Qt 界面使用自己定义控件 "提升为"
1.效果图 我做了一个很easy的样例,一个能够显示颜色的QLabel,边上有个button,点击,跳出颜色选取的Dialog,然后选择一个颜色.这个QLabel会变成什么颜色. 2.ColorLab ...
- OSG嵌入QT(QT界面使用Qt Designer编辑)
本文主要内容:使用Qt Designer编辑好QT界面后,将OSG中的ViewerWidget嵌入到QT的Widget中. 在VS中嵌入QT工具,建立QT GUIApplication后,打开自动生成 ...
- 在ROS中使用QT界面
在终端可以直接用catkin_create_qt_pkg命令创建带Qt界面的ROS package,再按照前面说的方法导入到Qt即可 这里参考的是qt_createTutorialsQt App Te ...
- Qt界面编程基本操作
Qt界面编程基本操作 了解基本代码构成 类widget的头文件widget.h如下: #ifndef WIDGET_H #define WIDGET_H #include <QWidget> ...
- QT界面绘制学习记录
1. MVC结构中,model必须作为类的成员变量存在,不可再函数内部申明.否则,会出现函数调用结束,model找不到的错误. 2.QcomboBox可设置为左边空白,右侧一小箭头的形式.代码:com ...
- 用QT创建新风格: QStyle
转贴: http://hi.baidu.com/yjj2008/blog/item/6cd4a1892ef0d4b60f2444a5.html 本文介绍了如何使用qt提供的接口来设计自己的GUI风格( ...
- qt 界面去掉系统边框2.0版
之前的一版存在bug.如果将鼠标放移动到界面内某个可点击的widget上(如:QPushButton)上,按住鼠标左键不放,界面可能会出现界面非预期移动的问题. 那是因为当鼠标移动到可点击的widge ...
- 对QT的理解——能在公司里不做Java,不做很偏门的产品,不使用偏门的语言,还有钱挣,要有感恩的心
我的理解: QT做应用软件可以很强大,界面足够漂亮(最有意思的是QSS,让我刮目相看),应该是足够了.同时QT也提供了源码,不过超级复杂,难以理解,所以还是无法深入底层.另外它提供了一个额外的好处,就 ...
随机推荐
- [Android Pro] 关于BitmapFactory.decodeStream(is)方法无法正常解码为Bitmap对象的解决方法
在android sdk 1.6版本API帮助文档中,其中关于BitmapFactory.decodeFactory.decodeStream(InputStream is)的帮助文档是这么说明的: ...
- etcd,Docker问题汇总
单节点etcd publish error 正在愉快的进行jenkins流程,突然发现etcd连接不上去了.重新reboot后发现日志publish error Oct :: k8s-master e ...
- entity framework 去缓存
MSDN上对MergeOption枚举的定义为: 成员名称 说明 AppendOnly 不会从数据源加载对象上下文中已存在的对象.这是查询或调用 EntityCollection<(Of < ...
- 谷歌扩展程序--------------Message
转载:https://developer.chrome.com/extensions/messaging#external-webpage Message Passing Since content ...
- 如何监控Oracle
介绍了DBA每天在监控Oracle数据库方面的职责,讲述了如何通过shell脚本来完成这些重复的监控工作.本文首先回顾了一些DBA常用的Unix命令,以及解释了如何通过Unix Cron来定时执行DB ...
- TensorFlow------读取图片实例
TensorFlow------读取图片实例: import tensorflow as tf import os def readpic(filelist): ''' 读取人物图片并转换成张量 :p ...
- 2017.12.25 Mybatis物理分页插件PageHelper的使用(二)
参考来自: 官方文档的说明:https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md 上篇博客 ...
- Android打印机--小票打印格式及模板设置
小票打印就是向打印设备发送控制打印格式的指令集,而这些打印格式须要去查询相应打印机的API文档,这里我把经常使用的api给封装了一下 文字对齐方式 打印字体大小 字体是否加粗 打印二维码 打印条形码 ...
- 在k8s中的基本概念
在k8s中的基本概念 一.Pod1. podk8s下最重要也最基本的概念,由一个根容器Pause和许多用户业务容器组成,是容器的载体. 2. pod的yaml定义格式及字段 apiVersion: v ...
- 算法笔记_062:蓝桥杯练习 最小乘积(基本型)(Java)
目录 1 问题描述 2 解决方案 1 问题描述 问题描述 给两组数,各n个. 请调整每组数的排列顺序,使得两组数据相同下标元素对应相乘,然后相加的和最小.要求程序输出这个最小值. 例如两组数分别为 ...