Qt實現繪制自定義形狀

先創建一個繼承自QWidget的控件:

class MyPainterWidget:public QWidget

重寫各種鼠標方法:

protected:void paintEvent(QPaintEvent *) override;void mousePressEvent(QMouseEvent *e) override;       //按下void mouseMoveEvent(QMouseEvent *e) override;        //移動void mouseReleaseEvent(QMouseEvent *e) override;     //松開void mouseDoubleClickEvent(QMouseEvent *event) override;

在構造函數中聲明跟蹤鼠標:

#include <QMouseEvent>
setMouseTracking(true);

定義兩個標志位作為開始繪制和鼠標移動的標志:

bool m_bStartDraw = false;    //是否已經開始左鍵點擊,同時標識是否開始進行繪制bool bMove = false;           //是否處于繪制時的鼠標移動狀態

創建一個點集記錄每次按下的坐標點:

QVector<QPointF> pointList;

在程序一開始的時候先清除點集:

MyPainterWidget::MyPainterWidget(QWidget *parent) : QWidget(parent)
{setMouseTracking(true);pointList.clear();
}

按下鼠標時將開始繪制標志位設為true:

// 按下
void MyPainterWidget::mousePressEvent(QMouseEvent *e)
{if (e->button() == Qt::LeftButton){if(!m_bStartDraw){pointList.clear();m_bStartDraw = true;}}   
}

創建一個點用于獲取鼠標移動時的當前位置:

QPointF movePoint;

重寫移動事件:

