热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

Linux下应用程序开发:用QT创建新风格

文章标题:Linux下应用程序开发:用QT创建新风格。Linux是中国IT实验室的一个技术频道。包含桌面应用,Linux系统管理,内核研究,嵌入式系统和开源等一些基本分类

  1.Qt的风格
  a) Qt简介
  Qt是一个跨平台的C++图形用户界面应用程序开发库,使用Qt可以开发出高质量的图形用户接口,它是完全面向对象的、易于扩展且允许真正的组件编程。Qt获得了很大的成功,特别是它的信号-槽机制是非常值得研究的通信机制,它也是Linux发行版标准组件KDE(K Desktop Enviroment)的基础。
  
  b) 风格机制
  Qt的风格机制实现了不同平台上的图形用户接口(GUI)的观感(look and feel),例如Windows平台上通常使用Windows或Windows-xp风格,而Unix平台上通常使用Motif、CDE风格。
  
  下图显示了Qt中与风格相关的类的继承关系
   
  QStyle是所有风格类的基类,它控制着所有的部件(widget即windows编程中的控件)的界面风格或观感,它定义了大量的枚举类型和十几个函数。枚举类型表示界面上的不同元素(如组合框中的按钮,按钮的边框等);函数控制图形用户界面的绘制,但大多数函数基本上只是一些声明而没有函数实现,他们的实现在QCommonStyle、QWindowStyle、QMotifStyle及其子类中。QStyle只实现了3个函数drawItem(), itemRect(), visualRect()。
  
  drawItem(): 负责绘制文本和象素图。
  itemRect(): 返回文本或图像所占的区域。
  visualRect(): 返回逻辑坐标,这个函数使Qt实现right-to-left风格(阿文、维文传统是文本从右向左显示,因此控件布局也是从右向左)。如下图所示:
   
  可以看到菜单、工具条是右对齐、单选框的按钮在右边
  
  c) 创建新风格的步骤
  在Qt中实现一种新风格的步骤很简单:只需选择一个风格类(如QCommonStyle或QStyle)作为父类,然后实现感兴趣的函数即可。难点在于函数的实现。
  
  选择父类:可以选择QStyle, QCommonStyle, QWindowStyle, QMotifStyle以及他们的子类的任意一个作为父类。通常可以选择QWindowsStyle或QMotifStyle,也可以选择QCommonStyle甚至是QStyle,但是工作量会比较大,因为很多界面的细节需要自己实现。
  
  重新实现必要的函数:想修改界面风格的哪部分,就重新实现与绘制那部分相关的函数,下面解释一下我们要重载的QStyle中的几个函数,这几个函数控制着图形用户界面上不同元素的布局和观感。
  
           1)void drawPrimitive( PrimitiveElement pe,
           QPainter *p,
            const QRect & r,
            const QColorGroup & cg,
            SFlags flags = Style_Default,
            const QStyleOption &opt = QStyleOption::Default ) ;
            
  功能:绘制基本图形元素,如QSpinBox中的带箭头的按钮 等。
  参数: PrimitiveElement pe: 这个枚举型变量表示将要绘制的基本图形界面元素(这里说的基本图形用户界面元素指GUI中不可再分的一个原子元素,如组合框 中的这个绘有黑色三角形的按钮,spinBox中的按钮 
  QPainter *p:指向QPainter类的指针,Qt中的所有绘制操作不管是绘制文本、图形还是图像都由这个类来处理。
  QRect &r: 表示一个矩形区域,Qt在这个区域中绘制基本界面元素(PrimitiveElement).
  QColorGroup &cg: QColorGroup表示一个部件(widget)的颜色组(color group),color group含有部件绘制自己时使用的各种颜色,譬如前景色背景色等。下图展示了color group中的各种颜色属性
   
  SFlags flags: 控制如何绘制图形界面元素的标志。
  QStyleOption &opt: 绘制不同的部件(widget)时会需要不同的参数,如绘制面板(panel)可能需要线宽作为额外参数而绘制焦点矩形(focus rect)可能需要背景色作为额外参数,所以Qt专门提供了一个类QStyleOption来封装不同的widget可能需要的不同的参数,opt指向这样一个类的对象。
  
  
  2)void drawComplexControl( ComplexControl control,
   QPainter *p,
   const QWidget *widget,
   const QRect &r,
   const QColorGroup &cg,
   SFlags flags = Style_Default,
   SCFlags cOntrols= QStyle::SC_All,
   SCFlags active = QStyle::SC_None,
   const QStyleOption& opt = QStyleOption::Default)
      
  功能:绘制复杂控制部件(widget)如SpinWidget,comboBox,slider,listView等
  
  参数:
  
  ComplexControl control:是一个枚举量,表示将要绘制的复杂控制部件(widget)如组合框、列表框等。
  QPainter *p:指向QPainter的指针,Qt中的所有绘制操作不管是绘制文本、图形还是图像都由这个类来处理。
  QWidget *widget:指向QWdget或其子类的指针,可以根据上面control的值转变(cast)成合适的类型,例如如果要绘制QSpinWidget,那么control取值为CC_SpinWidget,而widget指向一个QSpinWidget(QWidget的子类)的实例(instance)。使用这个变量可以访问QSpinWidget的成员函数和成员变量,譬如可以调用QSpinWidget的sizeHint函数获得这个部件的缺省大小(一个矩形空间)。
  QRect &r: 表示一个矩形区域,Qt在这个区域中绘制控件或其子部件。
  QColorGroup &cg: QColorGroup表示一个部件(widget)的颜色组(color group),color group含有部件绘制自己时使用的各种颜色,譬如前景色背景色等。
  SFlags flags: 控制如何绘制图形界面元素的标志
  SCFlags controls表示绘制复杂控制部件control的哪个子部件,缺省为SC_All,即绘制整个control而不是其某个子部件(注意control, controls是两个不同的参数)
  QStyleOption &opt: 在绘制不同的部件时可能需要不同的额外的参数,这个变量在绘制不同的widget时提供不同的信息。
  
  
   3) QRect querySubControlMetrics(ComplexControl control,
   const QWidget* widget,
   SubControl sc,
   const QStyleOption& = QStyleOption::Default)
  
  功能:获取子部件的坐标和尺寸信息。这个函数控制着一个复杂控件的布局,重载这个函数可以使的组合框的下拉按钮绘制在左边 而不是默认的右边。
  
  参数:
  ComplexControl control: 枚举量,表示将要绘制的复杂控制部件(widget)如组合框、列表框等。
  QWidget *widget:指向QWidget或其子类的指针,可以根据上面control的值转变(cast)成合适的类型,例如如果要绘制QSpinWidget,那么control取值为CC_SpinWidget,而widget指向一个QSpinWidget(QWidget的子类)的实例。使用这个变量可以访问QSpinWidget的成员函数和成员变量,譬如可以调用QSpinWidget的sizeHint函数获得这个部件的缺省大小(一个矩形空间)。
  SubControl sc:枚举量,一个复杂部件可能由多个的子部件组成,使用sc变量说明要获取那个子部件的坐标和尺寸信息。
  QStyleOption &opt: 计算不同部件的尺寸时可能需要不同的额外信息,QStyleOption封装了这些信息。
  
  2.创建新风格
  下面用一个例子来介绍一下创建新风格的整个过程,在编程之前,先看一下最终的结果是什么样的。(在Qt内部QSpinBox类是通过QSpinWidget实现的)
  默认风格的效果: 使用新风格的效果: 
  可以看到在新风格中我们的SpinBox有了垂直显示的效果。下面我们按上面说明的步骤来创建一种新的风格。
  
  1)选择基类:我们选择QWindowsStyle类作为我们新风格类的基类,当然也可以选择QMotifStyle,在这个例子种也可以选择QCommonStyle。一般不建议选择QCommonStyle作为基类,因为QCommonStyle只实现了一部分界面部件,如果要实现一个完整的风格类,我们需要重新写很多代码。
  
  2)重载相关的函数:在这个例程中我们只修改了spinBox的风格,实现这个部件(widget)只与QStyle类的三个函数drawPrimitive, drawComplexControl, qureySubControlMerics相关,所以我们只需重载这三个函数的相关部分代码.下面对代码中的关键部分做一下注释,不重要的部分省略了。详细的代码可以从后面下载。
  
  绘制spinbox中按钮的函数:
  
  void CustomStyle::drawPrimitive( PrimitiveElement pe,
             QPainter * p,
              const QRect & r,
              const QColorGroup & cg,
              SFlags flags,
              const QStyleOption & opt ) const
  {
  /*PE_SpinWidgetUp,PE_SpinWidgetDown表示spinBox中的下按钮和上按钮,下面的代码使得这两个按钮中的三角形分别向左和向右*/
  if ((pe == PE_SpinWidgetUp) || (pe == PE_SpinWidgetDown)){
   int fw = pixelMetric( PM_DefaultFrameWidth, 0 );//fw表示边框宽度,默认为2
   QRect br; //spinBox上按钮的边界矩形不是spinBox的边界矩形。
   br.setRect( r.x() + fw, r.y() + fw, r.width() - fw*2,
     r.height() - fw*
推荐阅读
  • 本文介绍了在Hibernate配置lazy=false时无法加载数据的问题,通过采用OpenSessionInView模式和修改数据库服务器版本解决了该问题。详细描述了问题的出现和解决过程,包括运行环境和数据库的配置信息。 ... [详细]
  • Skywalking系列博客1安装单机版 Skywalking的快速安装方法
    本文介绍了如何快速安装单机版的Skywalking,包括下载、环境需求和端口检查等步骤。同时提供了百度盘下载地址和查询端口是否被占用的命令。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 如何去除Win7快捷方式的箭头
    本文介绍了如何去除Win7快捷方式的箭头的方法,通过生成一个透明的ico图标并将其命名为Empty.ico,将图标复制到windows目录下,并导入注册表,即可去除箭头。这样做可以改善默认快捷方式的外观,提升桌面整洁度。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • windows便签快捷键_用了windows十几年,没想到竟然这么好用!隐藏的功能你知道吗?
    本文介绍了使用windows操作系统时的一些隐藏功能,包括便签快捷键、截图功能等。同时探讨了windows和macOS操作系统之间的优劣比较,以及人们对于这两个系统的不同看法。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文是一位90后程序员分享的职业发展经验,从年薪3w到30w的薪资增长过程。文章回顾了自己的青春时光,包括与朋友一起玩DOTA的回忆,并附上了一段纪念DOTA青春的视频链接。作者还提到了一些与程序员相关的名词和团队,如Pis、蛛丝马迹、B神、LGD、EHOME等。通过分享自己的经验,作者希望能够给其他程序员提供一些职业发展的思路和启示。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • Win10下游戏不能全屏的解决方法及兼容游戏列表
    本文介绍了Win10下游戏不能全屏的解决方法,包括修改注册表默认值和查看兼容游戏列表。同时提供了部分已经支持Win10的热门游戏列表,帮助玩家解决游戏不能全屏的问题。 ... [详细]
  • 如何在联想win10专业版中修改账户名称
    本文介绍了在联想win10专业版中修改账户名称的方法,包括在计算机管理中找到要修改的账户,通过重命名来修改登录名和属性来修改显示名称。同时指出了windows10家庭版无法使用此方法的限制。 ... [详细]
author-avatar
NewGuy
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有