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(3);
          int x = option->rect.x();
          int y = option->rect.y();
          int w = option->rect.width() / 2;
          int h = option->rect.height() / 2;
          x += (option->rect.width() - w) / 2;
          y += (option->rect.height() - h) / 2;

          if (element == PE_IndicatorSpinUp) {
              points[0] = QPoint(x, y + h);
              points[1] = QPoint(x + w, y + h);
              points[2] = QPoint(x + w / 2, y);
          } else { // PE_SpinBoxDown
              points[0] = QPoint(x, y);
              points[1] = QPoint(x + w, y);
              points[2] = QPoint(x + w / 2, 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(190));
              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

原文地址:https://www.cnblogs.com/zhangdewang/p/9285752.html

时间: 2024-11-02 17:05:06

QT界面 理解QStyle和QStyleOption以及QStyleFactory的相关文章

Qt界面美化 QSS

目前发现在Qt-Design中右击控件,可以选择Change StyleSheet ------------------------以下总结不太对 刚接触Qt,发现Qt Design无法对每个控件进行颜色风格设置.正在纳闷如此受欢迎的开发工具,怎么会没有这种,Delphi,VB,VC,C#都具备的基本功能呢? 后来在CSDN上才知道,Qt已经走在这些工具的最前方了,把界面已经独立出来和web编程一样.web有CSS专门美化工作.而Qt也有QSS进行美化设计.完全可以不影响程序开发.而且可以直接调

Qt 界面使用自定义控件 &quot;提升为&quot;

1.效果图 我做了一个非常简单的例子,一个可以显示颜色的QLabel,边上有个按钮,点击,跳出颜色选取的Dialog,然后选择一个颜色,这个QLabel会变成什么颜色. 2.ColorLabel 我们先把这个自定义的类写好: 头文件: #ifndef COLORLABEL_H #define COLORLABEL_H #include <QLabel> #include <QPainter> class ColorLabel : public QLabel{ Q_OBJECT pu

在ROS中使用QT界面

在终端可以直接用catkin_create_qt_pkg命令创建带Qt界面的ROS package,再按照前面说的方法导入到Qt即可 这里参考的是qt_createTutorialsQt App Templates (1) 要使用catkin_create_qt_pkg命令需要安装一个包,执行如下命令: $ sudo apt-get install ros-indigo-qt-ros 这样我就可以使用catkin_create_qt_pkg命令创建一个名为testgui的package $ cd

qt之旅-1纯手写Qt界面

通过手写qt代码来认识qt程序的构成,以及特性.设计一个查找对话框.下面是设计过程 1 新建一个empty qt project 2 配置pro文件 HEADERS += Find.h QT += widgets SOURCES += Find.cpp main.cpp 3 编写对话框的类 代码如下: //Find.h #ifndef FIND_H #define FIND_H #include <QDialog> class QCheckBox; class QLabel; class QL

QT界面开发-(特效)无边框窗口+背景图片

转发自邵发<C/C++系列教程>Qt界面开发 https://chuanke.baidu.com/4509752-209060.html 1.自己用代码画界面 2.用Laber控件放一张背景大图 hpp 1 #include <QtWidgets> 2 3 4 private: 5 virtual void paintEvent(QPaintEvent *event); 6 7 virtual void mouseMoveEvent(QMouseEvent * event); 8

用QT创建新风格: QStyle

转贴: http://hi.baidu.com/yjj2008/blog/item/6cd4a1892ef0d4b60f2444a5.html 本文介绍了如何使用qt提供的接口来设计自己的GUI风格(look and feel),并通过一个具体的例子(使QSpinBox垂直显示)来详细说明过程.运行环境:redhat 9.0,qt-x11-free-3 1.Qt的风格 a) Qt简介 Qt是一个跨平台的C++图形用户界面应用程序开发库,使用Qt可以开发出高质量的图形用户接口,它是完全面向对象的.

Qt界面风格设置

每个widget都可以设置风格 setStyle(QStyle style) 对QApplication设置QStyle即对所有 QApplication::setStyle(QStyleFactory::create("Fusion")); 其他widget如过没有被设置QStyle,默认使用QApplication的 QStyle主要可重写接口 绘制复杂控件 virtual void    drawComplexControl(ComplexControl control, con

对QT的理解

我的理解: QT做应用软件可以很强大,界面足够漂亮(最有意思的是QSS,让我刮目相看),应该是足够了.同时QT也提供了源码,不过超级复杂,难以理解,所以还是无法深入底层.另外它提供了一个额外的好处,就是MAC软件编程不用学COCOA这些太偏门的框架和语言.工作机会不算多但也不算少,总体来说,值得一学. 但是学习和使用了这么久Windows编程,不仔细学习直接处理消息和申请使用内存等特点(而不是把相关内容托管给语言或者框架),那样的话,就只能停留于开发应用软件层,无法做到知其然和所以然.所以必须学

qt 界面去掉系统边框

1 #ifndef CUSTOMIZE_QWIDGET_H 2 #define CUSTOMIZE_QWIDGET_H 3 #include <QWidget> 4 #include <QMouseEvent> 5 6 class CustomizeQWidget : public QWidget 7 { 8 Q_OBJECT 9 public: 10 explicit CustomizeQWidget(QWidget *parent = 0); 11 ~CustomizeQWid