Qt5 paintEvent () область слишком мала - PullRequest
0 голосов
/ 18 февраля 2019

Я хотел реализовать собственный виджет.При добавлении объекта 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 голосов
/ 18 февраля 2019

Обратите внимание, что Qt уже встроил очень хороший виджет графической сцены.Взгляните на Graphics View Framework .Он оптимизирован для тысяч элементов, поддерживает несколько видов для одной сцены, масштабирование, сдвиг, поворот и т. Д.


Но если вы хотите справиться с этим самостоятельно:

Координаты всобытие рисования всегда относительно корня виджета.Таким образом, (0,0) - это верхний левый угол виджета, независимо от того, где он находится (см. системы координат ).

Когда вы добавляете вспомогательный виджет (как ваши узлы) непосредственно ввиджет (в отличие от использования макета), вы его размещаете в верхнем левом углу.Его размер определяется как 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);
}
...