【问题标题】:Qt: Multiple layouts for a custom widgetQt:自定义小部件的多个布局
【发布时间】:2018-03-04 00:35:23
【问题描述】:

我正在开发一个由其他小部件(按钮、标签、查看器等)组成的自定义小部件,它将成为其他项目中的一个模块。对此自定义小部件具有多种布局非常重要。

布局将根据一些动态确定的因素而改变,例如作为一部分的应用程序(例如,对于 X 应用程序,我们希望事物垂直排列,或者我们希望 Z 小部件位于 M 小部件旁边,而不是一个在另一个之下) 并且还取决于检测到的功能(如果未检测到硬件 X,则隐藏 A、B、C 小部件)。

到目前为止,我在 Designer Form 中只有一个布局,我会在运行中以编程方式对其进行一些修改以进行小的重新排列。这不再可行,因为在某些应用程序中我们需要完全不同的布局。

因此,总而言之,我们有固定数量的小部件,但我们希望根据一些动态确定的因素进行不同的重新排列和可见性。

处理这种情况的正确方法是什么?

到目前为止我想到的解决方案:

  • 创建多个 .ui 文件并使用QUiLoader动态加载我需要的文件

  • 纯粹以编程方式创建布局

  • 使用堆叠的小部件创建单个 .ui 文件,每个页面将是不同的布局。切换布局时,“活动”布局的小部件将由指针分配。

【问题讨论】:

  • 单个大的 GUI 定义文件经常出现问题,在进行更改时会出现意外问题(不限于 Qt Designer 的 .ui 文件)。
  • 我认为这取决于使用第三个选项的复杂性。
  • 您缺少选项,创建做一件事的独立小部件。它们可以是纯 C++ 或使用 .ui 文件,这无关紧要,因为它们是独立的、自包含的 GUI 组件。然后使用 Designer 的提升功能在 Designer 中实际使用它们。此外,在没有 Designer 的情况下,在纯 C++ 代码中实现顶层可能是最简单的。
  • @drescherjm 由于您提到的原因,我并不真正支持第三种选择,它的复杂性而且对我来说似乎也不“正确”。但如果它比其他 2 个不那么麻烦,那么我可能会去。
  • @hyde 在我的自定义小部件中,我已经有其他使用促销的自定义小部件。此外,上述自定义小部件将在其他更大的应用程序中得到推广。

标签: c++ qt


【解决方案1】:

我建议选项 #2,以及一种简洁的实现方式。

如果您的自定义小部件只是一个带有一些子小部件的 QWidget 子类,您可以添加一个受保护的虚拟方法,该方法只负责布置子类,以及一个静态工厂方法来实例化正确的子类,具体取决于运行时配置选项.

只需将子实例设置为受保护成员,以便子类可以访问它们,添加受保护的customlayout纯虚方法、公共initialize方法和静态create方法。在构造函数中,只需设置子小部件并连接信号和插槽(不要介意子位置和可见性,在这里)。调用后,initialize 方法会将虚函数返回的布局设置为自定义小部件布局。

class CustomWidget : public QWidget
{
    Q_OBJECT

protected:

    virtual QLayout * customlayout() = 0;

    QLabel a;
    QLineEdit b;
    QPushButton c;

public:
    CustomWidget(QWidget * p) : QWidget(p)
    {
        a.setText("Text:");
        c.setText("Ok");

        //setup signals/slot etc.

    }
    void initialize()
    {
        setLayout(customlayout());
    }

    static CustomWidget * create();
};

几种可能的实现方式:

#include <QHBoxLayout>

class XCustomWidget : public CustomWidget
{
public:
    XCustomWidget() : CustomWidget(nullptr){}
protected:
    QLayout * customlayout() override
    {
        QHBoxLayout * l = new QHBoxLayout();
        l->addWidget(&a);
        l->addWidget(&b);
        l->addWidget(&c);
        return l;
    }
};

#include <QVBoxLayout>

class YCustomWidget : public CustomWidget
{
public:
    YCustomWidget() : CustomWidget(nullptr){}
protected:
    QLayout * customlayout() override
    {
        QVBoxLayout * l = new QVBoxLayout();
        l->addWidget(&a);
        l->addWidget(&b);
        c.setVisible(false);
        l->addStretch(1);
        return l;
    }
};

一个可能的工厂实现:

CustomWidget *CustomWidget::create()
{
    //read configuration ...

    if(isApplicationX)
    {
        return new XCustomWidget();
    }

    if(isApplicationY)
    {
        return new YCustomWidget();
    }
}

以及实例化(例如在表单构造函数中):

CustomWidget * w = CustomWidget::create();
w->initialize();
layout()->addWidget(w);

【讨论】:

  • 非常感谢您的回答!
猜你喜欢
  • 2014-09-03
  • 1970-01-01
  • 2012-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-13
  • 2014-12-17
  • 2018-07-01
相关资源
最近更新 更多