आपको लूप चलने के दौरान ईवेंट को संसाधित करने की अनुमति देने की आवश्यकता है ताकि एप्लिकेशन उत्तरदायी रहे।
और भी महत्वपूर्ण बात यह है कि लंबे समय तक चलने वाले कार्यों के लिए, आपको उपयोगकर्ता को शुरू होने के बाद लूप को रोकने का एक तरीका प्रदान करना होगा।
ऐसा करने का एक आसान तरीका एक टाइमर के साथ लूप शुरू करना है, और फिर लूप चल रहा है, जबकि समय-समय पर qApp.processEvents पर कॉल करें।
import sys, time
from PyQt4 import QtGui, QtCore
class ProgressBar(QtGui.QWidget):
def __init__(self, parent=None, total=20):
super(ProgressBar, self).__init__(parent)
self.progressbar = QtGui.QProgressBar()
self.progressbar.setMinimum(1)
self.progressbar.setMaximum(total)
self.button = QtGui.QPushButton('Start')
self.button.clicked.connect(self.handleButton)
main_layout = QtGui.QGridLayout()
main_layout.addWidget(self.button, 0, 0)
main_layout.addWidget(self.progressbar, 0, 1)
self.setLayout(main_layout)
self.setWindowTitle('Progress')
self._active = False
def handleButton(self):
if not self._active:
self._active = True
self.button.setText('Stop')
if self.progressbar.value() == self.progressbar.maximum():
self.progressbar.reset()
QtCore.QTimer.singleShot(0, self.startLoop)
else:
self._active = False
def closeEvent(self, event):
self._active = False
def startLoop(self):
while True:
time.sleep(0.05)
value = self.progressbar.value() + 1
self.progressbar.setValue(value)
QtGui.qApp.processEvents()
if (not self._active or
value >= self.progressbar.maximum()):
break
self.button.setText('Start')
self._active = False
app = QtGui.QApplication(sys.argv)
bar = ProgressBar(total=101)
bar.show()
sys.exit(app.exec_())
अद्यतन
यह मानते हुए कि आप अजगर की सी कार्यान्वयन (यानी CPython) का उपयोग कर रहे हैं, इस मुद्दे का हल पूरी तरह से निर्भर:
यहाँ एक डेमो स्क्रिप्ट है कि है कार्य (ओं) की प्रकृति पर जो जीयूआई के साथ एक साथ चलाना है। अधिक मौलिक रूप से, यह सीपीथॉन द्वारा Global Interpreter Lock (GIL) होने के द्वारा निर्धारित किया जाता है।
मैं सीपीथन के जीआईएल के किसी भी स्पष्टीकरण का प्रयास नहीं करने जा रहा हूं: इसके बजाय, मैं बस डेव बेज़ले द्वारा इस उत्कृष्ट PyCon video को देखने की सलाह दूंगा, और इसे छोड़ दूंगा।
आम तौर पर, जब एक पृष्ठभूमि कार्य के साथ समवर्ती एक जीयूआई भागने की कोशिश कर, पहले सवाल पूछने के लिए है: कार्य आईओ बाध्य है, या सीपीयू बाध्य?
यदि यह आईओ-बाध्य है (उदाहरण के लिए स्थानीय फाइल सिस्टम, इंटरनेट से डाउनलोड करना आदि), तो समाधान आमतौर पर काफी सरल होता है, क्योंकि सीपीथन हमेशा आई/ओ संचालन के लिए जीआईएल जारी करता है। पृष्ठभूमि कार्य को आसानी से asynchronously किया जा सकता है, या worker thread द्वारा किया जा सकता है, और जीयूआई उत्तरदायी रखने के लिए विशेष जरूरतों को पूरा करने की आवश्यकता नहीं है।
मुख्य कठिनाइयों सीपीयू-बाध्य कार्यों के साथ होती है, जब पूछने के लिए दूसरा प्रश्न होता है: क्या कार्य छोटे चरणों की श्रृंखला में विभाजित हो सकता है?
यदि यह हो सकता है, तो समाधान लंबित घटनाओं के वर्तमान ढेर को संसाधित करने के लिए समय-समय पर जीयूआई थ्रेड को अनुरोध भेजना है। उपरोक्त डेमो स्क्रिप्ट इस तकनीक का एक कच्चा उदाहरण है। अधिक आम तौर पर, कार्य एक अलग कार्यकर्ता थ्रेड में किया जाएगा, जो एक गुई-अपडेट सिग्नल उत्सर्जित करेगा क्योंकि कार्य के प्रत्येक चरण को पूरा कर लिया गया है। (एनबी: यह सुनिश्चित करना महत्वपूर्ण है कि कार्यकर्ता थ्रेड कभी भी किसी भी जीयूआई से संबंधित संचालन का प्रयास नहीं करता)।
लेकिन यदि कार्य छोटे चरणों में विभाजित नहीं किया जा सकता है, तो सामान्य थ्रेडिंग-प्रकार समाधानों में से कोई भी काम नहीं करेगा। जीयूआई तब तक स्थिर हो जाएगा जब तक कार्य पूरा नहीं हो जाता है, भले ही थ्रेड का उपयोग किया जाता है या नहीं। अर्थात multiprocessing मॉड्यूल का इस्तेमाल करते हैं -
इस अंतिम परिदृश्य के लिए, एकमात्र समाधान नहीं बल्कि एक अलग थ्रेड की तुलना में एक अलग प्रक्रिया उपयोग करने के लिए, है। बेशक, यह समाधान केवल प्रभावी होगा यदि लक्ष्य प्रणाली में एकाधिक CPU कोर उपलब्ध हैं। यदि वहां केवल एक सीपीयू कोर खेलने के लिए है, तो मूल रूप से कुछ भी नहीं किया जा सकता है जो मदद के लिए किया जा सकता है (पाइथन के एक अलग कार्यान्वयन पर स्विच करने के अलावा, या एक अलग भाषा के साथ)।
यदि मैं इसे जीयूआई विंडो स्टालों के साथ-साथ "प्रतिक्रिया नहीं दे रहा हूं, बंद करें" त्रुटि के साथ चलाता हूं। हालांकि अगर मैं अपने सभी कार्यों को समाप्त होने तक प्रतीक्षा करता हूं तो सामान्य आवेदन जारी रहता है। – Tuim
@Tuim। मेरी लिपि आपके प्रश्न में कोड के आधार पर सिर्फ एक साधारण डेमो है। यह एक सार्वभौमिक समाधान नहीं है जो सभी स्थितियों में काम करने जा रहा है। आप जो भी करने की कोशिश कर रहे हैं उसके उचित स्पष्टीकरण के साथ आपको अपने प्रश्न को अपडेट करने की आवश्यकता है। आप इन "कार्यों" का क्या उल्लेख करते हैं? क्या वे सीपीयू-बाध्य हैं, या आईओ-बाध्य हैं? क्या वह एप्लिकेशन है जो आपके द्वारा लिखे गए कार्यों को पूरा करता है, और इसलिए संशोधित कर सकता है? इसमें किस भाषा में लिखा गया है? आदि, – ekhumoro
ये कार्य अधिष्ठापन हैं जैसे ज़िप फ़ाइलों को अनपॅक करना, एमएसआई/डीब पैकेजों को इस तरह की चीजों को स्थापित करना। लेकिन यह मामले के लिए बहुत प्रासंगिक नहीं है। आवेदन पायथन में भी लिखा गया है और पूरी तरह से अनुकूलन योग्य है। इसके अलावा मुझे कॉपी-पेस्ट-सक्षम उत्तर की उम्मीद नहीं है! मैं सही दिशा में एक संकेत की उम्मीद कर रहा हूं और जो आपने मेरे लिए सही दिशा प्रतीत नहीं किया है, मैंने कोशिश की है। कोई अपराध नहीं। – Tuim