[英]Clearing a Layout in Qt
我正在 Qt 中创建一个应用程序,它允许用户在 QGraphicsView 中拖动各种“模块”。 Whenever one of these modules is selected, it emits a signal which is then picked up by a "ConfigurationWidget" which is a side-panel which should display all of the relevant parameters of the selected module:
class ConfigurationWidget : public QWidget
{
Q_OBJECT
public:
ConfigurationWidget(QWidget *parent) : QWidget(parent) {}
public slots:
void moduleSelected(Module* m)
{
if(layout())
{
while (itsLayout->count()>0)
{
delete itsLayout->takeAt(0);
}
}
delete layout();
itsLayout = new QFormLayout(this);
itsLayout->addRow(QString(tr("Type:")), new QLabel(m->name()));
itsLayout->addRow(QString(tr("Instance:")), new QLabel(m->instanceID()));
// ... Display a whole bunch of other fields that depends on the module
}
};
问题是,在选择模块时,ConfigrationWidget从未实际清除。 新字段只是在旧字段上绘制。 我尝试了 hide() 和 show()、invalidate()、update() 等的各种组合,但都无济于事。
制作可以动态更改其字段的小部件的正确方法是什么?
我之前用过的代码循环如下:
void clearLayout(QLayout *layout) {
if (layout == NULL)
return;
QLayoutItem *item;
while((item = layout->takeAt(0))) {
if (item->layout()) {
clearLayout(item->layout());
delete item->layout();
}
if (item->widget()) {
delete item->widget();
}
delete item;
}
}
希望这对你有帮助!
如果您将布局转移到堆栈上分配的另一个小部件,则该布局中的小部件将成为新小部件的子部件。 当临时对象超出范围时,它会自动破坏布局和其中的所有小部件。
void moduleSelected(Module* m)
{
if(layout())
QWidget().setLayout(layout());
itsLayout = new QFormLayout(this);
itsLayout->addRow(QString(tr("Type:")), new QLabel(m->name()));
itsLayout->addRow(QString(tr("Instance:")), new QLabel(m->instanceID()));
// ... Display a whole bunch of other fields that depends on the module
}
看起来最好的方法是使用 QStackedLayout,正如 armonge 所暗示的那样:
void ConfigurationWidget::moduleSelectedSlot(Module* m)
{
QStackedLayout *stackedLayout = qobject_cast<QStackedLayout*>(layout());
QWidget *layoutWidget = new QWidget(this);
QFormLayout *formLayout = new QFormLayout(layoutWidget);
formLayout->addRow(QString(tr("Type:")), new QLabel(m->name()));
formLayout->addRow(QString(tr("Instance:")), new QLabel(m->instanceID()));
// ... Display a whole bunch of other fields that depends on the module
delete stackedLayout->currentWidget();
stackedLayout->addWidget(layoutWidget);
stackedLayout->setCurrentWidget(layoutWidget);
}
我最近在使用 QFormLayout 时遇到了同样的问题。 对我有用的(也在 Qt 的文档中: http ://qt-project.org/doc/qt-5/layout.html)是 takeAt(int) 方法。
void clearLayout(QLayout *layout)
{
QLayoutItem *item;
while ((item = layout->takeAt(0)))
delete item;
}
使用while((item = layout->takeAt(0)))
将导致警告消息“无效索引在 0”。 我用count()
代替
void clearLayout(QLayout *layout)
{
if (layout) {
while(layout->count() > 0){
QLayoutItem *item = layout->takeAt(0);
QWidget* widget = item->widget();
if(widget)
delete widget;
delete item;
}
}
}
当您希望它们从窗口中消失时,将这些项目重新设置为 NULL。 我最近遇到了类似的问题,重新养育解决了这些问题。
到目前为止,我没有发现其他任何答案都有效。 它们要么崩溃,要么没有完全清除布局。 所以这是我发现的工作,我希望其他人觉得这很有用。
void eraseLayout(QLayout * layout)
{
while(layout->count() > 0)
{
QLayoutItem *item = layout->takeAt(0);
QWidget* widget = item->widget();
if(widget)
{
delete widget;
}
else
{
QLayout * layout = item->layout();
if (layout)
{
eraseLayout(layout);
}
else
{
QSpacerItem * si = item->spacerItem();
if (si)
{
delete si;
}
}
}
delete item;
}
}
感谢Vaidotas Strazdas 的评论,我找到了正确重置布局的解决方案。 使用deleteLater()
方法效果很好,否则delete
关键字会导致刷新后的布局出现大量显示错误。
void resetLayout(QLayout* apLayout)
{
QLayoutItem *vpItem;
while ((vpItem = apLayout->takeAt(0)) != 0) {
if (vpItem->layout()) {
resetLayout(vpItem->layout());
vpItem->layout()->deleteLater();
}
if (vpItem->widget()) {
vpItem->widget()->deleteLater();
}
delete vpItem;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.