Tôi hiện đang trong quá trình tạo lớp tạo ra pyqtSignal (int) và pyqtSlot (int). Khó khăn nằm trong việc tạo ra một tín hiệu phát ra một giá trị cụ thể.PyQt5 trang trí khe cắm tín hiệu ví dụ
Giả sử tôi muốn tạo ra một cái gì đó tương tự như ví dụ đơn giản sau:
import sys
from PyQt5.QtCore import (Qt, pyqtSignal, pyqtSlot)
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
QVBoxLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def printLabel(self, str):
print(str)
@pyqtSlot(int)
def on_sld_valueChanged(self, value):
self.lcd.display(value)
self.printLabel(value)
def initUI(self):
self.lcd = QLCDNumber(self)
self.sld = QSlider(Qt.Horizontal, self)
vbox = QVBoxLayout()
vbox.addWidget(self.lcd)
vbox.addWidget(self.sld)
self.setLayout(vbox)
self.sld.valueChanged.connect(self.on_sld_valueChanged)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
câu hỏi đầu tiên của tôi cho đoạn code trên là:
- Tại sao sử dụng() trang trí pyqtSlot ở tất cả khi loại bỏ
pyqtSlot(int)
không ảnh hưởng đến mã? - Bạn có thể đưa ra ví dụ về thời điểm cần thiết không?
Vì lý do cụ thể, tôi muốn tạo tín hiệu của riêng mình bằng cách sử dụng nhà máy pyqtSignal() và được cung cấp tài liệu phong nha here. Tuy nhiên, vấn đề duy nhất là, rất simple example không cung cấp một nền tảng vững chắc về cách phát ra các tín hiệu cụ thể.
Đây là những gì tôi đang cố gắng để làm nhưng đã thấy mình mất:
- Tạo một metaclass cho phép thực hiện nhiều loại khác nhau của các lớp con QWidget.
- Có metaclass sản xuất tín hiệu riêng của mình có thể được gọi từ bên ngoài lớp học.
Đây là những gì tôi sẽ cho:
from PyQt5.QtWidgets import QPushButton, QWidget
from PyQt5.QtCore import pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QSlider
def template(Q_Type, name: str, *args):
class MyWidget(Q_Type):
def __init__(self) -> None:
super().__init__(*args)
self._name = name
def setSignal(self,type):
self.signal = pyqtSignal(type)
def callSignal(self):
pass
return MyWidget
Như bạn có thể nhìn thấy. Tôi cung cấp cho các widget một tên bởi vì tôi thấy điều này là hữu ích, và tôi cũng cố gắng để nhanh chóng QWidget từ bên trong lớp để đơn giản hóa mã.
Đây là cách tôi muốn có một lớp học chính để sản xuất các vật dụng từ ví dụ đầu tiên:
import sys
from PyQt5.QtCore import (Qt, pyqtSignal, pyqtSlot)
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
QVBoxLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def printLabel(self, str):
print(str)
@pyqtSlot(int)
def sld_valChanged(self, value):
self.lcd.display(value)
self.printLabel(value)
def initUI(self):
#instantiate the QWidgets through template class
self.lcd = template(QLCDNumber,'lcd_display')
self.sld = template(QSlider, 'slider', Qt.Horizontal)
#create signal
#self.sld.setSignal(int)
vbox = QVBoxLayout()
vbox.addWidget(self.lcd)
vbox.addWidget(self.sld)
self.setLayout(vbox)
#connect signal - this won't send the value of the slider
#self.sld.signal.connect(self.sld_valChanged)
self.sld.valueChanged.connect(self.sld_valChanged)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Chỉ có 2 vấn đề cần được giải quyết ở đây:
- Mẫu metaclass được thiết lập không chính xác và tôi không thể khởi tạo QWidget từ trong metaclass.
Q_Type
cho tôi biết loại của nó làPyQt5.QtCore.pyqtWrapperType
khi cần làPyQt5.QtWidgets.QSlider
. - Mặc dù tôi đang tạo mộtSignal mới thông qua lớp templated, làm thế nào để tôi nhận được
QSlider
để gửi giá trị đã thay đổi mà tôi muốn nó gửi. Tôi tin rằng đây là nơi màemit()
đi vào chơi nhưng không có đủ kiến thức về cách nó hữu ích. Tôi biết tôi có thể thực hiện một số chức năng gọiself.sld.emit(35)
nếu tôi muốn tín hiệu chuyển giá trị 35 cho chức năng khe. Câu hỏi đặt ra không phải là cách mà tôi nên thực hiện chức năng này ở đâu?
Tôi có thể hoàn toàn mất cơ sở và đánh giá cao giải pháp, vui lòng sửa mã của tôi để tôi có thể có tín hiệu phát ra giá trị của thanh trượt.
Tại sao bạn cố gắng viết mã xấu, quá phức tạp và khó bảo trì này? Có vấn đề thực sự nào mà bạn đang cố giải quyết không? Tôi có một linh cảm bạn đang làm cho sai lầm tân binh rất phổ biến của cố gắng để buộc các API để làm việc theo cách bạn (sai) nghĩ rằng họ * nên * làm việc, chứ không phải là cách họ đang thiết kế để làm việc. Đây là một biến thể của [XY Problem] (http://xyproblem.info/). – ekhumoro
Việc sử dụng @pyqtSignal() không được chấp nhận. Chỉ sử dụng @pyqtSlot(). Kiểm tra tài liệu hướng dẫn cách sử dụng nó theo đúng cách. Đừng sáng tạo lại bánh xe. (Nếu bạn hỏi tôi, @pyqtSlot() nên được đặt tên là @pyQtSlot() để phù hợp với lược đồ đặt tên của PyQt.) –