2012-02-04 28 views
5

Có cách nào nhỏ nhặt hoặc thanh lịch để phân biệt giữa nhiều nguồn tín hiệu cùng loại trong PySide/PyQt?Phân biệt giữa các nguồn tín hiệu trong PySide

Tôi đang học PySide. Tôi đã viết ứng dụng đơn giản, nhân hai số từ hai đối tượng QLineEdit() khác nhau. Kết quả được hiển thị trong QLineEdit thứ ba.

Tín hiệu Multiplier và multiplicand QLineEdit.textChanged() được kết nối với một phương thức (TxtChanged). Trong phương pháp này tôi phải phân biệt giữa các nguồn tín hiệu. Sau một số thử nghiệm tôi đã tìm ra một số cách giải quyết dựa trên văn bản giữ chỗ (4 dòng bên dưới "là có cách khác?" Bình luận trong mã của tôi)

mã:

import sys 
from PySide import QtGui, QtCore 

class myGUI(QtGui.QWidget): 

    def __init__(self, *args, **kwargs): 
     QtGui.QWidget.__init__(self, *args, **kwargs) 

     self.multiplier = 0 
     self.multiplicand = 0 

     self.myGUIInit() 

    def myGUIInit(self): 
     # input forms 
     a1_label = QtGui.QLabel("a1") 
     a1_edit = QtGui.QLineEdit() 
     a1_edit.setPlaceholderText("a1") 

     a2_label = QtGui.QLabel("a2") 
     a2_edit = QtGui.QLineEdit() 
     a2_edit.setPlaceholderText("a2") 

     # output form 
     a1a2_label = QtGui.QLabel("a1*a2") 
     self.a1a2_edit = QtGui.QLineEdit() 
     self.a1a2_edit.setReadOnly(True) 


     # forms events 
     a1_edit.textChanged.connect(self.TxtChanged) 
     a2_edit.textChanged.connect(self.TxtChanged) 

     # grid 
     grid = QtGui.QGridLayout() 
     grid.setSpacing(10) 

     grid.addWidget(a1_label,1,0) 
     grid.addWidget(a1_edit,1,1) 

     grid.addWidget(a2_label,2,0) 
     grid.addWidget(a2_edit,2,1) 

     grid.addWidget(a1a2_label,3,0) 
     grid.addWidget(self.a1a2_edit,3,1) 

     self.setLayout(grid) 
     self.setGeometry(100,100,200,200) 
     self.setWindowTitle("a*b") 
     self.show() 

    def TxtChanged(self,text): 
     sender = self.sender() 
     sender_text = sender.text() 
     if sender_text == '': sender_text = '0' 

     # is there another way? 
     if sender.placeholderText() == 'a1': 
      self.multiplicand = sender_text 
     else: 
      self.multiplier = sender_text 

     product = int(self.multiplier) * int(self.multiplicand) 

     print(self.multiplier,self.multiplicand,product) 

     self.a1a2_edit.setText(str(product)) 


def main(): 
    app = QtGui.QApplication(sys.argv) 
    mainWindow = myGUI() 
    sys.exit(app.exec_()) 

main() 

tốt nhất liên quan, ostrzysz

+0

Cảm ơn mọi người vì câu trả lời. Trân trọng! – ostrzysz

Trả lời

3

Một điều khiến tôi khó hiểu nhất trong mã của bạn là bạn đang sử dụng placeholderText để phân biệt. QObject s có một thuộc tính khác được gọi là objectName phù hợp hơn với nhiệm vụ của bạn. Và, bạn không cần phải sử dụng sender.text() để nhận văn bản của QLineEdit. textChanged đã gửi nó, vì vậy bạn sẽ có nó trong thông số text của mình.

Ngoài ra, sử dụng từ điển thay vì hai biến riêng biệt (multipliermultiplicand) sẽ đơn giản hóa mã của bạn hơn nữa.

Đây là mã thay đổi:

