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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Qt-在控件上绘图的方式

發布時間:2023/12/18 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Qt-在控件上绘图的方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.總述
Qt的要在當前類對應的窗口上繪圖一般需要重寫paintEvent函數,但是Qt的事件過濾器默認是把父窗口下子控件的繪圖事件給過濾了的,因此重寫父窗口的paintEvent函數是無法在子控件上進行繪圖的,下面舉一個例子。

?

?1 void MainWindow::myDraw(QLabel * label)
?2 {
?3 ? ? QPainter painter(label);
?4 ? ? painter.setPen(Qt::gray);
?5 ? ? painter.setBrush(Qt::green);
?6 ? ? painter.drawRect(10,10,20,20);
?7 }
?8?
?9 void MainWindow::paintEvent(QPaintEvent *)
10 {
11 ? ? myDraw(ui->label);
12 ? ? myDraw(ui->label_2);
13 }


如上所示,重寫MainWindow的paintEvent(QPaintEvent *)函數,然后在里面對子控件繪圖是沒有用的。

2.解決方案
還是以上面的例子為例。

法一
自己定義一個Mylabel類繼承于QLabel,然后在這個類中重寫paintEvent(QPaintEvent *)函數,并在里面繪圖。然后在ui界面中把對應的QLabel提升為Mylabel。這種方式不是很靈活,因此不多介紹,詳見https://blog.csdn.net/seanwang_25/article/details/18667871。

法二
在介紹法二之前,先補充一下qt中的事件機制,qt程序需要在main()函數創建一個QApplication對象,然后調用它的exec()函數。這個函數就是開始 Qt 的事件循環。在執行exec()函數之后,程序將進入事件循環來監聽應用程序的事件(鼠標事件,鍵盤事件,繪圖事件等)。當事件發生時,Qt 將創建一個事件對象。Qt 中所有事件類都繼承于QEvent。在事件對象創建完畢后,Qt 將這個事件先傳給事件過濾器:

virtual bool QObject::eventFilter ( QObject * watched, QEvent * event );

在事件過濾器中可以對感興趣的事件進行處理或屏蔽,令函數返回 true,不感興趣的事件繼續轉發,令函數返回 false或者交給父類處理。

通過事件過濾器的事件將交給事件分發器:

virtual ?bool QObject::event(QEvent *e)

event()函數并不直接處理事件,而是按照事件對象的類型分派給特定的事件處理函數(event handler),比如paintEvent(QPaintEvent *ev),mouseMoveEvent(QMouseEvent *ev).....

法二的實現思想:

使用事件過濾器,在子控件的繪圖事件被過濾前對子控件的繪圖事件進行處理。下面的示例代碼實現了點擊界面上的畫圖按鈕進行畫圖,點擊清除按鈕不進行畫圖。

?1 //mainwindow.cpp
?2 #include "mainwindow.h"
?3 #include "ui_mainwindow.h"
?4 #include<QPushButton>
?5 #include<QPaintEvent>
?6 #include<QPainter>
?7 #include<QPen>
?8 #include<QColor>
?9 #include<QString>
10 #include<QDebug>
11 #include<QFont>
12 #include<QPixmap>
13 #include<QVector>
14 MainWindow::MainWindow(QWidget *parent) :
15 ? ? QMainWindow(parent),
16 ? ? ui(new Ui::MainWindow)
17 {
18 ? ? ui->setupUi(this);
19 ? ? labels.push_back(ui->label);
20 ? ? labels.push_back(ui->label_2);
21 ? ? ui->label->installEventFilter(this);//在label上安裝事件過濾器,this指針指定當事件發生時調用當前類中的事件過濾器進行處理
22 ? ? ui->label_2->installEventFilter(this);//在label_2上安裝事件過濾器
23 ? ? connect(ui->pushButton,&QPushButton::clicked,this,[&]()
24 ? ? {
25 ? ? ? ? flag =1;
26 ? ? ? ? update();//手動產生繪圖事件
27 ? ? });
28 ? ? connect(ui->pushButton_2,&QPushButton::clicked,this,[&]()
29 ? ? {
30 ? ? ? ? flag =0;
31 ? ? ? ? update();//手動產生繪圖事件
32 ? ? });
33 }
34?
35 MainWindow::~MainWindow()
36 {
37 ? ? delete ui;
38 }
39?
40 void MainWindow::myDraw(QLabel * label)
41 {
42 ? ? QPainter painter(label);
43 ? ? painter.setPen(Qt::gray);
44 ? ? painter.setBrush(Qt::green);
45 ? ? painter.drawRect(10,10,20,20);
46 }
47?
48 //void MainWindow::paintEvent(QPaintEvent *)
49 //{
50 // ? ?myDraw(ui->label);
51 // ? ?myDraw(ui->label_2);
52 //}
53?
54 bool MainWindow::eventFilter(QObject *watched, QEvent *event)
55 {
56 ? ? if(watched == ui->label && event->type() == QEvent::Paint)//發生繪圖事件,且是在label上發生的
57 ? ? {
58 ? ? ? ? ? ? if(flag == 1)//標志位為1才在label上繪圖,否者不繪圖
59 ? ? ? ? ? ? {
60 ? ? ? ? ? ? ? ? myDraw(ui->label);
61 ? ? ? ? ? ? ? ? return true;
62 ? ? ? ? ? ? }
63 ? ? ? ? ? ? else
64 ? ? ? ? ? ? ? ? return false;
65 ? ? }
66 ? ? else if(watched == ui->label_2 && event->type() == QEvent::Paint)
67 ? ? {
68 ? ? ? ? ? ? if(flag == 1)
69 ? ? ? ? ? ? {
70 ? ? ? ? ? ? ? ? myDraw(ui->label_2);
71 ? ? ? ? ? ? ? ? return true;
72 ? ? ? ? ? ? }
73 ? ? ? ? ? ? else
74 ? ? ? ? ? ? ? ? return false;
75 ? ? }
76 ? ? else
77 ? ? ? ? return QMainWindow::eventFilter(watched,event);//其它繪圖事件交給父類處理
78 }


