Qt界面外观之一:Qt风格与特殊效果窗体

时间:2024-03-17 14:38:31

一个完善的应用程序不仅应该有实用的功能,还要有一个漂亮的外观,这样才能使应用程序更加友好,更加吸引用户。作为一个跨平台的UI开发框架,Qt提供了强大而灵活的界面外观设计机制。这一章将学习在Qt中设计应用程序外观的相关知识,会对Qt风格QStyle和调色板QPalette进行简单介绍,以及介绍不规则窗体和透明窗体的实现方法。


一、Qt风格

Qt中的各种风格是一组继承自QStyle的类。QStyle类是一个抽象基类,封装了 一个GUI的外观,Qt的内建(built-in)部件使用它来执行几乎所有的绘制工作,以确保它们看起来可以像各个平台上的本地部件一样。一些风格已经内置在了Qt中,例如Winders风格和Motif风格;而有些风格只在特定的平台上才有效,例如Windows XP风格、Windows Vista风格和Mac OS X风格。Qt提供的风格类如下表所列。

类名 介绍
QCDEStyle CDE(Common Desktop Environment)风格
QCleanlooksStyle 类似于GNOME中的Clearlook风格
QGtkStyle GTK +风格
QMotifStyle Motif风格
QMacStyle Mac OS X风格
QPlastiqueStylc 类似于KDE中的Plastik风格
QWindowsStyle 微软Windows风格
QWindowsVistaStyle 微软Windows Vista风格
QWinclowsXPStyle 微软Windows XP风格

在使用Qt Creator设计模式设计界面时,可以使用Qt提供的各种风格进行预览, 当然也可以使用特定的风格来运行程序。下面来看具体的例子。

1.1 使用不同风格预览程序

新建Qt Gui应用,项目名称为myStyle,类名为MainWindow,基类保持QMainWindow不变。建立完项目后,单击mainwindow. ui文件进入设计模式,向界面上拖人一个Label、Push Button、 Spin Box、Line Edit 和 Progress Bar。 然后选择“工具→From Editor→Preview in”菜单项,这里列出了现在可用的几种风格,这里选择“CDE风格”,预览效果如图8-1所示。也可以使用其他几种风格进行预览。


1.2 使用不同风格运行程序

如果想使用不同的风格来运行程序,那么只需要调用QApplication的setStyle()函数指定要使用的风格即可。现在打开main.cpp文件,然后添加#include <QMotifStyle>头文件包含(注意windows下的Qt版本不包含该头文件),并在main()函数的“QApplication a(argc,argv);”一行代码后添加如下一行代码:

a.setStyle(new QMotifStyle);

这时运行程序,便会使用Motif风格。如果不想在程序中指定风格,而是想在运行程序时再指定,那么就可以在使用命令行运行程序时通过添加参数来指定,比如要使用Motif风格,则可以使用“-style motif”参数。而如果不想整个应用程序都使用相同的风格,那么可以调用部件的setStyle()函数来指定该部件的风格。进人mainwindow. cpp文件,先添加头文件#include <QWindowsXPStyle>(在最新的Qt5中已经去掉了该类,使用QCommonStyle替换),然后在构造函数中添加如下一行代码:

ui->progressBar->setStyle(new QWindowsXPStyle);

这时再次运行程序,其中的进度条部件就会使用Windows XP的风格了。另外,还可以使用QStyleFactory::keys()函数来获取当前系统所支持的风格。

除了Qt中提供的这些风格外,也可以自定义风格,一般的做法是子类化Qt的风格类,或者子类化QStyle类。关于这个内容这里不再讲述,有兴趣的读者可以查看Styles示例程序,它在Widgets分类下。关于Qt风格更多的内容,可以查看Styles and Style Aware Widgets关键字。

1.3 调色板

