zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    JavaScript脚本语言特色时钟
    这个周末安排,
    市场营销书籍推荐
    比较好的管理类书籍推荐
    如何培养自己的领导力?或许你该看看这些书
    十本最畅销的市场营销书籍,你看过几本?
    如何提高情商?答案可能在《情商必读12篇》这本书里
    如何管理好员工?
    做销售要看哪些书?《销售管理必读12篇》了解下
    管理书籍推荐,你看过哪些呢?
  • 原文地址:https://www.cnblogs.com/zhangdewang/p/9285752.html
Copyright © 2011-2022 走看看