上述寫法還是有一個不方便的地方,就是當控件很多的時候,要對每一個控件都單獨的像第21行和第22行那樣單獨的安裝事件過濾器。因此可以向QApplication或者QCoreApplication添加事件過濾器,這樣就相當于當前應用程序下所有的控件都安裝了事件過濾器。

?1 //main.cpp
?2 #include "mainwindow.h"
?3 #include <QApplication>
?4?
?5 int main(int argc, char *argv[])
?6 {
?7 ? ? QApplication a(argc, argv);
?8 ? ? MainWindow w;
?9 ? ? w.show();
10 ? ? a.installEventFilter(&w);//給整個應用程序安裝事件過濾器
11 ? ? return a.exec();
12 }


?

?1 //mainwindow.cpp
?2 #include "mainwindow.h"
?3 #include "ui_mainwindow.h"
?4 #include<QPushButton>
?5 #include<QPaintEvent>
?6 #include<QPainter>
?7 #include<QPen>
?8 #include<QColor>
?9 #include<QString>
10 #include<QDebug>
11 #include<QFont>
12 #include<QPixmap>
13 #include<QVector>
14 MainWindow::MainWindow(QWidget *parent) :
15 ? ? QMainWindow(parent),
16 ? ? ui(new Ui::MainWindow)
17 {
18 ? ? ui->setupUi(this);
19 ? ? labels.push_back(ui->label);
20 ? ? labels.push_back(ui->label_2);
21 ? ? //ui->label->installEventFilter(this);//在label上安裝事件過濾器,this指針指定當事件發生時調用當前類中的事件過濾器進行處理
22 ? ? //ui->label_2->installEventFilter(this);//在label_2上安裝事件過濾器
23 ? ? connect(ui->pushButton,&QPushButton::clicked,this,[&]()
24 ? ? {
25 ? ? ? ? flag =1;
26 ? ? ? ? update();//產生繪圖事件
27 ? ? });
28 ? ? connect(ui->pushButton_2,&QPushButton::clicked,this,[&]()
29 ? ? {
30 ? ? ? ? flag =0;
31 ? ? ? ? update();//產生繪圖事件
32 ? ? });
33 }
34?
35 MainWindow::~MainWindow()
36 {
37 ? ? delete ui;
38 }
39?
40 void MainWindow::myDraw(QLabel * label)
41 {
42 ? ? QPainter painter(label);
43 ? ? painter.setPen(Qt::gray);
44 ? ? painter.setBrush(Qt::green);
45 ? ? painter.drawRect(10,10,20,20);
46 }
47?
48 //void MainWindow::paintEvent(QPaintEvent *)
49 //{
50 // ? ?myDraw(ui->label);
51 // ? ?myDraw(ui->label_2);
52 //}
53?
54 bool MainWindow::eventFilter(QObject *watched, QEvent *event)
55 {
56 ? ? if(event->type() == QEvent::Paint)//繪圖事件
57 ? ? {
58 ? ? ? ? if(flag == 1)//標志位為1才在label上繪圖,否者不繪圖
59 ? ? ? ? {
60 ? ? ? ? ? ? for(QVector<QLabel *>::iterator it=labels.begin();it!=labels.end();it++)
61 ? ? ? ? ? ? {
62 ? ? ? ? ? ? ? ? if(watched == *it)//限制條件,只處理label上的繪圖事件
63 ? ? ? ? ? ? ? ? {
64 ? ? ? ? ? ? ? ? ? ? myDraw(*it);
65 ? ? ? ? ? ? ? ? ? ? return true;//返回true表示處理完成該事件,否者該事件還會繼續向下轉發
66 ? ? ? ? ? ? ? ? }
67 ? ? ? ? ? ? }
68 ? ? ? ? ? ? return QMainWindow::eventFilter(watched,event);//其它繪圖事件交給父類處理
69 ? ? ? ? }
70 ? ? ? ? else
71 ? ? ? ? ? ? return QMainWindow::eventFilter(watched,event);//其它繪圖事件交給父類處理
72?
73 ? ? }else
74 ? ? ? ? return QMainWindow::eventFilter(watched,event);
75 ? ??
76 }


