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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【Qt】2D绘图之涂鸦板

發(fā)布時(shí)間:2024/4/24 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Qt】2D绘图之涂鸦板 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

00. 目錄

文章目錄

    • 00. 目錄
    • 01. 概述
    • 02. 開發(fā)環(huán)境
    • 03. 程序設(shè)計(jì)(基本功能)
    • 04. 程序設(shè)計(jì)(放大功能)
    • 05. 程序設(shè)計(jì)(放大功能)
    • 06. 附錄

01. 概述

結(jié)合前面所學(xué)內(nèi)容,編寫一個(gè)簡單的涂鴉板程序。

02. 開發(fā)環(huán)境

Windows系統(tǒng):Windows10

Qt版本:Qt5.15或者Qt6

03. 程序設(shè)計(jì)(基本功能)

3.1 新建Qt Widgets應(yīng)用,項(xiàng)目名稱為12Draw,基類這次還用QDialog,類名保持Dialog不變即可。

3.2 到dialog.h文件中,先添加頭文件包含:#include ,然后添加幾個(gè)事件處理函數(shù)的聲明:

protected:void paintEvent(QPaintEvent *);void mousePressEvent(QMouseEvent *);void mouseMoveEvent(QMouseEvent *);void mouseReleaseEvent(QMouseEvent *);

3.3 再添加幾個(gè)private私有變量定義:

private:QPixmap pix;QPoint lastPoint;QPoint endPoint;

因?yàn)樵谇懊娼坛讨泻瘮?shù)里定義的QPixmap類對(duì)象是臨時(shí)的,不能存儲(chǔ)以前的值,為了實(shí)現(xiàn)保留上次的繪畫結(jié)果,我們需要將其設(shè)為全局變量。后面兩個(gè)QPoint變量存儲(chǔ)鼠標(biāo)指針的兩個(gè)坐標(biāo)值,我們需要用這兩個(gè)坐標(biāo)值完成繪圖。

3.4 在dialog.cpp文件中,先添加頭文件包含:#include ,然后在構(gòu)造函數(shù)中添加如下初始代碼:

//設(shè)置窗口大小resize(600, 500);//設(shè)置畫布大小和背景pix = QPixmap(200, 200);pix.fill(Qt::white);

3.5 在paintEvent添加如下代碼

//繪圖事件 void Dialog::paintEvent(QPaintEvent *) {QPainter p(&pix);//根據(jù)鼠標(biāo)指針前后兩個(gè)位置繪制直線p.drawLine(lastPoint, endPoint);//前一個(gè)坐標(biāo)值等于后一個(gè)坐標(biāo)值lastPoint = endPoint;QPainter painter(this);painter.drawPixmap(0, 0, pix); }

3.6 在mousePressEvent添加如下代碼

void Dialog::mousePressEvent(QMouseEvent *e) {if (e->button() == Qt::LeftButton){lastPoint = e->pos();}endPoint = lastPoint; }

當(dāng)鼠標(biāo)左鍵按下時(shí)獲得開始點(diǎn),每次開始繪制都讓結(jié)束點(diǎn)和開始點(diǎn)重合,這樣確保這兩個(gè)點(diǎn)的值都是預(yù)期的值。

3.7 在mouseMoveEvent添加如下代碼

//鼠標(biāo)移動(dòng)事件 void Dialog::mouseMoveEvent(QMouseEvent *e) {if (e->button() & Qt::LeftButton){endPoint = e->pos();update();} }

當(dāng)鼠標(biāo)移動(dòng)時(shí)獲得結(jié)束點(diǎn),并更新繪制,注意這里的buttons()函數(shù)可以獲取鼠標(biāo)移動(dòng)過程中按下的所有按鍵,然后用&Qt::LeftButton來判斷是否按下了左鍵,在mouseMoveEvent()中必須使用該方法來判斷按下的鼠標(biāo)按鍵。最后調(diào)用update()函數(shù)會(huì)執(zhí)行paintEvent()函數(shù)進(jìn)行重新繪制。

3.8 在mouseReleaseEvent添加如下代碼

//鼠標(biāo)釋放事件 void Dialog::mouseReleaseEvent(QMouseEvent *e) {if (e->button() == Qt::LeftButton){endPoint = e->pos();update();}}

當(dāng)鼠標(biāo)按鍵釋放時(shí)也進(jìn)行重繪。現(xiàn)在運(yùn)行程序,使用鼠標(biāo)在白色畫布上進(jìn)行繪制,發(fā)現(xiàn)已經(jīng)實(shí)現(xiàn)了簡單的涂鴉板功能,效果如下圖所示。

04. 程序設(shè)計(jì)(放大功能)

4.1 添加放大按鈕。到dialog.h文件中,先添加頭文件:

#include <QDialog> #include <QMouseEvent> #include <QPushButton>QT_BEGIN_NAMESPACE namespace Ui { class Dialog; } QT_END_NAMESPACEclass Dialog : public QDialog {Q_OBJECTpublic:Dialog(QWidget *parent = nullptr);~Dialog();protected:void paintEvent(QPaintEvent *);void mousePressEvent(QMouseEvent *);void mouseMoveEvent(QMouseEvent *);void mouseReleaseEvent(QMouseEvent *);private slots:void zoomIn();private:Ui::Dialog *ui;QPixmap pix;QPoint lastPoint;QPoint endPoint;qreal scale;QPushButton *button; }; #endif // DIALOG_H

4.2 到dialog.cpp文件中,先在構(gòu)造函數(shù)中添加如下代碼:

