PyQt

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

विस्तृत उत्तर के लिए धन्यवाद से निकलता है! फ़ॉर्म लेआउट का उपयोग करने का कारण यह था कि मैं चाहता था कि विजेट स्क्रॉल क्षेत्र के शीर्ष पर दिखने लगें और वहां से रिक्त स्थान भरें, मध्य में दिखाई देने के बजाय और नए विगेट्स बनने के बाद खुद को पुन: व्यवस्थित करें। हालांकि मुझे यकीन है कि ऐसा करने के अन्य तरीके हैं, फॉर्मलेआउट मेरे लिए एक आसान समाधान की तरह लग रहा था .. धन्यवाद फिर से! – boundless

+0

@boundless: आह, मैं देखता हूं। उस पर मेरा दृष्टिकोण 'स्क्रॉलआउटआउट' को दूसरे 'क्यूवीबॉक्स लयआउट' में लपेटकर '1'' के एक हिस्से के साथ जोड़ा जाएगा। यह चीजों को शीर्ष पर रखना चाहिए। – Avaris

+0

एक और चीज जिसे मैं फॉर्मलेआउट के लिए पसंद करता हूं, यह चीजों को शीर्ष पर रखते हुए एक दूसरे के बगल में दो विजेट्स को आसान बनाता है .. हालांकि शायद उस बिंदु पर, मुझे केवल ग्रिड लेआउट का उपयोग करना चाहिए। संकेत के लिए फिर से धन्यवाद! – 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_() 

इस तरह इसे हटाए जाने पर याद दिलाना नहीं चाहिए और वास्तव में सामान के लिए बटन का उपयोग किया जा सकता है। मैं डाउनलोड और हिस्सों की निगरानी के लिए दर्जनों द्वारा प्रगति सलाखों के लिए इस पैटर्न का पालन करता हूं और यह थ्रेडिंग और बहु ​​प्रसंस्करण के साथ भी ठीक काम करता है। और न आसान QThreads ...

+3

आपने किस हिस्से को बदल दिया है, और इसका यह प्रभाव क्यों है? –

0

यू का कहना है कि एक विजेट जब भी एक बटन क्लिक किया जाता है, या उर कार्यक्रम के किसी भी घटना के दौरान हटाने के लिए, deleteLater() विधि का उपयोग करना चाहते हैं: self.yourwidget.deleteLater()

self.button.clicked.connect(delete_widget); 

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

self.widget.deleteLater();

उपर्युक्त फ़ंक्शन का उपयोग करके यह विजेट