Qt5 paintEvent()区域太小

时间:2019-02-18 17:07:20

标签: c++ qt qt5

我想实现一个自定义小部件。通过双击将Node对象添加到拥有的Graph小部件时,Node::paintEvent正确地发生,但是QPaintEvent的区域是恒定的,并且无论在何处都很小我加了指示的边界重绘框始终为(0,0),宽度/高度为(100,30)。

任何想法为什么会这样?

代码

#include <QApplication>
#include <QMainWindow>
#include <QPainter>
#include <QMouseEvent>

#include <iostream>
#include <vector>

#define DEBUG(lvl, x) \
    std::clog << "L" << __LINE__ << ": " << x << "\n";

class Node final : public QWidget
{
protected:
    void paintEvent (QPaintEvent * event) override {
        DEBUG(0, "Node::paintEvent");
        QPainter painter(this);
        painter.setBrush(QColor(127,127,127));
        painter.drawRect(posX, posY, width, height);
        auto x = event->rect();
        DEBUG(0, "PaintBox:" << x.x() << "::" << x.y() << "::" << x.width() << "::" << x.height());
    }
public:
    explicit Node (QWidget * parent = 0): QWidget(parent) {}
    int posX{0}, posY{0}, width{60}, height{60};
};

class GraphView final : public QWidget
{
public:
    explicit GraphView (QWidget * parent = 0): QWidget(parent) {}
protected:
    void paintEvent (QPaintEvent *) override {
        DEBUG(0, "GraphView::paintEvent");
    }

    void mouseDoubleClickEvent (QMouseEvent * event) override {
        DEBUG(0, "mouseDoubleClickEvent");
        auto ptr = new Node(this);
        ptr->posX = event->x();
        ptr->posY = event->y();
        nodes.push_back(ptr);
        ptr->show();
    }

    void mousePressEvent (QMouseEvent * event) override {
        DEBUG(0, "mousePressEvent");
        auto ptr = static_cast<Node*>(childAt(event->pos()));
        if (ptr) {
            DEBUG(0, "FOUND X");
        }
    }
    std::vector<Node*> nodes;
};


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

    auto* gv = new GraphView{};
    QMainWindow w;
    w.setCentralWidget(gv);
    w.resize(640, 480);
    w.show();

    return a.exec();
}

在窗口区域的任何地方双击,将返回:

L34: GraphView::paintEvent
L48: mousePressEvent
L38: mouseDoubleClickEvent
L34: GraphView::paintEvent
L16: Node::paintEvent
L21: PaintBox:0::0::100::30

如果双击0,0到100,30之间的区域,节点将显示为应显示的状态。

1 个答案:

答案 0 :(得分:2)

请注意,Qt已经内置了非常好的图形场景小部件。看一下Graphics View Framework。它针对数千个项目进行了优化,在单个场景中支持多个视图,缩放,剪切,旋转等。


但是,如果您想自己处理:

paint事件中的坐标始终相对于小部件的根。因此,(0,0)是窗口小部件的左上角,与放置位置无关(请参见coordinate systems)。

将子窗口小部件(作为节点)直接添加到窗口小部件(而不是使用布局)时,它将放置在左上角。其大小由sizeHint确定。

现在,当您单击例如在(200,200),您将添加一个新的小部件,并相应地设置其位置成员。这将导致Node小部件中的GraphView小部件位于(0,0),大小为(100,30)。然后在绘画事件中,您在(200,200)处绘制一个矩形,该矩形在小部件范围之外!

您应该设置几何形状,以便将子窗口小部件放置在Qt的坐标系中:

 void GraphView::mouseDoubleClickEvent (QMouseEvent * event) {
    auto ptr = new Node(this);
    ptr->setGeometry(event->x(), event->y(), ptr->width, ptr->height);
    nodes.push_back(ptr);
    ptr->show();
}

然后基于(0,0)作图:

void Node::paintEvent (QPaintEvent * event) {
    QPainter painter(this);
    painter.setBrush(QColor(127,127,127));
    painter.drawRect(0, 0, width, height);
}