天天看點

[Qt教程] 第17篇 2D繪圖(七)塗鴉闆 [Qt教程] 第17篇 2D繪圖(七)塗鴉闆

<a target="_blank" href="http://bbs.qter.org/forum.php?mod=viewthread&amp;tid=119">樓主</a>

[Qt教程] 第17篇 2D繪圖(七)塗鴉闆 [Qt教程] 第17篇 2D繪圖(七)塗鴉闆

 發表于 2013-5-2 21:37:41 | 檢視:

1255| 回複: 16

塗鴉闆

版權聲明

導語

       通過前面幾節的學習,大家應該已經對qt中2d繪圖有了一定的認識,這一節我們将應用前面講到的内容,編寫一個簡單的塗鴉闆程式,這一節隻是實作最基本的滑鼠畫線功能。

環境:windows xp + qt 4.8.4+qtcreator 2.6.2

目錄

一、實作塗鴉闆

二、實作放大功能

正文

1.建立qt gui應用,項目名稱為pianter_3,基類這次還用qdialog,類名保持dialog不變即可。

2.到dialog.h檔案中,先添加頭檔案包含:#include &lt;qmouseevent&gt;

然後添加幾個函數的聲明:

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 &lt;qpainter&gt;

然後在構造函數中添加如下初始代碼:

resize(600, 500);    //視窗大小設定為600*500

pix = qpixmap(200, 200);

pix.fill(qt::white);

下面添加幾個函數的定義:

void dialog::paintevent(qpaintevent *)

{    

      qpainter pp(&amp;pix); 

  // 根據滑鼠指針前後兩個位置就行繪制直線    

      pp.drawline(lastpoint, endpoint); 

  // 讓前一個坐标值等于後一個坐标值,這樣就能實作畫出連續的線    

      lastpoint = endpoint; 

      qpainter painter(this); 

      painter.drawpixmap(0, 0, pix); 

}

       這裡使用了兩個點來繪制線條,這兩個點在下面的滑鼠事件中獲得。

void dialog::mousepressevent(qmouseevent *event)