class myGUI(QtGui.QWidget): 

    def __init__(self, *args, **kwargs): 
     QtGui.QWidget.__init__(self, *args, **kwargs) 

     self.data = {"multiplier": 0, 
        "multiplicand": 0} 

     self.myGUIInit() 

    def myGUIInit(self): 
     a1_label = QtGui.QLabel("a1") 
     a1_edit = QtGui.QLineEdit() 
     a1_edit.setObjectName("multiplicand") 

     a2_label = QtGui.QLabel("a2") 
     a2_edit = QtGui.QLineEdit() 
     a2_edit.setObjectName("multiplier") 

     # skipped the rest because same 

    def TxtChanged(self, text): 
     sender = self.sender() 

     # casting to int while assigning seems logical. 
     self.data[sender.objectName()] = int(text) 

     product = self.data["multiplier"] * self.data["multiplicand"] 

     print(self.data["multiplier"], self.data["multiplicand"], product) 

     self.a1a2_edit.setText(str(product)) 
+0

Điểm tốt về 'setObjectName', nhưng cá nhân tôi thích' functools hơn.cách tiếp cận một phần' như trong câu trả lời @jsbueno, bởi vì nó rõ ràng. Và 'QObject.sender()' có nhiều hạn chế, ví dụ: trong môi trường mutlithreaded. – reclosedev

+0

Cảm ơn bạn rất nhiều, đó là chính xác những gì tôi đang tìm kiếm! Trân trọng. – ostrzysz

6

Bạn có thể sử dụng chức năng functools.partial - và do đó kết nối các tín hiệu của bạn thẳng đến phương pháp/chức năng của bạn nhưng thay vào đó là đối tượng python sẽ tự động gọi hàm của bạn với một số dữ liệu bổ sung mà bạn vượt qua:

from functools import partial 
... 
     .... 
     a1_edit.textChanged.connect(partial(self.TxtChanged, a1_edit)) 
     a2_edit.textChanged.connect(partial(self.TxtChanged, a2_edit)) 
     ... 

    def TxtChanged(self,sender, text): 
     # and here you have the "sender" parameter as it was filled in the call to "partial" 
     ... 

partials là một phần của stdlib, và rất có thể đọc được, nhưng người ta luôn có thể sử dụng lambda thay vì một phần cho tác dụng tương tự -

a1_edit.textChanged.connect(lambda text: self.TxtChanged(a1_edit, text)) 

Bằng cách này, đối tượng thu được từ biểu thức lambda sẽ là một tạm thời chức năng sẽ sử dụng các giá trị cho "self" và "a1_edit" từ các biến cục bộ hiện tại (tại thời điểm nút được nhấn), và biến có tên là "text" sẽ được cung cấp bởi lời gọi lại của Pyside.

2

Mặc dù @jsbueno@Avaris đã trả lời câu hỏi trực tiếp của bạn về các nguồn tín hiệu, tôi sẽ không chuyển tiếp vào các nguồn này trong trường hợp cụ thể của bạn. Bạn có thể làm cho các thành viên dụ a1_edita2_edit:

... 
self.a1_edit = QtGui.QLineEdit() 
... 
self.a2_edit = QtGui.QLineEdit() 
... 

Nó sẽ đơn giản hóa TxtChanged chức năng của bạn:

def TxtChanged(self,text): 
    try: 
     multiplier = int(self.a1_edit.text()) 
     multiplicand = int(self.a2_edit.text()) 
    except ValueError: 
     self.a1a2_edit.setText('Enter two numbers') 
     return 
    product = multiplier * multiplicand 
    print(multiplier, multiplicand, product) 
    self.a1a2_edit.setText(str(product)) 

Ngoài ra, thay vì xử lý ValueError ngoại lệ, bạn có thể sử dụng QIntValidator cho các điều khiển đầu vào:

self.int_validator = QtGui.QIntValidator() 
self.a1_edit.setValidator(self.int_validator) 
self.a2_edit.setValidator(self.int_validator) 
Các vấn đề liên quan