一個完善的應用程序不僅應該有實用的功能,還要有一個漂亮的外觀,這樣才能使應用程序更加友好,更加吸引用戶。作為一個跨平台的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章講到的圖形效果也可以實現部件的透明效果,而且使用它還可以實現模糊、陰影和染色等特殊效果。