[Qt教程] 第17篇 2D绘图(七)涂鸦板
生活随笔
收集整理的這篇文章主要介紹了
[Qt教程] 第17篇 2D绘图(七)涂鸦板
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
[Qt教程]?第17篇 2D繪圖(七)涂鴉板
??|?查看: 1255|?回復: 16| 涂鴉板 版權聲明 該文章原創于Qter開源社區(www.qter.org),作者yafeilinux,轉載請注明出處! 導語 通過前面幾節的學習,大家應該已經對Qt中2D繪圖有了一定的認識,這一節我們將應用前面講到的內容,編寫一個簡單的涂鴉板程序,這一節只是實現最基本的鼠標畫線功能。 環境:Windows Xp + Qt 4.8.4+QtCreator 2.6.2 目錄 一、實現涂鴉板 二、實現放大功能 正文 一、實現涂鴉板 1.新建Qt Gui應用,項目名稱為pianter_3,基類這次還用QDialog,類名保持Dialog不變即可。 2.到dialog.h文件中,先添加頭文件包含:#include?<QMouseEvent> 然后添加幾個函數的聲明: protected: ? ??void?paintEvent(QPaintEvent?*); ? ??void?mousePressEvent(QMouseEvent?*); ? ??void?mouseMoveEvent(QMouseEvent?*); ? ??void?mouseReleaseEvent(QMouseEvent?*); 第一個是繪制事件處理函數,后面分別是鼠標按下、移動和釋放事件的處理函數。 下面再添加幾個private私有變量聲明: QPixmap?pix; QPoint?lastPoint; QPoint?endPoint; 因為在函數里聲明的QPixmap類對象是臨時變量,不能存儲以前的值,為了實現保留上次的繪畫結果,我們需要將其設為全局變量。后面兩個QPoint變量存儲鼠標指針的兩個坐標值,我們需要用這兩個坐標值完成繪圖。 2.到dialog.cpp文件中,先添加頭文件包含:#include?<QPainter> 然后在構造函數中添加如下初始代碼: resize(600, 500);? ? //窗口大小設置為600*500 pix = QPixmap(200, 200); pix.fill(Qt::white); 下面添加幾個函數的定義: void?Dialog::paintEvent(QPaintEvent?*) {? ?? ? ?? ?QPainter?pp(&pix);? ??//?根據鼠標指針前后兩個位置就行繪制直線? ?? ? ?? ?pp.drawLine(lastPoint,?endPoint);? ??//?讓前一個坐標值等于后一個坐標值,這樣就能實現畫出連續的線? ?? ? ?? ?lastPoint?=?endPoint;? ?? ? ?? ?QPainter?painter(this);? ?? ? ?? ?painter.drawPixmap(0,?0,?pix);? } 這里使用了兩個點來繪制線條,這兩個點在下面的鼠標事件中獲得。 void?Dialog::mousePressEvent(QMouseEvent?*event) {? ? ? ?? ?? ?? ?? ?if(event->button()==Qt::LeftButton)?//鼠標左鍵按下? ?? ?? ? ?? ?? ?? ?? ?lastPoint?=?event->pos();? } 當鼠標左鍵按下時獲得開始點。 void?Dialog::mouseMoveEvent(QMouseEvent?*event) {? ?? ? ?? ?? ?if(event->buttons()&Qt::LeftButton)?//鼠標左鍵按下的同時移動鼠標? ?? ? ?? ???{? ?? ??? ? ?? ?? ?? ?? ?? ?endPoint?=?event->pos();? ?? ??? ? ?? ?? ?? ?? ?? ?update();?//進行繪制? ?? ? ?? ?? ?} } 當鼠標移動時獲得結束點,并更新繪制。調用update()函數會執行paintEvent()函數進行重新繪制。 void?Dialog::mouseReleaseEvent(QMouseEvent?*event) {? ? ? ?? ?? ?? ?if(event->button()?==?Qt::LeftButton)?//鼠標左鍵釋放? ?? ? ?? ?? ?? ? {? ?? ??? ? ?? ?? ?? ?? ?? ?? ? endPoint?=?event->pos();? ?? ??? ? ?? ?? ?? ?? ?? ?? ? update();? ?? ? ?? ?? ?? ? } } 當鼠標按鍵釋放時也進行重繪。 現在運行程序,使用鼠標在白色畫布上進行繪制,發現已經實現了簡單的涂鴉板功能,效果如下圖所示。 二、實現放大功能 前面已經實現了簡單的繪制功能,下面我們將實現放大功能,將畫布放大后繼續進行涂鴉。這里將使用兩種方法來實現,也是對上一節坐標系統后面的問題的更進一步的應用實踐。 1.添加放大按鈕。到dialog.h文件中,先添加頭文件: #include?<QPushButton> 然后添加下面private私有變量聲明: qreal?scale; QPushButton?*button; 最后再添加一個私有槽聲明: private?slots: ? ??void?zoomIn(); 2.到dialog.cpp文件中,先在構造函數中添加如下代碼: //設置初始放大倍數為1,即不放大 scale =1; //新建按鈕對象 button = new QPushButton(this); //設置按鈕顯示文本 button->setText(tr("zoomIn")); //設置按鈕放置位置 button->move(500, 450); //對按鈕的單擊事件和其槽函數進行關聯 connect(button, SIGNAL(clicked()), this, SLOT(zoomIn())); 這里使用代碼創建了一個按鈕對象,并將其單擊信號關聯到了放大槽上,也就是說按下這個按鈕,就會執行zoomIn()槽。 3.下面添加zoomIn()的定義: void?Dialog::zoomIn() { ? ??scale?*=2; ? ??update(); } ? ??這里我們讓每按下這個按鈕,放大值都擴大兩倍。后面調用update()函數來更新顯示。 4.?通過上一節的學習,我們應該已經知道想讓畫布的內容放大有兩個辦法,一個是直接放大畫布的坐標系統,一個是放大窗口的坐標系統。下面我們先來放大窗口的坐標系統。更改paintEvent()函數如下: void?Dialog::paintEvent(QPaintEvent?*) { ? ??QPainter?pp(&pix); ? ??pp.drawLine(lastPoint,?endPoint);? ? ? ??lastPoint?=?endPoint;? ? ? ??QPainter?painter(this); ? ??//進行放大操作 ? ??painter.scale(scale,?scale); ? ??painter.drawPixmap(0,?0,?pix); } ? ??現在運行程序,先在白色畫布上任意繪制一個圖形,效果如下圖所示。 ? ??然后按下zoomIn按鈕,效果如下圖所示。 現在再用鼠標進行繪制,發現圖形已經不能和鼠標軌跡重合了,效果如下圖所示。 有了前面一節的知識,就不難理解出現這個問題的原因了。窗口的坐標擴大了,但是畫布的坐標并沒有擴大,而我們畫圖用的坐標值是鼠標指針的,鼠標指針又是獲取的窗口的坐標值?,F在窗口和畫布的同一點的坐標并不相等,所以就出現了這樣的問題。 其實解決辦法很簡單,窗口放大了多少倍,就將獲得的鼠標指針的坐標值縮小多少倍就行了。我們將paintEvent()函數更改如下: void?Dialog::paintEvent(QPaintEvent?*) { ? ??QPainter?pp(&pix); ? ??pp.drawLine(lastPoint/scale,?endPoint/scale); ? ??lastPoint?=?endPoint; ? ??QPainter?painter(this); ? ??painter.scale(scale,?scale); ? ??painter.drawPixmap(0,?0,?pix); } 運行程序,效果如下圖所示??梢钥吹?#xff0c;已經能夠在放大以后繼續繪圖了。 這種用改變窗口坐標大小來改變畫布面積的方法,實際上是有損圖片質量的。就像將一張位圖放大一樣,越放大越不清晰。原因就是,它的像素的個數沒有變,如果將可視面積放大,那么單位面積里的像素個數就變少了,所以畫質就差了。 5.方法二。擴大畫布坐標系統。先將paintEvent()更改如下: void?Dialog::paintEvent(QPaintEvent?*) { ? ??QPainter?pp(&pix); ? ??pp.scale(scale,?scale); ? ??pp.drawLine(lastPoint,endPoint); ? ??lastPoint?=?endPoint; ? ??QPainter?painter(this); ? ??painter.drawPixmap(0,?0,?pix); } 這時運行程序,先進行繪制,然后點擊zoomIn按鈕,發現以前的內容并沒有放大,而當我們再次繪畫時,發現鼠標指針和繪制的線條又不重合了。效果如下圖所示。 這并不是我們想要的結果,為了實現按下放大按鈕,畫布和圖形都進行放大,我們可以使用緩沖畫布(就是一個輔助畫布)來實現。將paintEvent()函數內容更改如下。 void?Dialog::paintEvent(QPaintEvent?*) { ? ??if(scale!=1)?//如果進行放大操作 ? ??{ ? ?? ??//臨時畫布,大小變化了scale倍 ? ?? ??QPixmap?copyPix(pix.size()*scale); ? ?? ??QPainter?pter(©Pix); ? ?? ??pter.scale(scale,?scale); ? ?? ??//將以前畫布上的內容復制到現在的畫布上 ? ?? ??pter.drawPixmap(0,?0,?pix); ? ?? ??//將放大后的內容再復制回原來的畫布上 ? ?? ??pix?=?copyPix; ? ?? ??//讓scale重新置1 ? ?? ??scale?=1; ? ??} ? ??QPainter?pp(&pix); ? ??pp.scale(scale,scale); ? ??pp.drawLine(lastPoint/scale,endPoint/scale); ? ??lastPoint?=?endPoint; ? ??QPainter?painter(this); ? ??painter.drawPixmap(0,0,pix); } 現在運行程序,效果如下圖所示。 結語 ? ?? ?本節講到的涂鴉板,只是為了實踐前面的知識,起到拋磚引玉的作用。大家可以根據自己的理解繼續探究下去。在下一節,我們將講解怎樣在涂鴉板上繪制出矩形、橢圓等圖形。 涉及到的源碼:??painter_3.zip?? |
總結
以上是生活随笔為你收集整理的[Qt教程] 第17篇 2D绘图(七)涂鸦板的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Qt教程] 第16篇 2D绘图(六)坐
- 下一篇: [Qt教程] 第18篇 2D绘图(八)双