2011-12-28 150 views
12

,我想创建一个接口,我可以动态地添加或删除小部件。我想为将要添加或删除的小部件定义一个单独的类。我似乎无法获得我实例化显示在主界面内的小部件。这里是我使用的代码:使用PyQt动态添加和删除小部件在PyQt

from PyQt4 import QtGui, QtCore 
import sys 

class Main(QtGui.QMainWindow): 
    def __init__(self, parent = None): 
     super(Main, self).__init__(parent) 

     # central widget 
     self.centralWidget = QtGui.QWidget(self) 

     # main layout 
     self.vLayout = QtGui.QVBoxLayout(self.centralWidget) 

     # main button 
     self.pButton_add = QtGui.QPushButton(self.centralWidget) 
     self.pButton_add.setText('button to add other widgets') 

     # scroll area 
     self.scrollArea = QtGui.QScrollArea(self.centralWidget) 
     self.scrollArea.setWidgetResizable(True) 

     # scroll area widget contents 
     self.scrollAreaWidgetContents = QtGui.QWidget(self.scrollArea) 

     # scroll area widget contents - layout 
     self.formLayout = QtGui.QFormLayout(self.scrollAreaWidgetContents) 

     self.scrollArea.setWidget(self.scrollAreaWidgetContents) 

     # add all main to the main vLayout 
     self.vLayout.addWidget(self.pButton_add) 
     self.vLayout.addWidget(self.scrollArea) 
     # set central widget 
     self.setCentralWidget(self.centralWidget) 
     # connections 
     self.pButton_add.clicked.connect(self.addWidget) 


    def addWidget(self): 
     z = Test(self.scrollAreaWidgetContents) 
     count = self.formLayout.rowCount() 
     self.formLayout.setWidget(count, QtGui.QFormLayout.LabelRole, z) 


class Test(QtGui.QWidget): 
    def __init__(self, parent): 
     super(Test, self).__init__(parent) 

     self.pushButton = QtGui.QPushButton(self) 


app = QtGui.QApplication(sys.argv) 
myWidget = Main() 
myWidget.show() 
app.exec_() 

的事情是,当我用我的“addWidget”方法内部下面的代码,它究竟是做什么,我想要它做的,但该类方法不似乎工作。

z = QtGui.QPushButton(self.scrollAreaWidgetContents) 
count = self.formLayout.rowCount()) 
self.formLayout.setWidget(count, QtGui.QFormLayout.LabelRole, z) 

我想知道为什么z = Test()不会产生任何结果?有任何想法吗?谢谢!

回答

12

其实,它确实有效。问题是,您的Test小部件的QPushButton没有任何布局管理。所以无法考虑按钮来计算其minimumSize。当您将该小部件放入布局中时,它只会缩小至0(因为QWidget没有默认值minimumSize),您什么都看不到。

您有两种选择,无论是手动管理布局还是进入不必要的痛苦世界,或者您依赖布局管理器。一般来说,你应该更喜欢后者。

我会重新写你的脚本是这样的(虽然我不知道为什么你使用QFormLayout,我离开它,因为它是。):

from PyQt4 import QtGui, QtCore 
import sys 

class Main(QtGui.QMainWindow): 
    def __init__(self, parent = None): 
     super(Main, self).__init__(parent) 

     # main button 
     self.addButton = QtGui.QPushButton('button to add other widgets') 
     self.addButton.clicked.connect(self.addWidget) 

     # scroll area widget contents - layout 
     self.scrollLayout = QtGui.QFormLayout() 

     # scroll area widget contents 
     self.scrollWidget = QtGui.QWidget() 
     self.scrollWidget.setLayout(self.scrollLayout) 

     # scroll area 
     self.scrollArea = QtGui.QScrollArea() 
     self.scrollArea.setWidgetResizable(True) 
     self.scrollArea.setWidget(self.scrollWidget) 

     # main layout 
     self.mainLayout = QtGui.QVBoxLayout() 

     # add all main to the main vLayout 
     self.mainLayout.addWidget(self.addButton) 
     self.mainLayout.addWidget(self.scrollArea) 

     # central widget 
     self.centralWidget = QtGui.QWidget() 
     self.centralWidget.setLayout(self.mainLayout) 

     # set central widget 
     self.setCentralWidget(self.centralWidget) 

    def addWidget(self): 
     self.scrollLayout.addRow(Test()) 


