我要做的是将qwidget渲染到另一个窗口(手动使用QPainter)
我有一个带有布局和一堆子控件的QWidget(w)。 w是隐藏的。在显示w之前,没有发生布局计算,这是预期的。
当我致电w->render(painter, w->mapToGlobal(QPoint(0,0))
时,我得到了一堆彼此重叠的控件
w->layout()->activate();w->layout()->update()
似乎没有做任何事情。
有没有办法强制布局发生而不显示w?
答案 0 :(得分:17)
在窗口小部件上强制进行布局计算而不在屏幕上显示:
widget->setAttribute(Qt::WA_DontShowOnScreen);
widget->show();
show()
调用将强制执行布局计算,Qt::WA_DontShowOnScreen
确保未显式显示窗口小部件。
答案 1 :(得分:10)
即使窗口小部件被隐藏,也可以通过在其布局上调用invalidate()
后跟activate()
来强制窗口小部件的布局计算。这也会导致窗口小部件的size()
和sizeHint()
函数返回正确和更新的值,即使尚未在该窗口小部件上调用show()
。
然而,有必要递归地关注所有子窗口小部件和布局,因为布局重新计算请求不会自动传播给子窗口。
以下代码显示了如何执行此操作。
/**
* Forces the given widget to update, even if it's hidden.
*/
void forceUpdate(QWidget *widget) {
// Update all child widgets.
for (int i = 0; i < widget->children().size(); i++) {
QObject *child = widget->children()[i];
if (child->isWidgetType()) {
forceUpdate((QWidget *)child);
}
}
// Invalidate the layout of the widget.
if (widget->layout()) {
invalidateLayout(widget->layout());
}
}
/**
* Helper function for forceUpdate(). Not self-sufficient!
*/
void invalidateLayout(QLayout *layout) {
// Recompute the given layout and all its child layouts.
for (int i = 0; i < layout->count(); i++) {
QLayoutItem *item = layout->itemAt(i);
if (item->layout()) {
invalidateLayout(item->layout());
} else {
item->invalidate();
}
}
layout->invalidate();
layout->activate();
}
答案 2 :(得分:1)
尝试使用QWidget::sizeHint()
方法,该方法应该在布局后返回小部件的大小。
答案 3 :(得分:0)
当使用sizeHint()加上翻译画家时,这对我有用,但是我在paint()方法中这样做。
void ParentWidget::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
painter->save();
painter->translate(option.rect.topLeft());
w->render(painter);
painter->restore();
}
在这种情况下,option.rect.topLeft()
为我提供了正确的展示位置。您应该尝试更合理的坐标,而不是w->mapToGlobal(QPoint(0,0)
。
答案 4 :(得分:0)
首先在w->layout()->update()
之前调用w->layout()->activate()
,我在类似问题上取得了一些成功。这似乎迫使activate()实际做某事而不是认为它很好,因为无论如何都没有显示窗口。