调色板QPalette类包含了部件各种状态的颜色组。一个调色板包含3种状态:激活(Active)、失效(Disabled)和非激活(Inactive)。Qt中的所有部件都包含一个调色板,并且使用各自的调色板来绘制它们自身,这样可以使用户界面更容易配置,也更容易保持一致。调色板中的颜色组包括:

  • 激活颜色组QPalette::Active,用于获得键盘焦点的窗口;
  • 非激活颜色组QPalette::Inactive,用于其他的窗口;
  • 失效颜色组QPalette::Disabled,用于由于一些原因而不可用的部件(不是窗口)。

要改变一个应用程序的调色板,可以先使用QAppliCation::palette()函数来获取其调色板,然后对其进行更改,最后再使用QApplication::SetPalette()函数来使用该调色板。更改了应用程序的调色板,会影响到该程序的所有窗口部件。如果要改变一个部件的调色板,可以调用该部件的palette()和setPalette()函数,这样只会影响该部件及其子部件。下面来看一个例子。

仍然在前面的程序中进行更改。在mainwindow.cpp文件中添加头文件#include <QPalette>,然后在构造函数中继续添加如下代码:

//获取 pushButton 的调色板
QPalette palette1 = ui->pushButton->palette();
//设置按钮文本颜色为红色
palette1.setColor(QPalette::ButtonText,Qt::red);
//设置按钮背景色为绿色
palette1.setColor(QPalette::Button,Qt::green);
//pushButton 使用修改后的调色板
ui->pushButton->setPalette(palette1);
//设置 lineEdit 不可用
ui->lineEdit->setDisabled(true);
QPalette palette2 = ui->lineEdit->palette();
//设置行编辑器不可用时的背景颜色为蓝色
palette2.setColor(QPalette::Disabled,QPalette::Base,Qt::blue);
ui->lineEdit->setPalette(palette2);

设置调色板颜色时可以使用setColor()函数,这个函数需要指定颜色角色(Color Role)。在QPalette中,颜色角色用来指定该颜色所起的作用,例如是背景颜色或者是文本颜色等,主要的颜色角色如下表所列。对于在设计模式中添加到界面上的部 件,也可以在其属性编辑器中通过修改palette属性来设置它的调色板,这样还可以预览修改后的效果。对于调色板更多的知识,可以参考QPalette类的帮助文档。

常量 描述
QPalette::Window 一个一般的背景颜色
QPalette::WindowText 一个一般的前景颜色
QPalette::Base 主要作为输人部件(如QLineEdit)的背贵色,也可用作QComboBox的下拉列表的背景色
QPalette::AlternateBase 在交种行颜色的视图中作为交替背景色
QPalette::ToolTipBase 作为QToolTip和QWhatsThis的背景色
QPalette::ToolTipText 作为QToolTip和QWhatsThis的前景色
QPalette::Text 和Base—起使用,作为前景色
QPalette::Button 按钮部件背景色
QPalette::ButtonText 按钮部件前景色


二、特殊效果窗体

2.1 不规则窗体

使用样式表可以实现矩形、圆形等规则形状的部件,不过,有时想设计一个不规则形状的部件或者窗口,以使得应用程序的外观更加个性化。Qt中提供了部件遮罩 (mask)来实现不规则窗体。
新建Qt Gui应用,项目名称为myMask,基类选择QWidget,类名保持Widget不变。建立好项目后向项目目录中放一张背景透明的png图片(这里是yafeilinux. png),然后再向项目中添加一个Qt资源文件, 建立好后先添加前缀“/image”,然后再将png图片添加进来并保存更改。下面进人widget.h文件,声明两个事件处理函数:

protected:
    void paintEvent(QPaintEvent *);
    void mousePressEvent(QMouseEvent *);

然后到widget.cpp文件中,先添加头文件包含:

#include <QPixmap>
#include <QBitmap>
#include <QPainter>

再在构造函数中添加如下代码:

QPixmap pix;
// 加载图片
pix.load(":/image/yafeilinux.png");
// 设置窗口大小为图片大小
resize(pix.size());
// 为窗口设置遮罩
setMask(pix.mask());

