在重寫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是不會生效的,這兩個功能互相沖突。