日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[Qt教程] 第17篇 2D绘图(七)涂鸦板

發布時間:2024/4/20 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [Qt教程] 第17篇 2D绘图(七)涂鸦板 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

[Qt教程]?第17篇 2D繪圖(七)涂鴉板

樓主 ?發表于 2013-5-2 21:37:41?|?查看: 1255|?回復: 16
涂鴉板

版權聲明
該文章原創于Qter開源社區(www.qter.org),作者yafeilinux,轉載請注明出處!


導語
通過前面幾節的學習,大家應該已經對Qt2D繪圖有了一定的認識,這一節我們將應用前面講到的內容,編寫一個簡單的涂鴉板程序,這一節只是實現最基本的鼠標畫線功能。

環境: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按鈕,效果如下圖所示。


現在再用鼠標進行繪制,發現圖形已經不能和鼠標軌跡重合了,效果如下圖所示。

有了前面一節的知識,就不難理解出現這個問題的原因了。窗口的坐標擴大了,但是畫布的坐標并沒有擴大,而我們畫圖用的坐標值是鼠標指針的,鼠標指針又是獲取的窗口的坐標值。現在窗口和畫布的同一點的坐標并不相等,所以就出現了這樣的問題。 其實解決辦法很簡單,窗口放大了多少倍,就將獲得的鼠標指針的坐標值縮小多少倍就行了。我們將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); } 運行程序,效果如下圖所示。可以看到,已經能夠在放大以后繼續繪圖了。

這種用改變窗口坐標大小來改變畫布面積的方法,實際上是有損圖片質量的。就像將一張位圖放大一樣,越放大越不清晰。原因就是,它的像素的個數沒有變,如果將可視面積放大,那么單位面積里的像素個數就變少了,所以畫質就差了。

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(&copyPix); ? ?? ??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?(2.65 KB, 下載次數: 22)?

總結

以上是生活随笔為你收集整理的[Qt教程] 第17篇 2D绘图(七)涂鸦板的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。