一個星期以來,我一直在為這個問題絞盡腦汁。每當我發出信號時,它似乎都停留在呼叫它的類的本地。
我的目標是在一個類中發出一個信號并在多個類中接收它。基本上我試圖向另一個類發出信號以傳遞資料。
我的問題可能源于使用 QStackedWidget,我看到的關于信號/插槽的每個 stackoverflow 執行緒或 youtube 視頻都沒有使用 QStackedWidget。
下面是我的代碼,它展示了即使我發出相同的信號,只有當信號在插槽所在的類中時才會激活插槽。
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5 import QtWidgets
from PyQt5.QtCore import pyqtSignal, QObject
import sys
# Class that holds the signal
class communication(QObject):
GotFilePath = pyqtSignal(str)
# Class for first page
class DataLoadedPage(QWidget):
# Initilize
def __init__(self):
super(DataLoadedPage, self).__init__()
# import signal class
self.communication = communication()
self.initUI()
def initUI(self):
# Label
self.label = QtWidgets.QLabel(self)
self.label.setText("First page")
self.label.move(50,50)
# Button
self.b1 = QtWidgets.QPushButton(self)
self.b1.setText('Next screen')
# Connect to signal from signal class and print which page its on
self.communication.GotFilePath.connect(self.somethingrandom)
# Connect button to emitter and change page
self.b1.clicked.connect(self.mouseclick)
def somethingrandom(self, emitted):
print('First') # <------------- Difference
def mouseclick(self):
self.communication.GotFilePath.emit("Emitted")
widget.setCurrentIndex(widget.currentIndex() 1) # Go to second page
# Class for second page
class DataLoadedPage2(QWidget):
# Initilize
def __init__(self):
super(DataLoadedPage2, self).__init__()
# import signal class
self.communication = communication()
self.initUI()
def initUI(self):
# Label
self.label = QtWidgets.QLabel(self)
self.label.setText("Second page")
self.label.move(50,50)
# Button
self.b1 = QtWidgets.QPushButton(self)
self.b1.setText('Previous screen')
# Connect to signal from signal class and print which page its on
self.communication.GotFilePath.connect(self.somethingrandom)
# Connect button to emitter and change page
self.b1.clicked.connect(self.mouseclick)
def somethingrandom(self, Emitted):
print('second') # <--------------- Difference
def mouseclick(self):
self.communication.GotFilePath.emit("Emitted")
widget.setCurrentIndex(widget.currentIndex()-1) # Go to first page
# define widget
app = QApplication(sys.argv)
widget = QtWidgets.QStackedWidget()
# Define pages
frontpage = DataLoadedPage()
secondpage = DataLoadedPage2()
# Add pages to widget
widget.addWidget(frontpage)
widget.addWidget(secondpage)
# Launch application
widget.show()
sys.exit(app.exec_())
隨意嘗試代碼,它確實有效
uj5u.com熱心網友回復:
雖然信號是作為類屬性創建的,但它們實際上系結到 QObject 的實體。
在您的代碼中,您正在創建的兩個不同實體communication,并且由于您將該實體信號連接到您在其中創建它的類的實體,因此您只會得到該信號。
如果您想要一個“廣播”信號,那么您應該為該信號創建一個類的單個實體,并在將使用它的任何發送者或接收者實體中使用它:
import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QLabel, QPushButton,
QStackedWidget, QVBoxLayout)
from PyQt5.QtCore import QObject, pyqtSignal
class Communication(QObject):
gotFilePath = pyqtSignal(str)
class DataLoadedPage(QWidget):
def __init__(self, communication):
super().__init__()
self.communication = communication
self.communication.gotFilePath.connect(self.somethingrandom)
self.initUI()
def initUI(self):
self.label = QLabel('First page')
self.b1 = QPushButton('Next screen')
layout = QVBoxLayout(self)
layout.addWidget(self.label)
layout.addWidget(self.b1)
self.b1.clicked.connect(self.mouseclick)
def somethingrandom(self, emitted):
print('First')
def mouseclick(self):
self.communication.gotFilePath.emit('Emitted')
widget.setCurrentIndex(widget.currentIndex() 1)
class DataLoadedPage2(QWidget):
def __init__(self, communication):
super().__init__()
self.communication = communication
self.communication.gotFilePath.connect(self.somethingrandom)
self.initUI()
def initUI(self):
self.label = QLabel('Second page')
self.b1 = QPushButton('Previous screen')
layout = QVBoxLayout(self)
layout.addWidget(self.label)
layout.addWidget(self.b1)
self.b1.clicked.connect(self.mouseclick)
def somethingrandom(self, Emitted):
print('Second')
def mouseclick(self):
self.communication.gotFilePath.emit('Emitted')
widget.setCurrentIndex(widget.currentIndex() - 1)
app = QApplication(sys.argv)
widget = QStackedWidget()
communication = Communication()
frontpage = DataLoadedPage(communication)
secondpage = DataLoadedPage2(communication)
widget.addWidget(frontpage)
widget.addWidget(secondpage)
widget.show()
sys.exit(app.exec_())
通過上面的代碼,在任何類之外創建通信物件,并在每個頁面中用作引數__init__,這樣就可以創建一個實體屬性供其參考,并最終連接到每個實體方法。任何時候發出信號,都會呼叫每個連接(“訂閱”)的函式。
請注意,這種行為很少需要,您實際上可能需要使用信號在實體之間進行通信。
為此,實際上不需要單獨的信號類,因為您可以添加到每個頁面類(因為 QWidget 繼承自 QObject)。
在這種情況下,由于連接是雙向的,因此必須在創建兩個實體后完成。您要么在每個類中創建一個實際連接信號的函式,要么在外部執行此操作。
class DataLoadedPage(QWidget):
gotFilePath = pyqtSignal(str)
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.label = QLabel('First page')
self.b1 = QPushButton('Next screen')
layout = QVBoxLayout(self)
layout.addWidget(self.label)
layout.addWidget(self.b1)
self.b1.clicked.connect(self.mouseclick)
def somethingrandom(self, emitted):
print('First')
def mouseclick(self):
self.gotFilePath.emit('Emitted')
widget.setCurrentIndex(widget.currentIndex() 1)
class DataLoadedPage2(QWidget):
gotFilePath = pyqtSignal(str)
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.label = QLabel('Second page')
self.b1 = QPushButton('Previous screen')
layout = QVBoxLayout(self)
layout.addWidget(self.label)
layout.addWidget(self.b1)
self.b1.clicked.connect(self.mouseclick)
def somethingrandom(self, Emitted):
print('Second')
def mouseclick(self):
self.gotFilePath.emit('Emitted')
widget.setCurrentIndex(widget.currentIndex() - 1)
app = QApplication(sys.argv)
widget = QStackedWidget()
frontpage = DataLoadedPage()
secondpage = DataLoadedPage2()
frontpage.gotFilePath.connect(secondpage.somethingrandom)
secondpage.gotFilePath.connect(frontpage.somethingrandom)
widget.addWidget(frontpage)
widget.addWidget(secondpage)
widget.show()
sys.exit(app.exec_())
使用上面的代碼,單擊第一頁的按鈕時將顯示“第二”,反之亦然。
一些進一步的說明: 1. 我冒昧地修復了一些命名、樣式和語法,以更好地遵循Python 代碼的官方樣式指南,這對代碼的可讀性很重要,并且還統一了匯入樣式(通常,您應該匯入單個類或包含它們的子模塊,而不是兩者);2. 你應該總是使用布局管理器,如上圖所示;3. 你可能正在關注一個 youtube 教程(“Code first with Hala”),該教程提供了很多糟糕的建議和不良做法,我強烈建議你忽略它。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/488664.html
標籤:Python python-3.x qt pyqt pyqt5
