我有一个带有MdiChilds的应用程序,其中应包含多个QDockWidgets。但是,我在拆分/设置窗口小部件时遇到麻烦,因此它们无法生成所需的默认布局。
我基本上想要这样的布局:

小部件4是最后创建的,需要移到列表化的小部件2和3旁边。但是,插入它会导致自身和另一个小部件丢失:

这是产生第二个屏幕截图的代码:

在主窗口的构造函数中(或mdi childs并不重要),我执行以下操作:

QDockWidgetTest::QDockWidgetTest(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    setCentralWidget(0); // only QDockWidgets
    QWidget* testWidget1 = new TestWidget("1", QColor("red"));
    QWidget* testWidget2 = new TestWidget("2", QColor("green"));
    QWidget* testWidget3 = new TestWidget("3", QColor("blue"));
    QWidget* testWidget4 = new TestWidget("4", QColor("yellow"));
    DockWidgetWrapper* testQWidget1 = new DockWidgetWrapper(testWidget1, "Test Widget 1", "TestWidget1");
    DockWidgetWrapper* testQWidget2 = new DockWidgetWrapper(testWidget2, "Test Widget 2", "TestWidget2");
    DockWidgetWrapper* testQWidget3 = new DockWidgetWrapper(testWidget3, "Test Widget 3", "TestWidget3");
    DockWidgetWrapper* testQWidget4 = new DockWidgetWrapper(testWidget4, "Test Widget 4", "TestWidget4");
    addDockWidget(Qt::LeftDockWidgetArea, testQWidget1);
    splitDockWidget(testQWidget1, testQWidget2, Qt::Vertical);
    tabifyDockWidget(testQWidget2, testQWidget3);
    splitDockWidget(testQWidget3, testQWidget4, Qt::Horizontal);
}

其中TestWidget被定义为一个简单的Widget,只是以给定的颜色绘制自身,标题位于中间:
#include <QWidget>
#include <QPainter>
#include <QPaintEvent>
#include <QFontMetrics>

class TestWidget: public QWidget
{
private:
    QString m_content;
    QColor m_fillColor;
public:
    TestWidget(QString content, QColor color):
        m_content(content),
        m_fillColor(color)
    {
        m_fillColor.setAlpha(50);
    }
protected:
    void paintEvent(QPaintEvent* e)
    {
        QPainter p(this);
        QFontMetrics fm(p.font());
        QRect g(geometry());
        p.fillRect(g, m_fillColor);
        p.drawText(g.width()/2 - fm.width(m_content), g.height()/2 + fm.height(), m_content);
    }
};

DockWidgetWrapper是QDockWidget的简单包装,可用于任何QWidget:
#include <QDockWidget>
#include <QVBoxLayout>

class DockWidgetWrapper: public QDockWidget
{
public:
    DockWidgetWrapper(QWidget* widget, QString const & windowTitle, QString const & objectName)
    {
        setWindowTitle(windowTitle);
        setFeatures(DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable);
        setWidget(widget);
        setObjectName(objectName);
    }
};

在最后一次splitDockWidget调用之后,窗口小部件3和4完全消失了,因此,在已标准化的窗口小部件上调用splitDockWidget会使要插入的和已标准化的窗口小部件都消失。如果我在QDockWidget header 上显示上下文菜单,并使Widget2通过它消失,则该应用看起来更加奇怪:

因此,应该有一个小部件3和4处于空白区域(根据上下文菜单,Qt似乎仍在显示它们的印象!)。仅当同时禁用这两个时,Widget1下面的空白区域才会消失。

如果我先拆分然后列表化,那就很好。问题是我想在软件的一般部分中进行制表,然后在加载软件的特定部分时进行拆分。因此,对我来说,重新排序两者并不是真正的选择。 In the documentation我只能在此找到以下内容:



绝对不会发生这种情况。此外,此描述还有一些不足之处:在我的示例中,这意味着一旦我将选项卡2和3置于选项卡中,就无法(以编程方式)使小部件4位于两者的右侧,或者还有另一种方法可以做到这一点?

对我来说,这个问题始终在Qt 4.8和5.3中发生。我想这可能是Qt中的错误吗?这是一个已知的错误吗(到目前为止,我的搜索结果为空)?还是对此有其他合理的解释,还是“找回”两个丢失的小部件的方法?

最佳答案

我相信您对该错误的评估是正确的,因此这是一种可能的解决方法。

我发现,可以通过将停靠小部件显式添加到表单中并指定其停靠区域,然后将其制成表格,从而获得所需的结果。我知道您想要相反的顺序,但是至少这消除了怪异的 Artifact 。

首先,请确保通过设计器或像这样通过编程方式启用了基座嵌套和制表位(您可以选择在此处包括动画):

setDockOptions(DockOption::AllowNestedDocks | DockOption::AllowTabbedDocks);

然后显式添加每个扩展坞。您只添加了一个。
addDockWidget(Qt::TopDockWidgetArea, testQWidget1);
addDockWidget(Qt::LeftDockWidgetArea, testQWidget2);
addDockWidget(Qt::LeftDockWidgetArea, testQWidget3);
addDockWidget(Qt::RightDockWidgetArea, testQWidget4);

将最后一个设置为:
Qt::RightDockWidgetArea

它似乎将其定位在您想要的位置。然后致电:
tabifyDockWidget(testQWidget2, testQWidget3);

如果需要,您可以稍后以编程方式将扩展坞移动到新位置,方法是再次调用addDockWidget()。 Qt非常聪明,可以意识到您正在重新添加一个现有的Qt,因此它不会重复它。

运行此测试代码时,我唯一的问题是顶部基座似乎很大,并且占用了大部分空间。我相信,一旦向每个控件添加控件,它们的大小就会适当调整。

我很想知道您的解决方案最终是什么,因为我本人将要从事一些与 jetty 相关的工作。

希望能有所帮助。

PS-这是我潜伏多年后的第一个SO答案,所以对我轻松一点=)

关于c++ - QDockWidget tabify/splitDockWidget奇怪的行为/错误?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28151738/

10-11 23:13