这里使用QPixmap类加载了资源文件中的图片,然后调用setMask()函数来为窗口设置遮罩。下面是两个事件处理函数的定义:

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    // 从窗口左上角开始绘制图片
    painter.drawPixmap(0, 0, QPixmap(":/image/yafeilinux.png"));
}

void Widget::mousePressEvent(QMouseEvent *)
{   // 关闭窗口
    close();
}

这里必须在paintEvent()函数中将图片绘制在窗口上,这样运行程序时才可以正常显示图片。在鼠标按下事件中,只是进行了简单的关闭窗口操作。

这个程序使用了一张图片来设置遮罩,其实还可以使用QRegion设置一个区域来作为遮罩,这个就不再讲解了。

2.2 透明窗体

如果想实现窗体内容部件的透明效果,只需在设置其背景色时指定alpha值即可,例如:

QPushButton{background-color:rgba(255, 255, 255, 100)}

其中rgba()中的a就是指alpha,取值为0〜255,取值为0时完全透明,取值为255时完全不透明。这里a的值为100,这样会出现半透明的效果,因为前面的r(红)、g (绿)、b(蓝)的值均为255,所以是白色,这样最终的效果是按钮的背景为半透明的白色。

部件的透明效果可以使用这种方式来设置,但是,作为*部件的窗口却无法使用这种方式来实现透明效果。不过,可以使用其他两种方法来实现透明效果。

新建Qt Gui应用,项目名称为myTranslucent,基类选择QWidget,类名保持Widget不变。建好项目后,在设计模式向界面上拖入一个Label、Push Button和Progress Bar,然后在widget.cpp文件中的构造函数里添加一行代码:

// 设置窗口的不透明度为0.5
setWindowOpacity(0.5);

使用setWindowOpacity()函数就可以实现窗口的透明效果,参数取值范围为0.0〜1.0,当取值为0.0时完全透明,取值为1.0时完全不透明。这时运行程序,效果如下图所示。可以看到,这样实现的效果是整个应用程序界面都是半透明的,如果不想让窗口中部件透明,那该怎么实现呢?下面来看另一种方法。

先将构造函数中的setWindowOpacity()函数调用注释掉,然后再添加下面两行代码:

setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);

这里使用了setAttribute()函数指定窗口的Qt::WA_TranslucentBackground属性,它可以使窗体背景透明,而其中的部件不受影响。不过在Windows下,还要使用setWindowFlags()函数指定Qt::FramelessWindowHint标志,这样才能实现透明效果。运行程序,效果如图8-6所示。读者会发现,窗口没有了标题栏,这时要想关闭窗口,就要使用Qt Creator的应用程序输出栏上的红色按钮来强行关闭程序。这样实现的效果是背景完全透明的,要是还想实现半透明效果,可以使用重绘事件。

先在widget.h文件中声明paintEvent()函数:

protected:
    void paintEvent(QPaintEvent *);

然后到widget.cpp文件中添加头文件#include <QPainter>,再进行paintEvent()函数的定义:

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.fillRect(rect(), QColor(255,255,255,100));
}

这里先使用rect()函数获取窗口的内部矩形,它不包含任何边框。然后使用半透明的白色对这个矩形进行填充,最终的效果如下图所示。对于fillRect()函数,可以指定任意的一个区域,所以可以实现窗体的部分区域全部透明,部分区域半透明或者不透明的效果。

使用第一种方法会使整个应用程序都成为半透明效果;而使用第二种方法,可以实现只是顶层窗口的背景透明,不过,它没有了标题栏和边框,需要手动为其添加一个标题栏。其实,对于一个个性化的窗体界面,没有标题栏也许正是想要的结果。

另外,使用第11章讲到的图形效果也可以实现部件的透明效果,而且使用它还可以实现模糊、阴影和染色等特殊效果。