使用QT编程的精髓就在于信号槽机制的灵活运用,信号和槽机制可以使互不相关的对象绑定在一起,实现对象之间的通信。
QT通过信号槽来传递和相应消息,与windows下消息机制相比,消息机制是基于回调函数,而Qt中用信号和槽来代替函数指针,使程序更安全简洁。
信号和槽之间的绑定可以是一对一的,一对多,多对一。即一个信号与一个槽连接,一个信号与多个槽相连,多个信号与一个槽相连,信号和信号直接相连。所有从QObject或其子类(例如QWidget类)派生的类都能够包含信号和槽。通过QObject的connection()函数来实现信号和槽的连接:
connect ( sender , SIGNAL ( signal ), receiver , SLOT ( slot ));
或者信号和信号的连接:
connect ( sender , SIGNAL ( signal ), receiver , SIGNAL ( signal ));
信号与槽之间的连接也可以被移除,使用disconnect函数:
disconnect ( sender , SIGNAL ( signal ), receiver , SLOT ( slot ));
使用信号与槽需要注意的事项:
- 信号与槽机制与普通函数的调用一样,如果使用不当,在程序执行时也有可能产生死循环。所以在定义槽函数时一定要注意避免间接形成无限循环,即在槽中再次发射所接收到的同样信号。
- 如果一个信号与多个槽相连,当这个信号被发射时,与之相连的槽被激活的顺序是随机的。
- 宏定义不能用在signal 和slot的参数中。
- 信号和槽的参数个数与类型必须一致。
更详细的讲解可以参考:
http://www.cnblogs.com/MuyouSome/p/3515941.html
介绍完信号和槽机制,再来说说它是怎么用到不同窗体之间的值传递的。
对于子对话框传值给主窗体:
- 可以把子对话框中控件的信号和主窗体的槽绑定在一起,或者是控件的信号与自定义的信号连接在一起,然后该信号与主窗体的槽函数连一起,这样子对话框的控件变化就会引起主窗口槽函数的响应,但是这种方法受限于子对话框的控件自身的传参类型。
- 也可以在子对话框中自定义信号,然后在主窗体中把这个信号绑定到槽函数,子对话框发射信号,主窗体的槽函数就会做出相应的处理。自定义信号可传递的参数类型很多,如int,str,dict,list,'QString'等。
例子如下:
首先是子对话框的代码DateDialog.py:
# -*- coding: utf-8 -*-"""Created on Wed Jul 15 16:18:59 2015@author: Administrator"""from PyQt4 . QtCore import *from PyQt4 . QtGui import *class DateDialog ( QDialog ):Signal_OneParameter = pyqtSignal ( str )def __init__ ( self , parent = None ):super ( DateDialog , self ). __init__ ( parent )layout = QVBoxLayout ( self )# nice widget for editing the dateself . datetime = QDateTimeEdit ( self )self . datetime . setCalendarPopup ( True )self . datetime . setDateTime ( QDateTime . currentDateTime ())self . lineedit = QLineEdit ( self )self . btn = QPushButton ( 'emit signal' )layout . addWidget ( self . lineedit )layout . addWidget ( self . datetime )layout . addWidget ( self . btn )# OK and Cancel buttonsbuttons = QDialogButtonBox (QDialogButtonBox . Ok | QDialogButtonBox . Cancel ,Qt . Horizontal , self )buttons . accepted . connect ( self . accept )buttons . rejected . connect ( self . reject )layout . addWidget ( buttons )self . connect ( self . datetime , SIGNAL ( 'dateTimeChanged(QDateTime)' ), self , SLOT ( 'showDate(QDateTime)' ))self . connect ( self . datetime , SIGNAL ( 'dateTimeChanged(QDateTime)' ), self , SIGNAL ( 'sendDate(QDateTime)' ))self . connect ( self . btn , SIGNAL ( 'clicked()' ), self , SLOT ( 'myfunc()' ))@pyqtSlot ()def myfunc ( self ):self . Signal_OneParameter . emit (( self . datetime . dateTime ()). toString ())self . lineedit . setText ( QString (( self . datetime . dateTime ()). toString ()))@pyqtSlot ( QDateTime )def showDate ( self , datetime ):self . lineedit . setText ( datetime . toString ())self . update ()#print '12345'# get current date and time from the dialogdef dateTime ( self ):return self . datetime . dateTime ()# static method to create the dialog and return (date, time, accepted)@staticmethoddef getDateTime ( parent = None ):dialog = DateDialog ( parent )result = dialog . exec_ ()date = dialog . dateTime ()return ( date . date (), date . time (), result == QDialog . Accepted )
主窗体的代码如下testSignal:
# -*- coding: utf-8 -*-"""Created on Thu Jul 16 09:02:41 2015@author: Administrator"""from PyQt4 . QtGui import *from PyQt4 . QtCore import *from DateDialog import *import sysclass MainWindow ( QDialog ):def __init__ ( self , parent = None ):QWidget . __init__ ( self )self . resize ( 300 , 200 )open_btn = QPushButton ( 'OPEN' )self . le_btn = QLineEdit ( self )self . le1_btn = QLineEdit ( self )self . le2_btn = QLineEdit ( self )self . le3_btn = QLineEdit ( self )self . connect ( open_btn , SIGNAL ( 'clicked()' ), self . openDialog )grid = QGridLayout ()grid . addWidget ( self . le_btn )grid . addWidget ( self . le1_btn )grid . addWidget ( self . le2_btn )grid . addWidget ( self . le3_btn )grid . addWidget ( open_btn )self . setLayout ( grid )self . setWindowTitle ( 'main windows' )def openDialog ( self ):dialog = DateDialog ( self )self . connect ( dialog , SIGNAL ( 'sendDate(QDateTime)' ), self , SLOT ( 'receiveDate(QDateTime)' ))self . connect ( dialog , SIGNAL ( 'sendDate(QDateTime)' ), self , SLOT ( 'copyDate(QDateTime)' ))self . connect ( dialog . datetime , SIGNAL ( 'dateTimeChanged(QDateTime)' ), self , SLOT ( 'getDate(QDateTime)' ))#self.connect(dialog,SIGNAL('Signal_OneParameter_Overload(str)'),self,SLOT('getStrDate(str)'))dialog . Signal_OneParameter . connect ( self . getStrDate )dialog . show ()@pyqtSlot ( str )def getStrDate ( self , dateStr ):self . le3_btn . setText ( dateStr )@pyqtSlot ( QDateTime )def receiveDate ( self , date ):self . le_btn . setText ( date . toString ())@pyqtSlot ( QDateTime )def getDate ( self , date ):self . le2_btn . setText ( date . toString ())@pyqtSlot ( QDateTime )def copyDate ( self , date ):self . le1_btn . setText ( date . toString ())app = QApplication ( sys . argv )app . setFont ( QFont ( "Helvetica" , 16 ))main = MainWindow ()main . show ()sys . exit ( app . exec_ ())
对于自定义的信号,使用方法是:
- 自定义的信号在__init__()函数之前定义。Signal_OneParameter = pyqtSignal(str)
- 在子对话框的槽函数发射信号,或在事件中发射信号。self.Signal_OneParameter.emit((self.datetime.dateTime()).toString())
- 在主窗体中连接信号和槽。dialog.Signal_OneParameter.connect(self.getStrDate)
- 然后实现槽函数。
参考: