1. 程式人生 > 其它 >如何實現視窗中子控制元件的繪圖(paintEvent())事件

如何實現視窗中子控制元件的繪圖(paintEvent())事件

在重寫paintEvent()函式時,這個paintEvent()屬於哪個物件,那麼就會重新繪製該物件,但是這樣也面臨著一個問題:

假如我重寫了一個mainwindow的paintEvent(),那麼該paintEvent只對MainWindow生效,

如果想繪製的圖形是在MainWindow上的子的元件應該怎麼繪製在哪裡繪製?

一般想到的是直接在paintEvent()更改,但是想要在哪個 控制元件上繪圖,就需要在它的 paintEvent() 函式裡繪圖,對於用Qt designer中編輯的控制元件,必須新建一個類繼承自控制元件,然後在它的 paintEvent() 裡繪圖,如果單獨就這個問題建立一個新的類就會有點小題大作了

因此可以用事件過濾器來解決這個問題

首先需要在標頭檔案中新增 eventFilter函式,

class MainWindow : public QMainWindow
{
    Q_OBJECT
protected:
    bool eventFilter(QObject *watched, QEvent *event) ;
}

在原始檔中實現eventFilter

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    if(ui->stackedWidget_3->currentIndex() == 1
) { if (watched == ui->linkWidget_1 && event->type() == QEvent::Paint) { for(int i = 0;i < linkLinePoints.count();i++) { int x1,y1,x2,y2; x1 = linkLinePoints.at(i).at(0)+10; y1 = linkLinePoints.at(i).at(1
)+10; x2 = linkLinePoints.at(i).at(2)+10; y2 = linkLinePoints.at(i).at(3)+10; QPainter painter(ui->linkWidget_1 ); QPen pen; // creates a default pen pen.setWidth(3); if(i == 0) pen.setBrush(Qt::black); else if(i == 1) pen.setBrush(Qt::red); else if(i == 2) pen.setBrush(Qt::blue); else if(i == 3) pen.setBrush(Qt::green); painter.setPen(pen); painter.drawLine(x1,y1, x2,y2); } } } else if(ui->stackedWidget_3->currentIndex() == 0) { if(watched == ui->linkWidget_2 && event->type() == QEvent::Paint) { for(int i = 0;i < linkLinePoints.count();i++) { int x1,y1,x2,y2; x1 = linkLinePoints.at(i).at(0)+10; y1 = linkLinePoints.at(i).at(1)+10; x2 = linkLinePoints.at(i).at(2)+10; y2 = linkLinePoints.at(i).at(3)+10; QPainter painter(ui->linkWidget_2 ); QPen pen; // creates a default pen pen.setWidth(3); if(i == 0) pen.setBrush(Qt::black); else pen.setBrush(Qt::red); painter.setPen(pen); painter.drawLine(x1,y1, x2,y2); } } } return QWidget::eventFilter(watched, event); }

之後,再將我們想要繪製的控制元件與這個過濾函式關聯起來

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->linkWidget_1->installEventFilter(this);
    ui->linkWidget_2->installEventFilter(this);
}

在這個程式中,我分別將兩個widget子控制元件ui->linkWidget_1 和 ui->linkWidget_2 和這個事件關聯起來,關聯起來之後,在eventfilter函式中,需要注意紅色字型程式碼所在處,要正確關聯watch物件和設定painter物件才可正確繪製。

最後,在相應的地方呼叫upDate函式,即可實現對子控制元件的繪製。

用該方法實現的子控制元件繪製,不需要重寫MainWindow的paintEvent函式,將其刪除或者註釋掉就行。

需要注意的是,如果控制元件有了自己的styleSheet,那麼再重新實現paintEvent是不會生效的,這兩個功能互相沖突。