我有一个带有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/