【问题标题】:How to specialize a widget according to a file type?如何根据文件类型专门化一个小部件?
【发布时间】:2010-08-02 08:52:44
【问题描述】:

我正在寻找一种在运行时专门化小部件的方法。我有一个用 Qt Designer 创建的表单。在这个表单中,有一个显示用户数据的小部件,如姓名、年龄等。然后用户选择一个文件并根据类型小部件显示附加信息(如 OO 示例人员 -> 学生、教师)。

我试图在我的表单上放置一个空的 QWidget,并为其分配一个人员小部件,如果用户单击一个按钮,我会在人员上调用 deleteLater() 并分配一个 new Student()。这可行,但新的小部件随后不遵循布局。

我还发现了 QStackedWidget。这似乎可行,但因为所有可能的小部件都是在显示表单时创建的,即使它们从未使用过,这种方式感觉不对。

实现这一点的方法是什么?

编辑:我觉得我的问题有点不清楚。如果想用原始小部件的专用(继承)版本替换 QWidget,应该使用什么 Qt 机制?我正在寻找 Qt 的方式来做到这一点。

【问题讨论】:

    标签: c++ qt


    【解决方案1】:

    您需要将一个小部件动态添加到您在设计器中绘制的小部件中。

    // in UI file
    QWidget *wdgFromForm;
    
    // in cpp file 
    QHBoxLayout *const layout(new QHBoxLayout(wdgFromForm)); 
    SpecializedWidget * specializedWidget( new SpecializedWidget(wdgFromForm));
    layout->addWidget(specializedWidget);
    

    【讨论】:

    • 谢谢,这行得通。这是在Qt中完成的方式吗?我觉得有点奇怪,不是替换现有布局中浮动的现有小部件,而是必须向此小部件添加布局并将新小部件放入此新布局中。
    • 您可以动态设置整个表单,但我发现使用设计器设置表单并为上下文相关的小部件使用占位符更容易。
    • 这正是我的意图。正如我所说,我只是觉得很奇怪,我必须添加一个布局,然后添加一个新的小部件,而不是仅仅替换占位符。但无论如何,我比 QStackedWidget 方法更喜欢它。谢谢。
    【解决方案2】:

    也许问题不在于小部件不合适,而只是您没有给小部件时间更新。

    您可以查看 processEvents: http://web.mit.edu/qt-dynamic/www/qapplication.html#details

    【讨论】:

    • 对不起,我不明白你的意思。目前没有任何事件(我没有放入任何事件),只需单击示例应用程序中的按钮即可。调用 myWidget->show() 后会显示新的小部件,但它不会显示原来的小部件原来的位置。相反,它位于左上角。我是不是搞错了什么?
    • 点击按钮是一个事件。用户执行的任何操作都会转换为事件。如果您在某个应用程序事件处理程序的循环中,Qt 库将无法更新 GUI 的状态。这时候 processEvents() 就派上用场了。
    【解决方案3】:

    这看起来像是factory pattern 的用例。

    #include <map>
    #include <string>
    struct Whatever;
    struct QWidget;
    typedef QWidget*(*WidgetCtor)(Whatever*);
    typedef std::map<std::string, WidgetCtor> FileFactory;
    
    QWidget* createFoo(Whatever*);
    QWidget* createBar(Whatever*);
    QWidget* createDefault(Whatever*);
    
    void factory_init(FileFactory& ff)
    {
        ff["foo"] = createFoo;
        ff["bar"] = createBar;
    }
    
    QWidget* create_by_factory(const FileFactory& ff, const std::string t, Whatever* w)
    {
        FileFactory::const_iterator it(ff.find(t));
        if(it != ff.end())
        {
            return it->second(w);
        }
        else
        {
            return createDefault(w);
        }
    }
    

    【讨论】:

    • 感谢您的回复。如果我必须更频繁地生成这些对象,工厂会很有帮助。但在这种情况下,工厂似乎有点矫枉过正。
    【解决方案4】:

    向布局动态添加小部件不是问题。 不过,您可能需要在包含的小部件上调用 updateGeometry。

    【讨论】:

    • UpdateGeometry 不起作用。添加小部件并不安静,它更多的是用另一个小部件替换布局中的现有小部件。
    • 替换应该与添加新小部件相同。您是否在正确的小部件上调用了 updateGeometry(),即具有您插入新小部件的布局的那个?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-05
    • 2019-11-30
    • 2022-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多