// 移動
void MyPainterWidget::mouseMoveEvent(QMouseEvent *e)
{if(m_bStartDraw){movePoint = e->pos();this->update();//重新進入painEvent事件進行繪制// 先刷新再設為true, 防止第一點和(0,0)連在一塊bMove = true;}
}

重寫釋放事件:

// 松開
void MyPainterWidget::mouseReleaseEvent(QMouseEvent *e)
{if (e->button() == Qt::LeftButton){if (m_bStartDraw){// 鼠標松開后的點需要添加到路徑中pointList.push_back(QPointF(e->x(), e->y()));bMove = false;this->update();//刷新繪制}}
}

寫一個表示結束繪制的功能函數:

void MyPainterWidget::endDraw()
{m_bStartDraw = false;//需要把第一個點連起來pointList.push_back(pointList[0]);this->update();
}

實現清除所有已繪的功能函數:

void MyPainterWidget::clearPath()
{pointList.clear();this->update();
}

主窗口:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QMenu>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();protected:// 右鍵菜單需要重寫的類void contextMenuEvent(QContextMenuEvent* event) override;private:Ui::MainWindow *ui;QMenu* m_pMenu;
};
#endif // MAINWINDOW_H
/*使用方式左鍵點擊,移動鼠標開始繪制,雙擊左鍵結束繪制,或者右鍵點擊結束繪制*/#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMenu>
#include <QAction>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);m_pMenu = new QMenu(this);QAction* pAc1 = new QAction(QString::fromLocal8Bit("結束繪制"), this);pAc1->setShortcut(QKeySequence("Ctrl+E"));QAction* pAc2 = new QAction(QString::fromLocal8Bit("清除"), this);pAc2->setShortcut(QKeySequence("Ctrl+D"));// 這是個假動作,為了讓菜單消失,且不影響繪制路徑QAction* pAc3 = new QAction(QString::fromLocal8Bit("退出菜單"), this);m_pMenu->addAction(pAc1);m_pMenu->addAction(pAc2);m_pMenu->addAction(pAc3);m_pMenu->setStyleSheet("QMenu{font:18px;}");connect(pAc1, &QAction::triggered, [=] {ui->graphicsPainter->endDraw();});connect(pAc2, &QAction::triggered, [=] {ui->graphicsPainter->clearPath();});
}MainWindow::~MainWindow()
{delete ui;
}// 右鍵菜單
void MainWindow::contextMenuEvent(QContextMenuEvent* event)
{m_pMenu->move(cursor().pos());m_pMenu->show();
}

完整代碼:

#ifndef GRAPHICSPAINTER_H
#define GRAPHICSPAINTER_H#include <QWidget>class MyPainterWidget : public QWidget
{Q_OBJECTpublic:explicit MyPainterWidget(QWidget *parent = nullptr);void endDraw();void clearPath();protected:void paintEvent(QPaintEvent *) override;void mousePressEvent(QMouseEvent *e) override;       //按下void mouseMoveEvent(QMouseEvent *e) override;        //移動void mouseReleaseEvent(QMouseEvent *e) override;     //松開void mouseDoubleClickEvent(QMouseEvent *event) override;     //雙擊bool m_bStartDraw = false;    //是否已經開始左鍵點擊,同時標識是否開始進行繪制bool bMove = false;           //是否處于繪制時的鼠標移動狀態QVector<QPointF> pointList;QPointF movePoint;
};#endif // GRAPHICSPAINTER_H
#include "MyPainterWidget.h"
#include <QPainter>
#include <QMouseEvent>MyPainterWidget::MyPainterWidget(QWidget *parent) : QWidget(parent)
{setMouseTracking(true);pointList.clear();
}void MyPainterWidget::paintEvent(QPaintEvent *)
{QPainter painter(this);painter.setPen(QColor(255,0,0));QVector<QLineF> lines;for(int i = 0; i < pointList.size()-1; i++){QLineF line(QPointF(pointList[i].x(), pointList[i].y()), QPointF(pointList[i+1].x(), pointList[i+1].y()));lines.push_back(line);}if (m_bStartDraw){int size = pointList.size();if (bMove && size > 0){QLineF line(QPointF(pointList[pointList.size() - 1].x(), pointList[pointList.size() - 1].y()),movePoint);lines.push_back(line);}}painter.drawLines(lines);
}// 按下
void MyPainterWidget::mousePressEvent(QMouseEvent *e)
{if (e->button() == Qt::LeftButton){if(!m_bStartDraw){pointList.clear();m_bStartDraw = true;}}   
}// 移動
void MyPainterWidget::mouseMoveEvent(QMouseEvent *e)
{if(m_bStartDraw){movePoint = e->pos();this->update();//重新進入painEvent事件進行繪制// 先刷新再設為true, 防止第一點和(0,0)連在一塊bMove = true;}
}// 松開
void MyPainterWidget::mouseReleaseEvent(QMouseEvent *e)
{if (e->button() == Qt::LeftButton){if (m_bStartDraw){// 鼠標松開后的點需要添加到路徑中pointList.push_back(QPointF(e->x(), e->y()));bMove = false;this->update();//刷新繪制}}
}// 雙擊結束繪制
void MyPainterWidget::mouseDoubleClickEvent(QMouseEvent *event)
{endDraw();
}void MyPainterWidget::endDraw()
{m_bStartDraw = false;//需要把第一個點連起來pointList.push_back(pointList[0]);this->update();
}void MyPainterWidget::clearPath()
{pointList.clear();this->update();
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/167415.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/167415.shtml
英文地址,請注明出處:http://en.pswp.cn/news/167415.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Xposed hook失敗的原因

最近對Xposed的比較感興趣&#xff0c;于是照著網上的給的例子做了一個Xposed模塊&#xff0c;但是在安卓模擬器上死活不生效&#xff0c;最后研究發現了兩個問題導致&#xff1a; 1、XposedBridgeAPI-89.jar 需要放到項目的lib目錄下&#xff0c;而不是libs目錄 2、XposedBr…

HEVC-SCC rgb file input

關鍵字 csc allocateCSCBuffer&#xff08;&#xff09;-> m_apcPicYuvCSC xCheckRDCostIntraCSC():更簡單&#xff0c; enum ACTRDTestTypes { ACT_TWO_CLR 0, //two color space ACT_TRAN_CLR 1, //transformed color space ACT_ORG_CL…

補充:如何提高selenium的運行速度?

已經通讀該專欄文章的同學,或許對UI自動化測試有了一定的掌握,細心的同學肯定會發現一個問題,當用例量達到一定程度時,對于整體用例的執行速度肯定不會很滿意。除了應用多線程運行用例的方式加快速度,有沒有其他的方法呢? 今天告訴大家,方法是有的!也是本人新學的。即…

[PyTorch][chapter 66][強化學習-值函數近似]

前言 現實強化學習任務面臨的狀態空間往往是連續的,無窮多個。 這里主要針對這種連續的狀態空間處理。后面DQN 也是這種處理思路。 目錄&#xff1a; 1&#xff1a; 原理 2&#xff1a; 梯度更新 3&#xff1a; target 和 預測值 4 流程 一 原理 強化學習最重要的是得到 …

c++版本opencv計算灰度圖像的輪廓點

代碼 #include<iostream> #include<opencv.hpp>int main() {std::string imgPath("D:\\prostate_run\\result_US_20230804_141531\\mask\\us\\104.bmp");cv::Mat imgGray cv::imread(imgPath, 0);cv::Mat kernel cv::getStructuringElement(cv::MORPH…

任意分圓環下的 RLWE:如何產生正確的噪聲分布

參考文獻&#xff1a; [Con09] Conrad K. The different ideal[J]. Expository papers/Lecture notes. Available at: http://www.math.uconn.edu/~kconrad/blurbs/gradnumthy/different.pdf, 2009.[LPR10] Lyubashevsky V, Peikert C, Regev O. On ideal lattices and learn…

thinkphp6生成PDF自動換行

composer安裝 composer require tecnickcom/tcpdf 示例 use TCPDF;public function info($university,$performance,$grade,$major){//獲取到當前域名$domain request()->domain();//實例化$pdf new TCPDF(P, mm, A4, true, UTF-8, false);// 設置文檔信息$pdf->SetCr…

Azkaban極簡使用文檔

登錄 地址: http://服務器ip:8081/, 用戶名密碼默認都是azkaban 構建項目流程 添加Project 編寫工作流文件 在本機新建文件夾如test, 創建一個flow20.project 文件, 內容 azkaban-flow-version: 2.0(固定步驟)編寫flow文件, 例如一個最基礎的實例 test1.flow nodes:- name…

JAVA序列化和反序列化

JAVA序列化和反序列化 文章目錄 JAVA序列化和反序列化序列化什么是序列化&#xff1f;為什么要進行序列化?如何將對線進行序列化具體實現過程 完整代碼 序列化 什么是序列化&#xff1f; 就是將對象轉化為字節的過程 為什么要進行序列化? 讓數據更高效的傳輸讓數據更好的…

Vue中的$nextTick

?&#x1f308;個人主頁&#xff1a;前端青山 &#x1f525;系列專欄&#xff1a;Vue篇 &#x1f516;人終將被年少不可得之物困其一生 依舊青山,本期給大家帶來vue篇專欄內容:vue中的$nextTick 目錄 &#x1f40b;Vue中的$nextTick有什么作用&#xff1f; &#x1f40b;一、…

socket can中是如何根據 結構體can_bittiming_const中的字段 計算bitrate的?

在 SocketCAN 中&#xff0c;can_bittiming_const 結構體用于表示 CAN 總線的定時參數&#xff0c;包括位率&#xff08;bitrate&#xff09;的計算。can_bittiming_const 包含了許多與位率相關的參數&#xff0c;其中一些參數用于計算實際的位率。 下面是一些與位率計算相關的…

小辰的智慧樹(差分+前綴和)

登錄—專業IT筆試面試備考平臺_牛客網 1.考慮總長度之和不能超過m&#xff0c;2考慮限制每棵樹高度不能低于ci&#xff0c;如果用二分最短輸能截到的高度&#xff0c;還要另外去判斷&#xff0c;是否每棵樹mid都能嚴格大于ci &#xff0c;這樣容易超時&#xff0c;換個角度&…

SQL常見函數整理 _ lead() 向下偏移

1. 用法 是在窗口函數中使用的函數&#xff0c;它用于獲取當前行的下一行&#xff08;后一行&#xff09;的某個列的值。具體來說&#xff0c;LEAD() 函數可用于查找任何給定行的下一行&#xff08;后一行&#xff09;的值&#xff0c;同時也可控制行數偏移量&#xff08;offse…

競賽選題 題目:基于LSTM的預測算法 - 股票預測 天氣預測 房價預測

文章目錄 0 簡介1 基于 Keras 用 LSTM 網絡做時間序列預測2 長短記憶網絡3 LSTM 網絡結構和原理3.1 LSTM核心思想3.2 遺忘門3.3 輸入門3.4 輸出門 4 基于LSTM的天氣預測4.1 數據集4.2 預測示例 5 基于LSTM的股票價格預測5.1 數據集5.2 實現代碼 6 lstm 預測航空旅客數目數據集預…

社交媒體廣告數據采集:Jsoup 的最佳實踐

搜狐是中國領先的綜合門戶網站之一&#xff0c;廣告在其網站上廣泛投放。為了了解搜狐廣告的策略和趨勢&#xff0c;采集和分析搜狐廣告數據變得至關重要。但是&#xff0c;搜狐網站的廣告數據通常需要通過網頁抓取的方式獲取&#xff0c;這就需要一個強大的工具來解析和提取數…

面試:線上問題處理

文章目錄 在處理線上問題時&#xff0c;你的排查思路和步驟是什么線上偶發性問題如何處理和跟蹤當系統出現大量錯誤日志時&#xff0c;你會如何分析和解決問題在高并發場景中&#xff0c;如何排查和解決線程安全問題當系統出現大規模的故障時&#xff0c;你的應急處理和恢復策略…

用友BIP與用友BIP對接集成銷售出庫列表查詢連通銷售出庫單個保存((紅字)銷售出庫審核-v)

用友BIP與用友BIP對接集成銷售出庫列表查詢連通銷售出庫單個保存(&#xff08;紅字&#xff09;銷售出庫審核-v) 源系統:用友BIP 面向數智化市場&#xff0c;用友傾力打造了全球領先的數智商業創新平臺——用友BIP&#xff0c;定位為數智商業的應用級基礎設施、企業服務產業的共…

虛擬機系列:(VMware Workstation Pro)Centos7下搭建Android開發環境及Android真機調試

一、Android SDK 安裝配置 1、環境 Linux系統為:Red Hat Enterprise Linux 7 64 位 ; 當然還需要Java環境,java 環境這里不敘述; 2、Android Studio 安裝 (1)下載位置: http://www.android-studio.org/ 我這里下載的:android-studio-ide-191.5977832-linux.tar.gz …

pat實現基于鄰接矩陣表示的深度優先遍歷

void DFS(Graph G, int v) {visited[v] 1;printf("%c ", G.vexs[v]);for (int i 0; i < G.vexnum; i) {if (!visited[i] && G.arcs[v][i]) DFS(G, i);} }

SpectralGPT: Spectral Foundation Model 論文翻譯2

遙感領域的通用大模型 2023.11.13在CVPR發表 原文地址&#xff1a;[2311.07113] SpectralGPT: Spectral Foundation Model (arxiv.org) 實驗 ? 在本節中&#xff0c;我們將嚴格評估我們的SpectralGPT模型的性能&#xff0c;并對其進行基準測試SOTA基礎模型&#xff1a;ResN…