在Qt中設置widget背景顏色或者圖片方法很多種:重寫paintEvent() , 調色板QPalette , 樣式表setStyleSheet等等。
但是各種方法都有其注意事項,如果不注意則很容易陷入麻煩中。
1:setStyleSheet()
這個函數我一直很喜歡使用,因為只要寫一句就可以實現效果,比其他方法都簡單,但是其卻有一個很值得注意的地方,也就是這個地方讓我大吃苦頭。
亦即:①:該函數只能用於設置有父窗口的子窗口的背景!如果一個窗口沒有子窗口,則無法使用該函數來設置背景顏色或圖 片!!
②:同時:對於一個父窗口而言:如果我們用setStyleShette設置了其樣式,而對於其子窗口:如果沒有用同樣的函數來設 置的話, 則其子窗口的樣式和其父窗口完全一致,亦即:其集成了自己父窗口的樣式!
③:延伸:對頂層窗口(沒有父窗口),其有若干個子窗口,則當我們用setStyleShette來設置這個頂層窗口的樣式后,依據①可知:該父窗口本身沒有任何變化,亦即設置沒有生效;而其子窗口:只要子窗口本身沒有用setStyleShette來設置自己的樣式表,則其就是用的自己父窗口的樣式表!!
例如:
主窗口(沒有父類)為MainWin
MainWin::MainWin()
{
this->setStyleSheet("background-image:url(:/bmp/IMG_0345.JPG)");
iButton = new QPushButton(this);
iLabel = new QLabel(iButton);
}
運行一下,效果如下:
亦即:雖然我們設置的是頂層的父窗口,但是該樣式卻是在其子窗口中生效,而頂層父窗口沒有任何變化! 這驗證了①。
修改一下上例代碼:
MainWin::MainWin()
{
this->setStyleSheet("background-image:url(:/bmp/IMG_0345.JPG)");
iButton = new QPushButton(this);
iLabel = new QLabel(iButton);
iLabel->setStyleSheet("background-image:url(:/bmp/1257253475842.jpg)");
}
則運行效果如下:
可見:子窗口只有調用setStyleSheet()設置了自己的樣式后才可以隔斷父窗口的樣式,否則其將是用父窗口的樣式。
再修改一下代碼:
MainWin::MainWin()
{
iButton = new QPushButton(this);
iButton ->setStyleSheet("background-image:url(:/bmp/IMG_0345.JPG)");
iLabel = new QLabel(iButton);
}
運行一下,效果如下:
可見:設置有父窗口的子窗口時:setStyleSheet()一定生效!!!
后來我又思考了一個問題,那就是:對於頂層父窗口,如果我setStyleSheet()設置了樣式表,而對其子窗口,我用其他方法,比如用QPalette調色板來設置背景圖片/顏色,這時子窗口的背景到底是由繼承自父窗口的樣式表決定呢還是由子窗口本身的QPalette調色板決定呢?
再次修改代碼:
MainWin::MainWin()
{
this->setStyleSheet("background-image:url(:/bmp/IMG_0345.JPG)");
iButton = new QPushButton(this);
iLabel = new QLabel(iButton);
QPalette palette;
palette.setBrush(iLabel->backgroundRole(),QBrush(QImage(":/bmp/1257253475842.jpg")));
iLabel->setPalette(palette);
iLabel->setAutoFillBackground(true);
}
此段代碼中我用QPalette來設置子窗口的背景圖片,看下到底是樣式表還是調色板生效,效果如下:
由此可見:一旦頂層窗口設置了樣式表,則其子窗口無論用什么方法來設置背景,都會不生效!!!
那如果不是頂層窗口而僅僅是一般窗口設置了樣式表呢?再次修改代碼:
MainWin::MainWin()
{
iButton = new QPushButton(this);
iButton ->setStyleSheet("background-image:url(:/bmp/IMG_0345.JPG)");
iLabel = new QLabel(iButton);
QPalette palette;
palette.setBrush(iLabel->backgroundRole(),QBrush(QImage(":/bmp/1257253475842.jpg")));
iLabel->setPalette(palette);
iLabel->setAutoFillBackground(true);
}
運行效果同上,這說明:不管是頂層窗口還是一般窗口,只要用setStyleSheet設置了樣式表,則其子窗口用其它方式設置背景顏色/圖片均不生效,只能用同樣方式setStyleSheet來設置更改!!!
為了驗證上邊的結論,再次修改代碼:
MainWin::MainWin()
iButton = new QPushButton(this);
iLabel = new QLabel(iButton);
QPalette palette;
palette.setBrush(iLabel->backgroundRole(),QBrush(QImage(":/bmp/1257253475842.jpg")));
iLabel->setPalette(palette);
iLabel->setAutoFillBackground(true);
}
運行一下:
此時調色板才生效,這也間接證明了上述結論。
==========================================================================
總結:
1:不要在頂層窗口(無父類的窗口)中使用setStyleSheet() ,否則其一父窗口的背景不會改變,其次其子窗口的背景設置方法變得局限唯一,不能再使用其它方法!
2:如果一個一般窗口(非頂層窗口)還有子窗口,那最好不要使用setStyleSheet()來設置其背景顏色,因為雖然此時該窗口的背景設置是生效的,但是其子窗口的背景設置也變得局限唯一,只能使用setStyleSheet,而不能使用其它方法! 當然:你如果就是只想使用這種方法,那也完全可以!!
說白了就是:不要再MainWindow中使用setStyleSheet()!
而上邊之所以強調拓寬子窗口設置背景的方法范圍,這是因為:如果只能用setStyleSheet樣式表來設置背景圖片的話,該圖片是無法縮放的,如果其大小與widget窗口大小不相符,則我們無法用程序來實現圖片的縮放,除非我們直接處理圖片使其大小與widget窗口相符; 而如果不局限於用setStyleSheet樣式表來設置的話,我們可以選擇用QPalette調色版,其內部setBrush()之前,我們完全可以先對圖片進行scale縮放再刷到窗口上,這樣就避免直接去處理圖片,靈活性強一點!
==========================================================================
注意:該文只針對QWidget體系,並不適用用QGraphicsWidget體系!關於這兩種體系之間的區分,詳見文章http://blog.csdn.net/NRC_DouNingBo/archive/2010/05/09/5571149.aspx