Qt 如何将widget 绘画重定向到parent widget?
Qt how to redirect widget painting to parent widget?
我正在创建一些用于绘图目的的自定义 qt 设计器小部件插件。通过这些小部件,用户可以像 Microsoft Visio 一样使用 qt designer 进行绘图(希望如此)。
如下图所示,有一个SvPage object page_0作为容器,它包含一个SvArc widget和一个SvCircle widget。
一切都很好,除了当一个小部件 (A) 覆盖另一个小部件 (B) 时,用户无法轻易 select 小部件 B。
为了解决这个问题,我正在尝试做:
将每个绘图小部件(例如 SvArc、SvCircle)的大小设置为非常小 (40px * 40 px);
将绘图小部件的内容直接绘制到其 parent 小部件 (SvPage)。在 SvPage::PaintEvent(QPaintEvent <em>event)
中,它迭代所有 children 绘图部件并调用 doPaint(QPainter</em>画家)
方法各children.
3。要自动刷新绘图控件(例如,当SvArc 控件被移动时,它在SvPage 上的绘图应该自动更新),在绘图控件的SvArc::PaintEvent(QPaintEvent *event)
中,它会触发SvPage 更新它的绘图。
但是在步骤3中,有一个问题会导致recursive repaint issue:
因为 SvArc::PaintEvent() 触发 SvPage::PaintEvent(),然后 SvPage::PaintEvent() 将再次触发 SvArc::PaintEvent() 因为 SvArc 小部件是 SvPage 小部件的 child 小部件.
所以,问题是将小部件绘制重定向到 parent 小部件是个好主意吗?如果是,如何解决递归重绘问题?如果没有,那有什么好?
代码(简体):
void SvPage::paintEvent(QPaintEvent *event)
{
initPainter();
QList<SvWidget*> widgets = this->findChildren<SvWidget*>();
for (int i = 0; i < widgets.count(); i++)
{
SvWidget* w = widgets.at(i);
w->doPaint(this->painter);
}
destoryPainter();
}
void SvWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
emit signalDoPaint();
}
void SvArc::doPaint(QPainter* painter)
{
painter->drawArc(x, y, w, h, a alen);
}
你把事情搞砸了。
每个小部件都应该负责自己的绘图。这就是 Qt 设计的工作方式。
您可以使用单个小部件作为某些对象的管理器并绘制它们,但是这些对象不必是小部件,它们可以是简单的数据表示。在那种情况下,对象将不关心任何绘画,它将由管理器小部件完成。
然而,这种方法效率较低。因为当你有多个独立的小部件时,绘制引擎可以轻松检测到变化并有效地只重绘需要更新的部分。
在您的情况下,您要么必须进行大量冗余重绘,要么实施更复杂的项目管理,这将是一项复杂的任务,如果您愿意的话,绝对不值得付出努力首先,您可能不是。
你现在的做法很糟糕。我建议只坚持使用实际尺寸的常规小部件,进行实际绘画。你实现和管理起来会容易很多,电脑画起来也会容易很多。
至于在重叠的小部件之间进行选择,QWidget
并不是真正为了促进这一点而设计的。小部件应该放在布局中,而不是重叠。这就是为什么它的 childAt()
函数只能 return 给定坐标处的单个小部件。
你真正应该做的是使用QGraphicsScene
、QGraphicsView
和QGraphicsItem
。与小部件类似,图形项目将有效地处理自己的绘图,不同之处在于 API 是为图形设计的,当您有重叠项目时,QGraphicsScene::items()
将为您提供该位置所有项目的列表, 所以你可以选择除最上面的项目。
I'm creating some custom Qt Designer widget plugin for drawing purpose. With these widgets, user can use Qt Designer for drawing just like Microsoft Visio (hopefully).
您在 Qt Designer 中重复使用的功能很少,可以很容易地分解到一个单独的项目中。唯一对您有价值的是 属性 检查器窗格。
对于其他一切,使用小部件是最复杂的实现方式。使用 QGraphicsScene
和 QGraphicsView
,并从 90% 的功能已经实现并准备就绪开始。
在 QGraphicsScene
中实现一个基本的矢量插图系统是一个下午的工作。您可以在几天内完成 Windows 2.x 次具有早期 Corel Draw 功能的内容。它证明了场景框架和一般现代开发框架的强大功能。
我正在创建一些用于绘图目的的自定义 qt 设计器小部件插件。通过这些小部件,用户可以像 Microsoft Visio 一样使用 qt designer 进行绘图(希望如此)。
如下图所示,有一个SvPage object page_0作为容器,它包含一个SvArc widget和一个SvCircle widget。
一切都很好,除了当一个小部件 (A) 覆盖另一个小部件 (B) 时,用户无法轻易 select 小部件 B。
为了解决这个问题,我正在尝试做:
将每个绘图小部件(例如 SvArc、SvCircle)的大小设置为非常小 (40px * 40 px);
将绘图小部件的内容直接绘制到其 parent 小部件 (SvPage)。在
SvPage::PaintEvent(QPaintEvent <em>event)
中,它迭代所有 children 绘图部件并调用doPaint(QPainter</em>画家)
方法各children.
3。要自动刷新绘图控件(例如,当SvArc 控件被移动时,它在SvPage 上的绘图应该自动更新),在绘图控件的SvArc::PaintEvent(QPaintEvent *event)
中,它会触发SvPage 更新它的绘图。
但是在步骤3中,有一个问题会导致recursive repaint issue: 因为 SvArc::PaintEvent() 触发 SvPage::PaintEvent(),然后 SvPage::PaintEvent() 将再次触发 SvArc::PaintEvent() 因为 SvArc 小部件是 SvPage 小部件的 child 小部件.
所以,问题是将小部件绘制重定向到 parent 小部件是个好主意吗?如果是,如何解决递归重绘问题?如果没有,那有什么好?
代码(简体):
void SvPage::paintEvent(QPaintEvent *event)
{
initPainter();
QList<SvWidget*> widgets = this->findChildren<SvWidget*>();
for (int i = 0; i < widgets.count(); i++)
{
SvWidget* w = widgets.at(i);
w->doPaint(this->painter);
}
destoryPainter();
}
void SvWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
emit signalDoPaint();
}
void SvArc::doPaint(QPainter* painter)
{
painter->drawArc(x, y, w, h, a alen);
}
你把事情搞砸了。
每个小部件都应该负责自己的绘图。这就是 Qt 设计的工作方式。
您可以使用单个小部件作为某些对象的管理器并绘制它们,但是这些对象不必是小部件,它们可以是简单的数据表示。在那种情况下,对象将不关心任何绘画,它将由管理器小部件完成。
然而,这种方法效率较低。因为当你有多个独立的小部件时,绘制引擎可以轻松检测到变化并有效地只重绘需要更新的部分。
在您的情况下,您要么必须进行大量冗余重绘,要么实施更复杂的项目管理,这将是一项复杂的任务,如果您愿意的话,绝对不值得付出努力首先,您可能不是。
你现在的做法很糟糕。我建议只坚持使用实际尺寸的常规小部件,进行实际绘画。你实现和管理起来会容易很多,电脑画起来也会容易很多。
至于在重叠的小部件之间进行选择,QWidget
并不是真正为了促进这一点而设计的。小部件应该放在布局中,而不是重叠。这就是为什么它的 childAt()
函数只能 return 给定坐标处的单个小部件。
你真正应该做的是使用QGraphicsScene
、QGraphicsView
和QGraphicsItem
。与小部件类似,图形项目将有效地处理自己的绘图,不同之处在于 API 是为图形设计的,当您有重叠项目时,QGraphicsScene::items()
将为您提供该位置所有项目的列表, 所以你可以选择除最上面的项目。
I'm creating some custom Qt Designer widget plugin for drawing purpose. With these widgets, user can use Qt Designer for drawing just like Microsoft Visio (hopefully).
您在 Qt Designer 中重复使用的功能很少,可以很容易地分解到一个单独的项目中。唯一对您有价值的是 属性 检查器窗格。
对于其他一切,使用小部件是最复杂的实现方式。使用 QGraphicsScene
和 QGraphicsView
,并从 90% 的功能已经实现并准备就绪开始。
在 QGraphicsScene
中实现一个基本的矢量插图系统是一个下午的工作。您可以在几天内完成 Windows 2.x 次具有早期 Corel Draw 功能的内容。它证明了场景框架和一般现代开发框架的强大功能。