先創建一個繼承自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();
}