這兩天在使用QPainter的過程中出現了一些問題,記錄一下。
測試程序很簡單,寫一個繼承自QWidget的類,重載其paintEvent函數進行繪圖。
case1:
在paintEvent函數中使用一個臨時的painter對象進行繪制。
結果:能夠正常繪制。
case2:
在paintEvent函數中動態分配一個painter對象進行繪制。
結果:能夠正常繪制。
case3:將Painter聲明為一個類的成員變量進行繪制。
結果:不能正常繪制
分析:由於我在初始化m_painter時,用到的是QPainter m_painter(this);
這句代碼等於QPainter m_painter,m_painter.begin(this);
但是m_painter.begin()函數只有在paintEvent()函數中調用才是有意義的(Qt中的繪制動作只能在paintEvent()函數中完成)
由於此時begin()函數隱式在構造函數中被調用了,最終倒是繪圖動作失效。
試探的解決辦法:在用不帶參數的構造函數初始化painter,然后再paintEvent函數中利用begin函數為painter綁定對象。
試探的解決方法的結果;窗體先是正常繪制,接着就崩潰了,並報出如下錯誤:
我原本的思路是:當MyWidget對象析構是,就會自動調用其內部成員變量painter的析構函數,所以我就沒有顯式的嗲用end()函數,因為我希望painter對象能夠在MyWidget的聲明周期中一直存在。
結果:程序提醒我在繪制完成后必須調用end()函數,難道QPainter對象是一個一次性消耗品,用完一次就得扔?
果然,當加上end()代碼后,程序就沒問題了。
但是,調用end()函數中,m_painter對象就等於析構了。當我第二次進行繪制動作時,會不會出現問題?
結果是並不會,因此當進行隱藏以及重現窗體,更改窗體大小這些動作時(這些動作都會觸發窗體的重繪操作),窗體並沒有崩潰。
這里我有點疑惑,難道時begin()函數為m_painter重新分配了資源?可按理來說,已經析構的對象時無法再次使用的。。
Qt的文檔上並沒有相關的解答。
總之:從這個例子中我可以體會到painter的構造析構函數與begin()end()函數是有區別的。
case4:以一個QPainter對象的指針作為類成員變量,為這個指針分配資源。
如是在構造函數中以帶參數的構造函數來初始化QPainter對象,依然會出現上面的錯誤。
一個嘗試:我故意不用end()函數結束繪制,而選擇delete掉m_painter;
程序果然崩潰了:
總結:end()函數和delete是有區別的,end()之后還能再begin(),在delete之后,該對象就徹底消失了。
小小感觸:最好還是將QPainter對象當成一個一次消耗品來用吧,即在需要繪圖時創建一個臨時的QPainter對象來進行繪制。