2011-12-28 38 views
12

bằng PyQt, tôi đang cố gắng tạo giao diện mà tôi có thể thêm hoặc xóa tiện ích động. Tôi muốn xác định một lớp riêng biệt cho tiện ích con sẽ được thêm hoặc xóa. Tôi dường như không thể nhận được tiện ích mà tôi nhanh chóng hiển thị bên trong giao diện chính. Đây là mã tôi đang sử dụng:tự động thêm và xóa tiện ích trong 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_() 

điều là, khi tôi sử dụng mã dưới đây vào trong phương pháp 'addWidget' của tôi, nó chính xác những gì tôi muốn nó phải làm, nhưng phương pháp lớp không dường như hoạt động.

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

Tôi tự hỏi tại sao z = Test() không sinh ra bất kỳ kết quả nào? Bất kỳ ý tưởng? Cảm ơn!

Trả lời

12

Thực ra, nó hoạt động. Vấn đề là, tiện ích Test của bạn có QPushButton mà không có bất kỳ quản lý bố cục nào. Vì vậy, nó không thể tính toán của nó minimumSize với việc xem xét các nút. Khi bạn đặt tiện ích con đó trong bố cục, nó chỉ co lại thành 0 (vì QWidget không có mặc định là minimumSize) và bạn không thấy gì cả.

Bạn có hai lựa chọn, hoặc là bạn quản lý bố cục theo cách thủ công và bước vào thế giới không cần thiết của đau hoặc bạn dựa vào người quản lý bố cục. Nói chung, bạn nên thích cái sau.

tôi sẽ viết lại kịch bản của bạn như thế này (Mặc dù tôi không chắc chắn lý do tại sao bạn sử dụng QFormLayout, tôi để nó như nó là.):

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

Cảm ơn câu trả lời chi tiết! Lý do tôi sử dụng Form Layout là tôi muốn các widget bắt đầu xuất hiện ở phía trên cùng của vùng cuộn và điền vào các vị trí trống từ đó, thay vì xuất hiện ở giữa và sắp xếp lại chúng như các widget mới được tạo ra. Mặc dù tôi chắc chắn có những cách khác để làm điều đó, formlayout có vẻ như một giải pháp dễ dàng cho tôi .. Cảm ơn một lần nữa! – boundless

+0

@boundless: Ah, tôi hiểu rồi. Cách tiếp cận của tôi với điều đó sẽ được gói 'scrollLayout' trong một' QVBoxLayout' khác với một đoạn '1' được thêm vào bên dưới. Điều đó sẽ giữ mọi thứ ở trên cùng. – Avaris

+0

một điều khác mà tôi thích formlayout cho là, nó làm cho nó dễ dàng hơn để có hai vật dụng bên cạnh nhau cũng như giữ mọi thứ ở đầu .. Mặc dù có lẽ vào thời điểm đó, tôi chỉ nên sử dụng bố trí lưới. Cảm ơn một lần nữa vì gợi ý! – boundless

4

Đây là một sự thay đổi nhỏ mà sẽ làm cho tự xóa nút khi đã nhấp:

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

Bằng cách này, bạn không nên nhớ rò rỉ khi xóa và nút thực sự có thể được sử dụng cho nội dung. Tôi làm theo mô hình này cho các thanh tiến trình của hàng chục để tải xuống và theo dõi khối và nó hoạt động tốt ngay cả với luồng và xử lý đa. Và không phải là dễ dàng QThreads ...

+3

Phần nào bạn đã thay đổi và tại sao nó lại có hiệu ứng này? –

0

Nếu u muốn nói, xóa một widget bất cứ khi nào một nút được nhấn vào, hoặc trong bất kỳ sự kiện của chương trình ur, sử dụng phương pháp deleteLater(): self.yourwidget.deleteLater()

self.button.clicked.connect(delete_widget); 

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

self.widget.deleteLater();

Sử dụng chức năng trên làm cho tiện ích đó biến mất khỏi Ứng dụng

Các vấn đề liên quan