Qt 在控件上面繪圖 label,pushbutton
Qt 之所以不能在在任意控件上面繪圖,是因為Qt的事件過濾器把控件的繪圖事件給過濾了,自己知識不夠,盜用狗哥的話

“在事件過濾器eventFilter() 中攔截 Label 的 QEvent::Paint 事件”

代買如下

bool Widget::eventFilter(QObject *watched, QEvent *event)

{

if(watched == ui->label && event->type() == QEvent::Paint)

{

magicTime();

}

return QWidget::eventFilter(watched,event);

}

然后就是在magicTime()函數中實現自己的繪制了

如下demo

void Widget::magicTime()

{

QPainter painter(ui->label);

painter.setPen(Qt::gray);

painter.setBrush(Qt::green);

painter.drawRect(10,10,200,200);

}

不過在此之間,還有一個步驟是要做的

ui->label->installEventFilter(this);
運行截圖

?

Qt在子部件上繪圖
本文記錄如何使用qpainter在子部件上繪圖。
1.需要在子部件上安裝事件過濾器
frame->installEventFilter(this); //安裝事件過濾器到窗口

2.頭文件中聲明如下
bool eventFilter(QObject *watched, QEvent *event);
bool m_flag=false;//繪圖標志
3.聲明畫圖函數
void graphChart(QWidget *w);
4.如果使用按鈕來控制畫圖
?
m_flag = true;

update();

代碼展示如下:

頭文件:

?
#ifndef MAINWINDOW_H

#define MAINWINDOW_H

?
#include <QMainWindow>

#include<QPaintEvent>

#include<QPainter>

namespace Ui {

class MainWindow;

}

?
class MainWindow : public QMainWindow

{

Q_OBJECT

?
public:

explicit MainWindow(QWidget *parent = nullptr);

~MainWindow();

// void paintEvent(QPaintEvent *p);

QPainter *painter;

?
private slots:

void on_pushButton_clicked();

?
private:

Ui::MainWindow *ui;

bool m_flag = false;//繪圖標志

bool eventFilter(QObject *watched, QEvent *event);

void graphChart(QWidget *w);

};

?
#endif // MAINWINDOW_H

Cpp文件 :

?
#include "mainwindow.h"

#include "ui_mainwindow.h"

?
MainWindow::MainWindow(QWidget *parent) :

QMainWindow(parent),

ui(new Ui::MainWindow)

{

ui->setupUi(this);

ui->widget->installEventFilter(this);

}

?
MainWindow::~MainWindow()

{

delete ui;

}

?
?
?
void MainWindow::on_pushButton_clicked()

{

m_flag = true;

update();

}

?
bool MainWindow::eventFilter(QObject *watched, QEvent *event)

{

if(watched ==ui->widget&&event->type()==QEvent::Paint)

{

graphChart(ui->widget);

}

?
return QWidget::eventFilter(watched,event);

}

?
void MainWindow::graphChart(QWidget *w)

{

if(m_flag)

{

painter = new QPainter();

painter->begin(w);

QPen pen;

pen.setColor(Qt::red);

painter->setPen(pen);

painter->drawText(100,100,"Paintevent");

painter->end();

?
}

?
}

補充:
畫了個等邊三角形?

?
void MainWindow::drawTriangle(QPainter *painter)

{

painter->save();

double radius =100;

painter->setPen(Qt::NoPen);

static const QPointF points[3]={QPointF(radius,0),QPointF(0,0),QPointF(radius/2,sqrt(pow(radius,2)-pow(radius/2,2)))};

?
painter->setBrush(Qt::red);

painter->drawConvexPolygon(points,3);

painter->restore();

}

總結

以上是生活随笔為你收集整理的Qt-在控件上绘图的方式的全部內容,希望文章能夠幫你解決所遇到的問題。

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