Dialog::Dialog(QWidget *parent): QDialog(parent), ui(new Ui::Dialog) {ui->setupUi(this);//設(shè)置窗口大小resize(600, 500);//設(shè)置畫布大小和背景pix = QPixmap(300, 250);pix.fill(Qt::white);//設(shè)置初始放大倍數(shù)為1scale = 1;//新建按鈕對(duì)象button = new QPushButton(this);//設(shè)置按鈕顯示文本button->setText(tr("放大"));//設(shè)置按鈕的位置button->move(500, 450);//信號(hào)與槽關(guān)聯(lián)connect(button, &QPushButton::clicked, this, &Dialog::zoomIn);}

這里使用代碼創(chuàng)建了一個(gè)按鈕對(duì)象,并將其單擊信號(hào)關(guān)聯(lián)到了放大槽上,也就是說按下這個(gè)按鈕,就會(huì)執(zhí)行zoomIn()槽。

4.3 添加zoomIn函數(shù)

//槽函數(shù) 放大 void Dialog::zoomIn() {scale *= 2;update(); }

這里實(shí)現(xiàn)每按下這個(gè)按鈕,放大值都擴(kuò)大兩倍。后面調(diào)用update()函數(shù)來更新顯示。

4.4 讓畫布的內(nèi)容放大有兩個(gè)辦法,一個(gè)是直接放大畫布的坐標(biāo)系統(tǒng),一個(gè)是放大窗口的坐標(biāo)系統(tǒng)。下面我們先來放大窗口的坐標(biāo)系統(tǒng)。更改paintEvent()函數(shù)如下:

//繪圖事件 void Dialog::paintEvent(QPaintEvent *) {QPainter p(&pix);//根據(jù)鼠標(biāo)指針前后兩個(gè)位置繪制直線p.drawLine(lastPoint, endPoint);//前一個(gè)坐標(biāo)值等于后一個(gè)坐標(biāo)值lastPoint = endPoint;QPainter painter(this);painter.scale(scale, scale);painter.drawPixmap(0, 0, pix); }

現(xiàn)在運(yùn)行程序,效果如下圖所示。

然后按下zoomIn按鈕,效果如下圖所示。

現(xiàn)在再用鼠標(biāo)進(jìn)行繪制,發(fā)現(xiàn)圖形已經(jīng)不能和鼠標(biāo)軌跡重合了,效果如下圖所示。

窗口的坐標(biāo)擴(kuò)大了,但是畫布的坐標(biāo)并沒有擴(kuò)大,而我們畫圖用的坐標(biāo)值是鼠標(biāo)指針的,鼠標(biāo)指針又是獲取的窗口的坐標(biāo)值。現(xiàn)在窗口和畫布的同一點(diǎn)的坐標(biāo)并不相等,所以就出現(xiàn)了這樣的問題。

其實(shí)解決辦法很簡單,窗口放大了多少倍,就將獲得的鼠標(biāo)指針的坐標(biāo)值縮小多少倍就行了。我們將paintEvent()函數(shù)更改如下:

//繪圖事件 void Dialog::paintEvent(QPaintEvent *) {QPainter p(&pix);//根據(jù)鼠標(biāo)指針前后兩個(gè)位置繪制直線p.drawLine(lastPoint / scale, endPoint / scale);//前一個(gè)坐標(biāo)值等于后一個(gè)坐標(biāo)值lastPoint = endPoint;QPainter painter(this);painter.scale(scale, scale);painter.drawPixmap(0, 0, pix); }

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

05. 程序設(shè)計(jì)(放大功能)

方法二

5.1 擴(kuò)大畫布坐標(biāo)系統(tǒng)。先將paintEvent()更改如下:

//繪圖事件 void Dialog::paintEvent(QPaintEvent *) {QPainter p(&pix);p.scale(scale, scale);//根據(jù)鼠標(biāo)指針前后兩個(gè)位置繪制直線p.drawLine(lastPoint, endPoint);//前一個(gè)坐標(biāo)值等于后一個(gè)坐標(biāo)值lastPoint = endPoint;QPainter painter(this);painter.drawPixmap(0, 0, pix); }

這時(shí)運(yùn)行程序,先進(jìn)行繪制,然后點(diǎn)擊zoomIn按鈕,發(fā)現(xiàn)以前的內(nèi)容并沒有放大,而當(dāng)我們?cè)俅卫L畫時(shí),發(fā)現(xiàn)鼠標(biāo)指針和繪制的線條又不重合了。效果如下圖所示。

這并不是我們想要的結(jié)果,為了實(shí)現(xiàn)按下放大按鈕,畫布和圖形都進(jìn)行放大,我們可以使用緩沖畫布(就是一個(gè)輔助畫布)來實(shí)現(xiàn)。將paintEvent()函數(shù)內(nèi)容更改如下。

//繪圖事件 void Dialog::paintEvent(QPaintEvent *) {if (1 != scale){//臨時(shí)畫布QPixmap copyPix(pix.size() * scale);QPainter pp(&copyPix);pp.scale(scale, scale);//將以前畫布上的內(nèi)容復(fù)制到現(xiàn)在的畫布上pp.drawPixmap(0, 0, pix);//將放大后的內(nèi)容在復(fù)制到原來的畫布上pix = copyPix;//讓scale重新置1scale = 1;}QPainter p(&pix);p.scale(scale, scale);//根據(jù)鼠標(biāo)指針前后兩個(gè)位置繪制直線p.drawLine(lastPoint / scale, endPoint / scale);//前一個(gè)坐標(biāo)值等于后一個(gè)坐標(biāo)值lastPoint = endPoint;QPainter painter(this);painter.drawPixmap(0, 0, pix); }

運(yùn)行結(jié)果

06. 附錄

源碼下載:【Qt】2D繪圖之涂鴉板.rar

總結(jié)

以上是生活随笔為你收集整理的【Qt】2D绘图之涂鸦板的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。