日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Qt中在控件上绘图

發(fā)布時(shí)間:2023/12/18 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Qt中在控件上绘图 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.總述

Qt的要在當(dāng)前類(lèi)對(duì)應(yīng)的窗口上繪圖一般需要重寫(xiě)paintEvent函數(shù),但是Qt的事件過(guò)濾器默認(rèn)是把父窗口下子控件的繪圖事件給過(guò)濾了的,因此重寫(xiě)父窗口的paintEvent函數(shù)是無(wú)法在子控件上進(jìn)行繪圖的,下面舉一個(gè)例子。

?

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 }

如上所示,重寫(xiě)MainWindow的paintEvent(QPaintEvent *)函數(shù),然后在里面對(duì)子控件繪圖是沒(méi)有用的。

2.解決方案

還是以上面的例子為例。

法一

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

法二

在介紹法二之前,先補(bǔ)充一下qt中的事件機(jī)制,qt程序需要在main()函數(shù)創(chuàng)建一個(gè)QApplication對(duì)象,然后調(diào)用它的exec()函數(shù)。這個(gè)函數(shù)就是開(kāi)始 Qt 的事件循環(huán)。在執(zhí)行exec()函數(shù)之后,程序?qū)⑦M(jìn)入事件循環(huán)來(lái)監(jiān)聽(tīng)?wèi)?yīng)用程序的事件(鼠標(biāo)事件,鍵盤(pán)事件,繪圖事件等)。當(dāng)事件發(fā)生時(shí),Qt 將創(chuàng)建一個(gè)事件對(duì)象。Qt 中所有事件類(lèi)都繼承于QEvent。在事件對(duì)象創(chuàng)建完畢后,Qt 將這個(gè)事件先傳給事件過(guò)濾器:

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

在事件過(guò)濾器中可以對(duì)感興趣的事件進(jìn)行處理或屏蔽,令函數(shù)返回 true,不感興趣的事件繼續(xù)轉(zhuǎn)發(fā),令函數(shù)返回 false或者交給父類(lèi)處理

通過(guò)事件過(guò)濾器的事件將交給事件分發(fā)器:

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

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

法二的實(shí)現(xiàn)思想:

使用事件過(guò)濾器,在子控件的繪圖事件被過(guò)濾前對(duì)子控件的繪圖事件進(jìn)行處理。下面的示例代碼實(shí)現(xiàn)了點(diǎn)擊界面上的畫(huà)圖按鈕進(jìn)行畫(huà)圖,點(diǎn)擊清除按鈕不進(jìn)行畫(huà)圖。

1 //mainwindow.cpp2 #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上安裝事件過(guò)濾器,this指針指定當(dāng)事件發(fā)生時(shí)調(diào)用當(dāng)前類(lèi)中的事件過(guò)濾器進(jìn)行處理 22 ui->label_2->installEventFilter(this);//在label_2上安裝事件過(guò)濾器 23 connect(ui->pushButton,&QPushButton::clicked,this,[&]() 24 { 25 flag =1; 26 update();//手動(dòng)產(chǎn)生繪圖事件 27 }); 28 connect(ui->pushButton_2,&QPushButton::clicked,this,[&]() 29 { 30 flag =0; 31 update();//手動(dòng)產(chǎn)生繪圖事件 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)//發(fā)生繪圖事件,且是在label上發(fā)生的 57 { 58 if(flag == 1)//標(biāo)志位為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);//其它繪圖事件交給父類(lèi)處理 78 }

上述寫(xiě)法還是有一個(gè)不方便的地方,就是當(dāng)控件很多的時(shí)候,要對(duì)每一個(gè)控件都單獨(dú)的像第21行和第22行那樣單獨(dú)的安裝事件過(guò)濾器。因此可以向QApplication或者QCoreApplication添加事件過(guò)濾器,這樣就相當(dāng)于當(dāng)前應(yīng)用程序下所有的控件都安裝了事件過(guò)濾器。

1 //main.cpp2 #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);//給整個(gè)應(yīng)用程序安裝事件過(guò)濾器 11 return a.exec(); 12 }

?

1 //mainwindow.cpp2 #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上安裝事件過(guò)濾器,this指針指定當(dāng)事件發(fā)生時(shí)調(diào)用當(dāng)前類(lèi)中的事件過(guò)濾器進(jìn)行處理 22 //ui->label_2->installEventFilter(this);//在label_2上安裝事件過(guò)濾器 23 connect(ui->pushButton,&QPushButton::clicked,this,[&]() 24 { 25 flag =1; 26 update();//產(chǎn)生繪圖事件 27 }); 28 connect(ui->pushButton_2,&QPushButton::clicked,this,[&]() 29 { 30 flag =0; 31 update();//產(chǎn)生繪圖事件 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)//標(biāo)志位為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表示處理完成該事件,否者該事件還會(huì)繼續(xù)向下轉(zhuǎn)發(fā) 66 } 67 } 68 return QMainWindow::eventFilter(watched,event);//其它繪圖事件交給父類(lèi)處理 69 } 70 else 71 return QMainWindow::eventFilter(watched,event);//其它繪圖事件交給父類(lèi)處理 72 73 }else 74 return QMainWindow::eventFilter(watched,event); 75 76 }

Qt 在控件上面繪圖 label,pushbutton

Qt 之所以不能在在任意控件上面繪圖,是因?yàn)镼t的事件過(guò)濾器把控件的繪圖事件給過(guò)濾了,自己知識(shí)不夠,盜用狗哥的話(huà)

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

代買(mǎi)如下

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

  • {

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

  • {

  • magicTime();

  • }

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

  • }

  • 然后就是在magicTime()函數(shù)中實(shí)現(xiàn)自己的繪制了

    如下demo

  • void Widget::magicTime()

  • {

  • QPainter painter(ui->label);

  • painter.setPen(Qt::gray);

  • painter.setBrush(Qt::green);

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

  • }

  • 不過(guò)在此之間,還有一個(gè)步驟是要做的

    ui->label->installEventFilter(this);

    運(yùn)行截圖

    Qt在子部件上繪圖

    本文記錄如何使用qpainter在子部件上繪圖。

    1.需要在子部件上安裝事件過(guò)濾器

    frame->installEventFilter(this); //安裝事件過(guò)濾器到窗口

    2.頭文件中聲明如下

    bool eventFilter(QObject *watched, QEvent *event); bool m_flag=false;//繪圖標(biāo)志

    3.聲明畫(huà)圖函數(shù)

    void graphChart(QWidget *w);

    4.如果使用按鈕來(lái)控制畫(huà)圖

  • 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;//繪圖標(biāo)志

  • 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();

  • ?
  • }

  • ?
  • }

  • 補(bǔ)充:

    畫(huà)了個(gè)等邊三角形?

  • 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();

  • }

  • ?

    總結(jié)

    以上是生活随笔為你收集整理的Qt中在控件上绘图的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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