2011-12-28 6 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

+0

@ Безграничный: Ах, я вижу. Мой подход к этому будет обернуть 'scrollLayout' в другой' QVBoxLayout' с добавлением строки «1» ниже. Это должно держать вещи наверху. – Avaris

+0

еще одна вещь, которая мне нравится formlayout для, это упрощает иметь два виджета рядом друг с другом, а также держать вещи наверху. Хотя, возможно, в этот момент я должен просто использовать сетку. Еще раз спасибо за подсказку! – boundless

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_() 

Таким образом, он не должен ает утечку при удалении и кнопка на самом деле может быть использована для вещей. Я следую этому шаблону для индикаторов выполнения десятками для мониторинга загрузок и кусков, и он отлично работает даже с поточной обработкой и многопроцессорной обработкой. И не легкие ... объектов QThread

+3

Какую часть вы изменили и почему она имеет этот эффект? –

0

Если и хочу сказать, удалить виджет всякий раз, когда кнопка нажата, или во всяком случае ур программы, используйте метод deleteLater(): self.yourwidget.deleteLater()

self.button.clicked.connect(delete_widget); 

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

self.widget.deleteLater();

Использование вышеуказанной функции делает виджетом исчезновение из Приложения

Смежные вопросы