Ich versuche, meinen Kopf darum zu wickeln, wie man richtig Threads und Signale mit und Python3
verwendet, aber irgendwie gelingt es nicht zu verstehen, wie das alles funktioniert. Ich habe hier einen Beispielcode gefunden und versuche jetzt, es in PyQt5
arbeiten zu lassen.PyQt Signale und Slots: "neuer Stil" emittieren?
Hier die gui-Datei ist ui.py
:
from PyQt5 import QtCore, QtWidgets
class Ui_Win(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(416, 292)
self.centralWidget = QtWidgets.QWidget(MainWindow)
self.centralWidget.setObjectName("centralWidget")
MainWindow.setCentralWidget(self.centralWidget)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_Win()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Und hier ist das Hauptskript test_slotting.py
:
from ui import Ui_Win
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import pyqtSlot
import time
class GenericThread(QtCore.QThread):
def __init__(self, parent=None):
QtCore.QThread.__init__(self, parent)
def __del__(self):
self.quit()
self.wait()
def run(self):
#Do all your heavy processing here
#I'll just wait for 2 seconds
time.sleep(2)
self.emit(QtCore.pyqtSignal('itemSelectionChanged()'))
return
class MainUI(QtWidgets.QMainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self)
self.ui = Ui_Win()
self.ui.setupUi(self)
self.ui.List1 = QtWidgets.QListWidget(self)
self.ui.List2 = QtWidgets.QListWidget(self)
hbox = QtWidgets.QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(self.ui.List1)
hbox.addWidget(self.ui.List2)
self.ui.centralWidget.setLayout(hbox)
self.ui.List1.addItems(['alpha','beta','gamma','delta','epsilon'])
self.ui.List2.addItems(['Item1','Item2'])
self.ui.List1.itemSelectionChanged.connect(self.start_heavy_processing_thread)
@pyqtSlot()
def start_heavy_processing_thread(self):
genericThread = GenericThread(self)
# self.connect(genericThread, QtCore.SIGNAL("itemSelectionChanged()"), self.fill_List2)
genericThread.itemSelectionChanged.connect(self.fill_List2)
genericThread.start()
def fill_List2(self):
self.ui.List2.clear()
list1SelectedItem = str(self.ui.List1.currentItem().text())
self.ui.List2.addItem(list1SelectedItem)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = MainUI()
MainWindow.show()
sys.exit(app.exec_())
Von dem ursprünglichen Code Beispiel hatte ich "alten Stil"
zu ändernself.connect(genericThread, QtCore.SIGNAL("itemSelectionChanged()"), self.fill_List2)
zu "neuen Stil"
self.ui.List1.itemSelectionChanged.connect(self.start_heavy_processing_thread)
Aber jetzt bekomme ich die folgenden AttributeError: 'GenericThread' object has no attribute 'itemSelectionChanged'
. Ich denke, diese Linie von test_slotting.py
ist immer noch „im alten Stil“:
self.emit(QtCore.pyqtSignal('itemSelectionChanged()'))
Aber was wäre die neue Stil Version davon sein? Jede Hilfe würde sehr geschätzt ...
Vielen Dank für Ihre ausführliche Erklärung. Dummer Fehler, indem 'itemSelectionChanged()' auf 'GenericThread' anstelle von' QListWidget' verwendet wird, sry dafür. Ich muss noch einiges über 'QThread' nachlesen, danke für den Tipp. Thx auch für das Codebeispiel, wird auch hv das genauer überprüfen. Ich habe es geschafft, etw zusammenzufügen und mein Beispiel zum Laufen zu bringen. Allerdings gibt es immer noch einige Bits, die ich nicht wirklich verstehe (Kommentare im Code, zögern Sie nicht, wenn Sie möchten :)). Nochmals, Danke für Ihre Hilfe! – dliv
oh und P.S .: Die Abbildung ist wirklich super hilfreich! – dliv
Ich bin froh, dass ich helfen kann. Wie ich in meiner Antwort geschrieben habe - sieh dir das my git-Repository an, in dem ich Threads verwende. Es sollte dir genug geben, um alles besser in den Griff zu bekommen. – rbaleksandar