我想实现一个自定义小部件。通过双击将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之间的区域,则会如应显示节点。
请注意,QT已经在非常好的图形场景窗口小部件中构建。看看图形视图框架。它针对数千个项目进行了优化,在单个场景上支持多个视图,缩放,剪切,旋转等。
但是,如果您想自己处理:
油漆事件中的坐标始终相对于小部件根。因此,(0,0)
是小部件的左上角,无论放置位置如何(请参阅坐标系)。
直接将子小部件(作为节点)直接添加到一个小部件(而不是使用布局)时,您将放置在左上角。它的大小由sizeHint
。
现在,当您单击例如在(200,200)
,您将添加一个新的小部件,并相应地设置其位置成员。这会导致在GraphView
小部件中的Node
窗口小部件的 (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);
}