2017-08-14 220 views
1

Qt具有与小部件分开的布局系统类型,这会导致我出现问题。我知道,当我有一个了QSplitter,我可以做Qt小部件在彼此之上堆叠子布局

new SomeCustomQWidget(splitter); 

但是添加的东西给它,如果我有一个QWidget,我不应该能够做同样的事情? Qt网页仅解释如何将layoutItems添加到布局,只通过继承两个子类来将它们连接到小部件。所以,正确的无我做这样的事情

item = new QWidget(parentsplitter); //this works 
subitem = new customWidget(item); //this too 
subitem2 = new QSlider(item); //this isn't laid out with subitem 

然而,这导致滑动器的子项的顶部,而不是被旁边(右侧或低于我期望)。调用

//either 
new QVBoxLayout(item); 
//or 
item->setLayout(new QVBoxLayout()); 
//or 
item->setLayout(new QVBoxLayout(item)); 

在初始化项目后没有帮助。 (我的逻辑是该项目将布局作为子项目并将添加后续子项)。

我早些时候解决了这个问题,但现在我在QGraphicsView中制作一个小部件时面临完全相同的问题。我觉得应该不需要为我想要动态添加到这些小部件的每个项目创建一个自定义子类,就像Qt网站所期望的那样。 (如果我只是想添加一些文本和几个按钮,我真的需要制作2个自定义子类吗?)我使用.ui文件进行基本布局,但这些项目需要动态创建。

解决方案

忘了打电话给item->show();在用于布局的部件。

原来,我测试过其他正确的代码,但由于我的一些子类调用了show(),但其他一些子类却没有,所以这只是对我而言是打破了。

但这不是graphicswidgets的问题,因为graphicslayout只能用于添加graphicslayoutite,它不包括例如graphicstextitems。

解决方案2 使用QGraphicsProxyWidget代替QGraphicsWidget固定的问题!

回答

1
QWidget *parent = new QWidget(); 
QVBoxLayout *rootLayout = new QVBoxLayout(parent); 
QHBoxLayout *subLayout1 = new QHBoxLayout(); 
QHBoxLayout *subLayout2 = new QHBoxLayout(); 
rootLayout->addLayout(subLayout1); 
rootLayout->addLayout(subLayout2); 

subLayout1->addWidget(new QLabel("Foo")); 
subLayout1->addWidget(new QLabel("Bar")); 

subLayout2->addWidget(new QPushButton("Foo button")); 
subLayout2->addWidget(new QPushButton("Bar button")); 

parent->show(); 

注意一旦布局由setLayout的指派给小部件或当widger被传递到构造FO布局,在1对1的关系,其持续到插件或布局被破坏。请参阅documentation

如果已经在此窗口小部件上安装了布局管理器,则QWidget不会让您安装另一个窗口。您必须先删除现有布局管理器(由layout()返回),然后才能使用新布局调用setLayout()。

这就是为什么subitem2 = new QSlider(item)不适合你。

0

我觉得你很困惑父母/孩子的关系与管理布局。

让我们从布局开始。在小部件上设置时,布局将成为该小部件的子项。当使用窗口小部件父窗体构建时,窗口小部件将变为父窗体,并在窗口小部件上设置布局。在向布局添加小部件时,它们将成为布局设置的小部件的子项,而不是布局本身。在小部件上设置父项或用父项构建小部件不会自动将小部件添加到其父布局。删除布局不会删除由它控制的小部件,因为它们不是它的子项。

总结 - 布局和养育是两个不同的机制。首先是管理小部件的位置和大小,另一个是用于对象层次和资源管理(父母删除他们的子女)。虽然布局有一个方便的构造函数,但这两者都是 - 设置布局的父级,并在父级小部件上设置布局。

在代码:

item = new QWidget() 
layout = new QVBoxLayout(item); 

等同于:

item = new QWidget(); 
layout = new QVBoxLayout(); 

layout->setParent(item); 
item->setLayout(layout); 

该代码添加一个孩子的布局和项目成为其母公司:

item = new QWidget(); 
layout = new QVBoxLayout(item); 
child = new QWidget(); 
layout->addWidget(child); 

这增加了孩​​子到父项,但是不是添加孩子到布局:

item = new QWidget(); 
layout = new QVBoxLayout(item); 
child = new QWidget(item); 

一个了QSplitter的特殊之处在于它是一个小部件,当你使用分离器作为窗口小部件的几何形状由分离器支配的小工具的父它自己的孩子,即布局。其他小部件的行为不像那样。

所以要注释代码:

item = new QWidget(parentsplitter); //this works because splitter does layout 
subitem = new customWidget(item); //item is not splitter so subitem geometry is not managed 
subitem2 = new QSlider(item); //item is not splitter so subitem2 geometry is not managed 

如果你想展示的项目子项目,然后按项目要么必须是一个分离器也还是有一个布局将管理孩子,所以:

childsplitter = new QWidget(parentsplitter); //note that parentsplitter has only 1 item 
subitem = new customWidget(childsplitter); 
subitem2 = new customWidget(childsplitter); 

widget = new QWidget(parentsplitter); //note that parentsplitter has only 1 item 
lay = new QHBoxLayout(widget); 
subItem = new customWidget(); 
subItem2 = new customWidget(); 
lay->addWidget(subItem); 
lay->addWidget(subItem2); 

如果你想父母分离器有两个项目,那么你做的事:

item = new customWidget(parentsplitter); 
item2 = new customWidget(parentsplitter);