调用update()不会触发paintEvent()

问题描述 投票:0回答:1

我试图在小部件的中心画一条线,所以我尝试使用

paintEvent()
来调用
update()

但是,

paintEvent()
不会被调用。这是为什么?

test_paint.h:

#ifndef TEST_PAINT_H
#define TEST_PAINT_H

#include <QPainter>
#include <QWidget>

class test_paint:public QWidget{
    Q_OBJECT
public:
    test_paint(QWidget* device){paper = device;}

protected:
    void paintEvent(QPaintEvent* e){
        QPainter p(paper);
        QPen myPen;
        myPen.setColor(Qt::red);
        myPen.setWidth(5);
        p.setPen(myPen);
        QPoint p1;
        QPoint p2;
        p1.setX(10);
        p1.setY(10);
        p2.setX(100);
        p2.setY(10);
        p.drawLine(p1,p2);
    };
    void try_painting(){
        update();
    }
public slots:
    void call_paint(){
        try_painting();
    }

private:
    QWidget* paper;
};

#endif // TEST_PAINT_H

main.cpp:

#include <QApplication>
#include <QPushButton>
#include <QMainWindow>
#include <QMenu>
#include <QMenuBar>
#include <QWidget>
#include <QVBoxLayout>
#include <QObject>
#include "test_paint.h"

int main(int argc, char* argv[]){
    QApplication a(argc,argv);
    QMainWindow window;
    window.setFixedSize(500, 600);

    QMenu menu("Menu");
    window.menuBar()->addMenu("Menu");

    QWidget *center = new QWidget();
    window.setCentralWidget(center);
    window.show();

    QPushButton* push = new QPushButton("test_move");
    QVBoxLayout* vlayout = new QVBoxLayout();
    vlayout -> addWidget(push);
    center->setLayout(vlayout);

    test_paint* d = new test_paint(center);

    QObject::connect(push,SIGNAL(clicked()),d,SLOT(call_paint()));
    return a.exec();
}
c++ qt qwidget paintevent
1个回答
0
投票

您的方法存在 3 个问题:

初始化自定义小部件:

你有这个:

QWidget *center = new QWidget();

window.setCentralWidget(center);
window.show();

QPushButton* push = new QPushButton("test_move");
QVBoxLayout* vlayout = new QVBoxLayout();
vlayout -> addWidget(push);
center->setLayout(vlayout);

test_paint* d = new test_paint(center);

d
初始化为
center
作为其父级,并且不将其包含在任何布局中。那是在您使
window
center
的父级)可见之后,这是一个问题,因为父级小部件只有在其本身可见之前添加,才会使其子级可见(请参阅如何做上的我的答案)使添加到插槽中的子小部件可见?)。

要解决这个问题,您可以将初始化移到父级的

show
之前:

QWidget *center = new QWidget();

window.setCentralWidget(center);

test_paint* d = new test_paint(center);

window.show();

QPushButton* push = new QPushButton("test_move");
QVBoxLayout* vlayout = new QVBoxLayout();
vlayout -> addWidget(push);
center->setLayout(vlayout);

或者,您可以致电

d.show();

但是,这仍然行不通:

  • 如果您使用第一种解决方案,您仍然看不到任何可见的东西。
  • 如果您选择第二个,
    d
    将成为第二个窗口。

这是因为第二个问题:

构造者:

您有以下内容作为您的构造函数:

test_paint(QWidget* device) { paper = device; }

这不会使用您作为 device 传递的父窗口小部件

初始化基类
,因此无法让您从窗口小部件之间的父/子关系中受益。

这会导致不正确的事件处理和传播,并最终导致

paintEvent
不被触发,或导致第二个窗口,所有这些都在QWidget文档中提到:

QWidget *parent = nullptr
是新小部件的父级。如果是
nullptr
(默认),新的小部件将是一个窗口。如果不是,它将是父级的子级,并受到父级几何形状的约束(除非您指定 Qt::Window 作为窗口标志)。

因此您可以按如下方式修复该问题:

test_paint(QWidget* device) : QWidget(device) { paper = device; }
  base class initialization ->^^^^^^^^^^^^^^^

再次,这会出现另一个问题:

尝试在其绘制事件之外绘制小部件:

test_paint::paintEvent
中,你有这个:

QPainter p(paper);

这意味着您想在

paper
之上绘制/绘制,但是当前的
paintEvent
d
而不是
paper
,这将导致您出现以下警告:

QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::setPen: Painter not active

要解决这个问题,您应该使用当前的小部件并在其上绘图:

QPainter p(this);

这是一个简化的、最小的示例:

#include <QApplication>
#include <QtWidgets>

class test_paint : public QWidget
{
public:
    test_paint(QWidget* parent) : QWidget(parent) {}

protected:
    void paintEvent(QPaintEvent* e) override
    {
        qDebug()<<"painting"<<size();
        QPainter p(this);

        p.fillRect(rect(), Qt::white);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QWidget w;
    test_paint d(&w);
    QPushButton push("test");
    QVBoxLayout vlayout;

    vlayout.addWidget(&push);
    w.setLayout(&vlayout);

    QObject::connect(&push, &QPushButton::clicked, [&d]()
    {
        qDebug()<<"updating";
        d.update();
    });

    w.show();

    return a.exec();
}

结果:

一些输出:

painting QSize(100, 30)
painting QSize(100, 30)
painting QSize(100, 30)
updating
painting QSize(100, 30)
painting QSize(100, 30)
painting QSize(100, 30)
updating
painting QSize(100, 30)
painting QSize(100, 30)
painting QSize(100, 30)
© www.soinside.com 2019 - 2024. All rights reserved.