Qt:自定义小部件的多个布局

时间:2018-03-02 12:34:42

标签: c++ qt

我正在开发一个自定义小部件,其中包含其他小部件(按钮,标签,查看器等),这些小部件将成为其他项目中的模块。为此自定义窗口小部件设置多个布局非常重要。

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

到目前为止,我在Designer Form中有一个单独的布局,我会在程序上稍微修改一下以进行小的重新排列。这不再可行,因为在某些应用程序中我们需要一个完全不同的布局。

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

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

到目前为止我一直在考虑的解决方案:

  • 使用QUiLoader

  • 创建多个.ui文件并动态加载我需要的文件
  • 以编程方式创建布局

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

1 个答案:

答案 0 :(得分:1)

我建议选择#2,并采用一种干净的方式来实现它。

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

只需将子实例作为受保护成员,以便子类可以访问它们,添加protectedd 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);