Skin(表皮) 是制作比較酷的軟件界面的有利工具. 一個(gè)軟件可以同時(shí)使用多種Skin 以取得不同的外觀, 使同一個(gè)軟件有截然不同的風(fēng)格. 用戶可以根據(jù)自己的喜好選擇 不同的風(fēng)格. 本節(jié)介紹使用 Qt 制作 Skin 的方法.
軟件界面的風(fēng)格變化可以通過兩種機(jī)制完成,一種是通過設(shè)置主題(Themes),它使用 界面庫本身所具有的對界面組件(Components)的控制能力切換顯示風(fēng)格;另外一種是 通過提供不同系列的圖片來切換顯示界面,即這里所講的 Skin。
制作表皮有幾個(gè)重要的因素值得考慮:
1. 使用無邊界的窗口
在 XWindow 下,無邊界的窗口是指不受窗口管理器管理的邊界不規(guī)則的窗口。由于不受窗口管理器管理管理,所以軟件窗口界面沒有附加的標(biāo)題條(Title Bar)等。 在Qt中,建立無邊界窗口的最簡單的方法 是設(shè)置 QWidget 的 WFlags 的值是 WStyle_NoBorder。它定義在 qnamespace.h 中。不規(guī)則窗口的特點(diǎn)則要求對整個(gè) 窗口使用圖像掩碼。使用 X 窗口形狀的擴(kuò)展(X Shape Extension)來達(dá)到要求。在 Qt 中可以直接使用,
QBitmap bm;
bm = *(Pixmaps[MASK]);
setMask(bm);
setBackgroundPixmap(*Pixmaps[BACKGROUND]);
2. 窗口的移動(dòng)
由于上述窗口不受窗口管理器的管理的特性,所以移動(dòng)窗口需要特殊處理,一般的 方法是截取根Widget的鼠標(biāo)按鈕事件,自己處理鼠標(biāo)點(diǎn)擊和移動(dòng)的事件。
void SkinDemo::mouseMoveEvent(QMouseEvent *e)
{
QPoint newpos = e->globalPos();
QPoint upleft = pos0 + newpos - last;
move(upleft);
}
void SkinDemo::mousePressEvent(QMouseEvent *e)
{
last = e->globalPos();
pos0 = e->globalPos() - e->pos();
}
這里我們?nèi)〉玫氖髽?biāo)位置是絕對位置,即相對于根窗口的位置,同時(shí)也記錄下窗口 左上角的位置,當(dāng)鼠標(biāo)移動(dòng)時(shí),取得新的絕對位置,則窗口左上角 的新位置應(yīng)該 是原來位置與鼠標(biāo)移動(dòng)的位置之差。
3. 按鈕的制作
在 例子( qt-skin-example.tar.gz) 中,我們重新定義了鼠標(biāo)按下和鼠標(biāo)移動(dòng)的事件處理 函數(shù),并且含有按鈕的所有信息,主工作區(qū)的所有信息等。主工作區(qū)的信息是它的位置和尺寸,主窗口的信息是它所使用的背景圖片和圖片的掩碼(用來制造不規(guī)則 窗口),所以整個(gè)主窗口的大小可以由圖片的尺寸來決定。幾個(gè)按鈕的信息包含它們的 位置,它們的大小由圖片的大小來決定。
對于表皮中的圖像按鈕, 設(shè)置它的父類是 QButton,這種按鈕由兩幅圖片構(gòu)成,一幅圖片是正常狀態(tài)(Normal),一幅圖片是按鈕按下時(shí)的狀態(tài)(Activated)。有時(shí)也可以設(shè)置成四 種狀態(tài),即增加禁止?fàn)顟B(tài)(Disabled)和鼠標(biāo)指針進(jìn)入時(shí)的狀態(tài) (Hovered)。Qt3 的手工代碼實(shí)現(xiàn):
#include <qapplication.h>
#include <qwidget.h>
#include <qpixmap.h>
#include <qbitmap.h>
#include <qpoint.h>
class myclass:public QWidget
{
public:
myclass();
protected:
void mouseMoveEvent(QMouseEvent *e);
void mousePressEvent(QMouseEvent *e);
private:
QPixmap *pixmap;
QBitmap *bitmap;
QPoint last,pos0;
};
myclass::myclass()
{
setGeometry(0,0,120,120);
pixmap=new QPixmap("/doc/test/a/tmp.png");
bitmap=new QBitmap("/doc/test/a/mask.png");
setPaletteBackgroundPixmap(*pixmap);
setMask(*bitmap);
}
void myclass::mouseMoveEvent(QMouseEvent *e)
{
if(e->state()==LeftButton)
{
QPoint newpos = e->globalPos();
QPoint upleft = pos0 + newpos - last;
move(upleft);
}
}
void myclass::mousePressEvent(QMouseEvent *e)
{
last = e->globalPos();
pos0 = e->globalPos() - e->pos();
}
int main(int argc,char *argv[])
{
QApplication a(argc,argv);
myclass w;
a.setMainWidget(&w);
w.show();
return a.exec();
}