{   

               if(event-&gt;button()==qt::leftbutton) //滑鼠左鍵按下 

               lastpoint = event-&gt;pos(); 

       當滑鼠左鍵按下時獲得開始點。

void dialog::mousemoveevent(qmouseevent *event)

         if(event-&gt;buttons()&amp;qt::leftbutton) //滑鼠左鍵按下的同時移動滑鼠 

        {        

                  endpoint = event-&gt;pos(); 

                  update(); //進行繪制 

         }

當滑鼠移動時獲得結束點,并更新繪制。調用update()函數會執行paintevent()函數進行重新繪制。

void dialog::mousereleaseevent(qmouseevent *event)

            if(event-&gt;button() == qt::leftbutton) //滑鼠左鍵釋放 

             {        

                      endpoint = event-&gt;pos(); 

                      update();    

             }

       當滑鼠按鍵釋放時也進行重繪。

       現在運作程式,使用滑鼠在白色畫布上進行繪制,發現已經實作了簡單的塗鴉闆功能,效果如下圖所示。

[Qt教程] 第17篇 2D繪圖(七)塗鴉闆 [Qt教程] 第17篇 2D繪圖(七)塗鴉闆

       前面已經實作了簡單的繪制功能,下面我們将實作放大功能,将畫布放大後繼續進行塗鴉。這裡将使用兩種方法來實作,也是對上一節坐标系統後面的問題的更進一步的應用實踐。

1.添加放大按鈕。到dialog.h檔案中,先添加頭檔案:

#include &lt;qpushbutton&gt;

然後添加下面private私有變量聲明:

qreal scale;

qpushbutton *button;

最後再添加一個私有槽聲明:

private slots:

    void zoomin();

2.到dialog.cpp檔案中,先在構造函數中添加如下代碼:

//設定初始放大倍數為1,即不放大

scale =1;

//建立按鈕對象

button = new qpushbutton(this);

//設定按鈕顯示文本

button-&gt;settext(tr("zoomin"));

//設定按鈕放置位置

button-&gt;move(500, 450);

//對按鈕的單擊事件和其槽函數進行關聯

connect(button, signal(clicked()), this, slot(zoomin()));

       這裡使用代碼建立了一個按鈕對象,并将其單擊信号關聯到了放大槽上,也就是說按下這個按鈕,就會執行zoomin()槽。

3.下面添加zoomin()的定義:

void dialog::zoomin()

{

    scale *=2;

    update();

    這裡我們讓每按下這個按鈕,放大值都擴大兩倍。後面調用update()函數來更新顯示。

4. 通過上一節的學習,我們應該已經知道想讓畫布的内容放大有兩個辦法,一個是直接放大畫布的坐标系統,一個是放大視窗的坐标系統。下面我們先來放大視窗的坐标系統。更改paintevent()函數如下:

    qpainter pp(&amp;pix);

    pp.drawline(lastpoint, endpoint); 

    lastpoint = endpoint; 

    qpainter painter(this);

    //進行放大操作

    painter.scale(scale, scale);

    painter.drawpixmap(0, 0, pix);

    現在運作程式,先在白色畫布上任意繪制一個圖形,效果如下圖所示。

[Qt教程] 第17篇 2D繪圖(七)塗鴉闆 [Qt教程] 第17篇 2D繪圖(七)塗鴉闆

    然後按下zoomin按鈕,效果如下圖所示。

[Qt教程] 第17篇 2D繪圖(七)塗鴉闆 [Qt教程] 第17篇 2D繪圖(七)塗鴉闆

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

[Qt教程] 第17篇 2D繪圖(七)塗鴉闆 [Qt教程] 第17篇 2D繪圖(七)塗鴉闆

有了前面一節的知識,就不難了解出現這個問題的原因了。視窗的坐标擴大了,但是畫布的坐标并沒有擴大,而我們畫圖用的坐标值是滑鼠指針的,滑鼠指針又是擷取的視窗的坐标值。現在視窗和畫布的同一點的坐标并不相等,是以就出現了這樣的問題。

其實解決辦法很簡單,視窗放大了多少倍,就将獲得的滑鼠指針的坐标值縮小多少倍就行了。我們将paintevent()函數更改如下:

    pp.drawline(lastpoint/scale, endpoint/scale);

    lastpoint = endpoint;

       運作程式,效果如下圖所示。可以看到,已經能夠在放大以後繼續繪圖了。

[Qt教程] 第17篇 2D繪圖(七)塗鴉闆 [Qt教程] 第17篇 2D繪圖(七)塗鴉闆

這種用改變視窗坐标大小來改變畫布面積的方法,實際上是有損圖檔品質的。就像将一張位圖放大一樣,越放大越不清晰。原因就是,它的像素的個數沒有變,如果将可視面積放大,那麼機關面積裡的像素個數就變少了,是以畫質就差了。

5.方法二。擴大畫布坐标系統。先将paintevent()更改如下:

    pp.scale(scale, scale);

    pp.drawline(lastpoint,endpoint);

       這時運作程式,先進行繪制,然後點選zoomin按鈕,發現以前的内容并沒有放大,而當我們再次繪畫時,發現滑鼠指針和繪制的線條又不重合了。效果如下圖所示。

[Qt教程] 第17篇 2D繪圖(七)塗鴉闆 [Qt教程] 第17篇 2D繪圖(七)塗鴉闆

       這并不是我們想要的結果,為了實作按下放大按鈕,畫布和圖形都進行放大,我們可以使用緩沖畫布(就是一個輔助畫布)來實作。将paintevent()函數内容更改如下。

    if(scale!=1) //如果進行放大操作

    {

       //臨時畫布,大小變化了scale倍

       qpixmap copypix(pix.size()*scale);

       qpainter pter(&amp;copypix);

       pter.scale(scale, scale);

       //将以前畫布上的内容複制到現在的畫布上

       pter.drawpixmap(0, 0, pix);

       //将放大後的内容再複制回原來的畫布上

       pix = copypix;

       //讓scale重新置1

       scale =1;

    }

    pp.scale(scale,scale);

    pp.drawline(lastpoint/scale,endpoint/scale);

    painter.drawpixmap(0,0,pix);

       現在運作程式,效果如下圖所示。

[Qt教程] 第17篇 2D繪圖(七)塗鴉闆 [Qt教程] 第17篇 2D繪圖(七)塗鴉闆

結語

      本節講到的塗鴉闆,隻是為了實踐前面的知識,起到抛磚引玉的作用。大家可以根據自己的了解繼續探究下去。在下一節,我們将講解怎樣在塗鴉闆上繪制出矩形、橢圓等圖形。

涉及到的源碼: 

[Qt教程] 第17篇 2D繪圖(七)塗鴉闆 [Qt教程] 第17篇 2D繪圖(七)塗鴉闆

kb, 下載下傳次數: 22)