Qt在透明QWidget上自由繪畫

2021-09-29 16:23:16 字數 3339 閱讀 1252

初學qt,需要實現這樣的效果:

在透明的qwidget上自由的繪圖,看起來就像是直接在桌面繪圖一樣。

要達到這樣的效果,需要分成兩個步驟:

如何將qwidget變得透明。

如何在透明的qwidget控制項上使用qpainter繪製圖形。

當然,第二點是widget透明之後才發現的需求,發現的過程後面會說。

兩個需求完成總共花了大概3個小時。這期間剛開始一直中文搜尋國內部落格,沒有解決任何乙個問題。最後20來分鐘沒辦法了,英文google一下吧,結果沒多久就找到了答案。

不知道為啥,國內各大部落格論壇,關於qt方面的內容又舊又亂,難道是沒有什麼新鮮血液進入了麼?

為了讓這3個小時價值最大化,於是有了這篇部落格,也算是為qt社群增磚添瓦吧。

此前,先把給我了幫助的兩個網頁掛出來鳴謝一下:

關於透明widget的

qt centre(關於透明繪製的)

接下來是正題:

先說一下被誤導的嘗試,關於讓窗體透明,網友辦法很多。

setwindowopacity(0) ;:設定完之後,窗體不會有任何顯示,就像你從來沒執行過程式一樣。除了特殊用途,一般也不會有這種需求。

setpalette(palette): 其中palette給乙個透明的當背景,或者透明的顏色值。錯誤,設定完後,窗體會變成黑色。

…不一一枚舉了…

進入整體,其實透明窗體實現相對簡單,對你想要透明的qwidget物件設定三個屬性就行了(建構函式還是main函式中設定,看你心情)。偽**如下:

setwindowflags(qt::framelesswindowhint);

setattribute(qt::wa_nosystembackground);

setattribute(qt::wa_translucentbackground);

setattribute(qt::wa_transparentformouseevents);

稍微解釋一下:

最後,來看一下每個屬性的效果,我的工程主窗體就是乙個普通的qwidget,方便起見,顯示了乙個label,並重寫了paintevent函式,使用qpainter畫了乙個橢圓。原始碼會在文末附上。

上面是什麼屬性都沒有設定的qwidget,藍色文字部分是乙個label,紅色的橢圓是用qpainter畫在qwidget上的。我們要達到的透明效果是,只能看到藍色文字和紅色橢圓,其它都是桌面背景。下面通過屬性的一步步設定,仔細觀察一下介面的變化吧。

上面是setwindowflags(qt::framelesswindowhint);**執行後的介面。qwidget的標題框消失了,但是還有預設背景。

上面是setattribute(qt::wa_nosystembackground);執行後的介面,還真的變黑了。不糾結

噹噹當~,這不就是我要的效果麼。這是執行了setattribute(qt::wa_translucentbackground);的效果。背景其實就是我的桌面背景。

接下來乙個問題就是,當qwidget變成透明背景後,居然沒法響應滑鼠了,滑鼠的事件沒有發給我的widget。來看看效果:

途中的lable的拖動效果,是因為我重寫了qwidgetmousemoveeventmousepressevent函式。**大概是這樣的:

void widget::mousepressevent(qmouseevent *event) 

void widget::mousemoveevent(qmouseevent *event)

只有滑鼠在label上時,widget才能夠響應滑鼠的拖拽動作,在qpainter畫出的紅色橢圓上,滑鼠的效果和在桌面的效果沒啥區別。無法效應滑鼠,肯定就不能作畫,畢竟我們的手繪是需要靠滑鼠或者觸控筆輸入的。那麼,怎麼讓透明的窗體相應滑鼠的各種事件呢?

在透明的窗體上,不能響應滑鼠事件,應該是透明這個因素造成的。更深層次的原因,暫時還不了解。但實驗結果如此。

說說最終的解決思路吧:

申明乙個qpixmap,變數名為cachemap。它將作為整個窗體(qwidget)的底圖。

初始化cachemap,用近乎透明的顏色填充。

在paintevent函式中,通過qpainter將cachemap繪製到窗體上,充作背景。

最終,雖然整個qwidget將會有乙個近乎透明的背景圖,也就是cachemap存在,但它幾乎時透明到人眼無法識別。對於計算機來說,就不是這樣了。於是我們完成了目標。

核心**如下:

/* 標頭檔案 */    

qpixmap *cachemap;

/* cpp檔案 建構函式中 */

cachemap = new qpixmap(this->size());

cachemap->fill(qcolor(0, 0, 0, 1));

/* cpp檔案 paintevent函式中 */

void widget::paintevent(qpaintevent *e)

最終效果如下:

對於繪圖來講,拿到了滑鼠的事件,只需要記錄滑鼠軌跡,就可以通過qpainter來繪製出軌跡了。簡單粗暴點的,可以直接將滑鼠的軌跡點全部用直線鏈結起來,也可以用bezier曲線擬合,另外可以通過控制cachemap的繪製與否,來控制滑鼠是否穿透到桌面來實現特殊的效果。當然,這些又是另的話題了。

qwidget 透明窗體

1 設定窗體的背景色 在建構函式裡新增 需要新增標頭檔案qpalette或qgui qpalette pal palette pal.setcolor qpalette background,qcolor 0x00,0xff,0x00,0x00 setpalette pal 通過設定窗體的背景色來實...

QWidget背景 透明 問題

2010年12月13日 星期一 11 13 一.背景設定為成黑色,前景色設為白色。方法一 paltette方式,經測試,該方法不會影響到其他控制項,建議使用 qpalette bgpal palette bgpal.setcolor qpalette background,qcolor 0,0 0,...

QWidget實現透明的方式

qwidget實現透明的方式 this setwindowflags qt framelesswindowhint this setattribute qt wa translucentbackground,true 重寫qwidget的paintevent qpaintevent event 函式...