自定义 Qt 设计器小部件:包含自定义垂直布局的滚动区域

Posted

技术标签:

【中文标题】自定义 Qt 设计器小部件:包含自定义垂直布局的滚动区域【英文标题】:Custom Qt designer widget : a scroll Area containing a custom vertical layout 【发布时间】:2013-08-13 11:27:05 【问题描述】:

我想做一些相当简单的事情:向 Qt 设计器添加一个自定义小部件,它基本上是一个包含自定义垂直布局的滚动区域(我向垂直布局添加了一些代码,以便为我的项目处理其对象)。 这个想法是代表一个垂直菜单,将在我的屏幕一侧

到目前为止我做了什么

我创建了自定义小部件插件和自定义布局。

我的自定义小部件代码如下所示:

#include "menuwidget.h"

MenuWidget::MenuWidget(QWidget *parent) :
        QScrollArea(parent)

    this->setWidgetResizable(true);
    QWidget* layoutHoldingWidget= new QWidget(this);
    layout= new MenuLayout();
    layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
    layout->addStretch(1);
    layoutHoldingWidget->setLayout(layout);
    this->setWidget(layoutHoldingWidget);

如果我手动添加到布局中(在构造函数代码中)一些按钮

for(int i =0;i<20;i++)
    layout->addWidget(new QPushButton(this));

它确实有效,我可以看到我的滚动区域包含一些按钮,这几乎是我想要的。

我想要什么

我希望能够直接通过 Qt 设计器添加这些按钮:用户首先将空的 MenuWidget 拖到主窗口上,然后将 QPushButtons 拖到我的自定义小部件上,就像他在常规垂直布局上所做的那样。

这可能吗?我怎么能这样做?

谢谢! :)

编辑 1

我缺少的是在拖放 QScrollArea 时始终创建的“scrollAreaWidgetContents”小部件。我做了类似的事情,在其 domXml 函数中将一个小部件(我们称之为 containerWidget)添加到我的自定义 scrollArea 中,这使我能够像我想做的那样将小部件拖放到我的滚动区域上。

但是我仍然无法弄清楚:我希望 containerWidget 有一个 customLayout (myCustomLayout) 。如果我在 domXml 函数中添加它,我会在终端中得到以下行:

Designer:不支持布局类型“MyCustomLayout”, 默认为网格。

所以这意味着我不能告诉设计师使用我的自定义布局来放置我的小部件,这有点可悲:D

这里有什么办法可以“作弊”吗?

【问题讨论】:

阅读 QtDesigner 中的自定义小部件qt-project.org/doc/qt-4.8/designer-using-custom-widgets.html 我已经阅读过这方面的内容,但我不明白它对我有什么帮助。我认为我的问题非常具体。 给定的链接和链接的文档解释了如何使用自己的小部件和小部件插件扩展 qt 设计器 谢谢,但我已经无数次阅读这个文档了。我需要一些关于这个特定问题的帮助... 我将给定的选项用于子类小部件,并使用 qt-project.org/doc/qt-4.8/designer-creating-custom-widgets.html 或 qt-project.org/doc/qt-4.8/qtdesigner.html 指南为 QtDesigner 创建插件。所有步骤都应在其中提及。根据您的描述,您还没有创建一个完整的插件,只是一个替代品。您的下一步将是重新实现指南中提到的给定虚拟功能。据我所知,那里几乎涵盖了所有内容,因此最终请再次阅读这些链接。 【参考方案1】:

有两点需要考虑:

1) 在从 QDesignerCustomWidgetInterface 派生的类中覆盖函数以返回 true

bool isContainer() const  return true; 

这告诉 QtDesigner 小部件可以包含孩子。 (在 Qt 中,几乎任何 Widget 都可以包含任何子部件,但 QtDesigner 试图以合理的方式限制它 - 例如,您不能将子部件添加到 QtDesigner 中的 QLabel)

2) 实现 Widget 的 childEvent。可能在您的情况下,它会将 QtDesigner 中添加的小部件添加到布局中。

这是我实施的一个核心来尝试这一点。我在 QtCreator 中使用“Qt Widget Plugin”向导创建了一个骨架,并稍作修改。

不要忘记将 QtDesigner 的编译器/Qt 版本构建为 release,将 \plugins\designer 目录中的 .dll 和 .lib 文件复制到 重启 QtDesigner!

verticalplugin.cpp

//all other functions remained as created by QtCreator wizard
bool VerticalMenuPlugin::isContainer() const

    return true;

VerticalMenu.h

#ifndef VERTICALMENU_H
#define VERTICALMENU_H

#include <QtGui/QWidget>
#include <QtGui/QVBoxLayout>

class VerticalMenu : public QWidget

    Q_OBJECT

protected:
    virtual void childEvent ( QChildEvent * event );
public:
    VerticalMenu(QWidget *parent = 0);
;

#endif

VerticalMenu.cpp

#include "verticalmenu.h"
#include <QChildEvent>

VerticalMenu::VerticalMenu(QWidget *parent) :
    QWidget(parent)

    setLayout (new QVBoxLayout);


void VerticalMenu::childEvent ( QChildEvent * event )

    if ( event->added() )
    
        QWidget * newChild = qobject_cast<QWidget *>(event->child());
        if ( newChild )
        
            layout()->addWidget( newChild );
        
    

我希望'这将有助于作为一个起点。

【讨论】:

感谢您的回答!我肯定会用 childEvent 方法尝试这种方式,这似乎是解决我的问题的一个很好的方法:)【参考方案2】:

Qt 4 does not support custom layout plugins for designer,所以我无法实现我想做的事情。我将改为使用垂直布局,并尝试在小部件代码中实现应该在自定义布局代码中的附加功能。

【讨论】:

哦,我迟到了 12 分钟 :-( +1:感谢您的链接!然而,也可以按照我建议的方式解决这个问题。为什么它毕竟应该是一个布局? Qt Designer 创建一个完全可操作的、相同的 Widget(除非在 createWidget 中另外指定),其行为与运行时的小部件相同。当您指定布局子级、创建新的子级本身、在 Qt Designer 的 GUI 中移动等时,这个小部件当然可以管理它的内容)。我猜,qt-project 论坛的开发者太专注于自定义 QLayout,而不是解决她的问题。 (没有人需要钻孔器,但需要一个洞)

以上是关于自定义 Qt 设计器小部件:包含自定义垂直布局的滚动区域的主要内容,如果未能解决你的问题,请参考以下文章

如何让 qt 设计器自定义 QOpenGLWidget 小部件背景透明?

✿3-The Basics-使用Qt Widgets进行GUI设计

✿3-The Basics-使用Qt Widgets进行GUI设计

✿3-The Basics-使用Qt Widgets进行GUI设计

如何在 Qt 中制作可展开/可折叠的部分小部件

在 Qt 设计器中创建要提升的自定义小部件