class Test(QtGui.QWidget): 
    def __init__(self, parent=None): 
     super(Test, self).__init__(parent) 

     self.pushButton = QtGui.QPushButton('I am in Test widget') 

     layout = QtGui.QHBoxLayout() 
     layout.addWidget(self.pushButton) 
     self.setLayout(layout) 



app = QtGui.QApplication(sys.argv) 
myWidget = Main() 
myWidget.show() 
app.exec_() 
+0

感谢您的详细答案!我使用表单布局的原因是,我希望小部件开始出现在滚动区域的顶部,并从那里填充空白的地方,而不是在中间出现,并在创建新小部件时重新排列。虽然我确信有其他方法可以做到这一点,但formlayout对我来说似乎是一个简单的解决方案..再次感谢! – boundless 2011-12-28 08:43:04

+0

@boundless:啊,我明白了。我的做法是将'scrollLayout'封装在另一个'QVBoxLayout'中,并在下面添加一段'1'。这应该让事情处于顶峰。 – Avaris 2011-12-28 09:25:25

+0

另一件我喜欢formlayout的东西是,它可以更容易地让两个小部件相互靠近,同时保持顶部。尽管也许在那一点上,我应该只使用网格布局。再次感谢提示! – boundless 2011-12-28 22:11:37

4

这里是一个小的变化,这将使按钮删除自己一旦点击:

from PyQt4 import QtGui, QtCore 
import sys 

class Main(QtGui.QMainWindow): 
    def __init__(self, parent = None): 
     super(Main, self).__init__(parent) 

     # main button 
     self.addButton = QtGui.QPushButton('button to add other widgets') 
     self.addButton.clicked.connect(self.addWidget) 

     # scroll area widget contents - layout 
     self.scrollLayout = QtGui.QFormLayout() 

     # scroll area widget contents 
     self.scrollWidget = QtGui.QWidget() 
     self.scrollWidget.setLayout(self.scrollLayout) 

     # scroll area 
     self.scrollArea = QtGui.QScrollArea() 
     self.scrollArea.setWidgetResizable(True) 
     self.scrollArea.setWidget(self.scrollWidget) 

     # main layout 
     self.mainLayout = QtGui.QVBoxLayout() 

     # add all main to the main vLayout 
     self.mainLayout.addWidget(self.addButton) 
     self.mainLayout.addWidget(self.scrollArea) 

     # central widget 
     self.centralWidget = QtGui.QWidget() 
     self.centralWidget.setLayout(self.mainLayout) 

     # set central widget 
     self.setCentralWidget(self.centralWidget) 

    def addWidget(self): 
     self.scrollLayout.addRow(TestButton()) 


class TestButton(QtGui.QPushButton): 
    def __init__(self, parent=None): 
     super(TestButton, self).__init__(parent) 
     self.setText("I am in Test widget") 
     self.clicked.connect(self.deleteLater) 


app = QtGui.QApplication(sys.argv) 
myWidget = Main() 
myWidget.show() 
app.exec_() 

这样它不应该mem泄漏时删除和该按钮可以实际上用于东西。我遵循这种模式进行数据下载和块监控的进度条,即使使用线程和多处理,它也能正常工作。而不是简单的QThreads ...

+3

您更改了哪部分,为什么会有这种效果? – 2012-10-01 14:21:16

0

如果妳想说的是,无论何时删除一个按钮被点击,或乌尔程序的任何事件中一个小部件,使用deleteLater()方法:self.yourwidget.deleteLater()

self.button.clicked.connect(delete_widget); 

def delete_widget(self): 
    self.widget.deleteLater(); 

self.widget.deleteLater();

使用上述功能使小部件从应用程序中消失