PyQt5 的 signal 与 slot 有所改变,例如,先定义一个 ZeroSignal 类:

class ZeroSignal(QObject):
atzero = pyqtSignal(int)

使用时,一是绑定 slot 如下:

    self.zerosig = ZeroSignal()
self.zerosig.atzero[int].connect(self.countZero)

然后是找个机会发动之:

def checkZero(self):
if self.value() == 0:
self.zerosig.atzero.emit(self.value())

大约如此,完整代码如下:

import os
import sys from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import * class ZeroSignal(QObject):
atzero = pyqtSignal(int) class ZeroSpinBox(QSpinBox):
def __init__(self, parent=None):
super(ZeroSpinBox, self).__init__(parent)
self.zeros = 0
self.valueChanged[int].connect(self.checkZero)
self.zerosig = ZeroSignal()
self.zerosig.atzero[int].connect(self.countZero) def countZero(self, v):
if v == 0:
self.zeros += 1
print(self.zeros) def checkZero(self):
if self.value() == 0:
self.zerosig.atzero.emit(self.value()) class Form(QDialog):
def __init__(self, parent=None):
super(Form, self).__init__(parent) dial = QDial()
dial.setNotchesVisible(True)
spin = ZeroSpinBox()
layout = QHBoxLayout()
layout.addWidget(dial)
layout.addWidget(spin)
self.setLayout(layout)
dial.valueChanged.connect(spin.setValue)
spin.valueChanged.connect(dial.setValue)
spin.valueChanged.connect(self.emitZero)
self.setWindowTitle("Sinal and Solt") self.zerobox = spin
self.zerobox.zerosig.atzero[int].connect(self.annouce) def emitZero(self, v):
if v == 0:
self.zerobox.zerosig.atzero.emit(self.zerobox.zeros) def annouce(self, v):
print("zero count: %d" % v) # print two times because add ZeroSpinBox emit once def run():
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_() if __name__ == '__main__':
run()

关于对话框的代码如下,尤其 NumberLiveDialog 值得推荐:

import sys,math,random,string
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import * class NumberDialog(QDialog):
def __init__(self, format, parent=None):
super(NumberDialog, self).__init__(parent) thousandsLabel = QLabel("&Thousands separator:")
self.thousandsEdit = QLineEdit(format["thousandsseparator"])
thousandsLabel.setBuddy(self.thousandsEdit)
decimalMarkerLabel = QLabel("Decimal $marker:")
self.decimalMarkerEdit = QLineEdit(format["decimalmarker"])
decimalMarkerLabel.setBuddy(self.decimalMarkerEdit)
decimalPlacesLabel = QLabel("&Decimal places:")
self.decimalPlacesSpinBox = QSpinBox()
decimalPlacesLabel.setBuddy(self.decimalPlacesSpinBox)
self.decimalPlacesSpinBox.setRange(0, 6)
self.decimalPlacesSpinBox.setValue(format["decimalplaces"])
self.redNegativesCheckBox = QCheckBox("&Red negative numbers")
self.redNegativesCheckBox.setChecked(format["rednegatives"]) buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.format = format.copy() grid = QGridLayout()
grid.addWidget(thousandsLabel, 0, 0)
grid.addWidget(self.thousandsEdit, 0, 1)
grid.addWidget(decimalMarkerLabel, 1, 0)
grid.addWidget(self.decimalMarkerEdit, 1, 1)
grid.addWidget(decimalPlacesLabel, 2, 0)
grid.addWidget(self.decimalPlacesSpinBox, 2, 1)
grid.addWidget(self.redNegativesCheckBox, 3, 0, 1, 2)
grid.addWidget(buttonBox, 4, 0, 1, 2)
self.setLayout(grid) buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
self.setWindowTitle("Number format") def accept(self):
class ThousandsError(Exception): pass
class DecimalError(Exception): pass
Punctuation = frozenset(" ,;:.") thousands = str(self.thousandsEdit.text())
decimal = str(self.decimalMarkerEdit.text())
try:
if len(decimal) == 0:
raise DecimalError("The decimal marker may not be empty.")
if len(thousands) > 1:
raise ThousandsError("The thousands separator may only be empty or one charactor.")
if len(decimal) > 1:
raise DecimalError("The decimal marker must be one character.")
if thousands == decimal:
raise ThousandsError("The thousands separator and decimal marker must be different.")
if thousands and thousands not in Punctuation:
raise ThousandsError("The thousands separator must be in Punctuation.")
if decimal and decimal not in Punctuation:
raise DecimalError("The decimal marker must be a punctuation symbol.")
except ThousandsError as e:
QMessageBox.warning(self, "Thousands separator error:", str(e))
self.thousandsEdit.selectAll()
self.thousandsEdit.setFocus()
return
except DecimalError as e:
QMessageBox.warning(self, "Decimal marker error:", str(e))
self.decimalMarkerEdit.selectAll()
self.decimalMarkerEdit.setFocus()
return self.format["thousandsseparator"] = thousands
self.format["decimalmarker"] = decimal
self.format["decimalplaces"] = self.decimalPlacesSpinBox.value()
self.format["rednegatives"] = self.redNegativesCheckBox.isChecked() QDialog.accept(self) def numberFormat(self):
return self.format class NumberModelessDialog(QDialog):
changed = pyqtSignal() def __init__(self, format, parent=None):
super(NumberModelessDialog, self).__init__(parent)
self.setAttribute(Qt.WA_DeleteOnClose)
punctuationRe = QRegularExpression(r"[ ,;:.]") thousandsLabel = QLabel("&Thousands separator:")
self.thousandsEdit = QLineEdit(format["thousandsseparator"])
thousandsLabel.setBuddy(self.thousandsEdit)
self.thousandsEdit.setMaxLength(1)
self.thousandsEdit.setValidator(QRegularExpressionValidator(punctuationRe, self)) decimalMarkerLabel = QLabel("Decimal $marker:")
self.decimalMarkerEdit = QLineEdit(format["decimalmarker"])
decimalMarkerLabel.setBuddy(self.decimalMarkerEdit)
self.decimalMarkerEdit.setMaxLength(1)
self.decimalMarkerEdit.setValidator(QRegularExpressionValidator(punctuationRe, self)) decimalPlacesLabel = QLabel("&Decimal places:")
self.decimalPlacesSpinBox = QSpinBox()
decimalPlacesLabel.setBuddy(self.decimalPlacesSpinBox)
self.decimalPlacesSpinBox.setRange(0, 6)
self.decimalPlacesSpinBox.setValue(format["decimalplaces"]) self.redNegativesCheckBox = QCheckBox("&Red negative numbers")
self.redNegativesCheckBox.setChecked(format["rednegatives"]) buttonBox = QDialogButtonBox(QDialogButtonBox.Apply | QDialogButtonBox.Close)
self.format = format grid = QGridLayout()
grid.addWidget(thousandsLabel, 0, 0)
grid.addWidget(self.thousandsEdit, 0, 1)
grid.addWidget(decimalMarkerLabel, 1, 0)
grid.addWidget(self.decimalMarkerEdit, 1, 1)
grid.addWidget(decimalPlacesLabel, 2, 0)
grid.addWidget(self.decimalPlacesSpinBox, 2, 1)
grid.addWidget(self.redNegativesCheckBox, 3, 0, 1, 2)
grid.addWidget(buttonBox, 4, 0, 1, 2)
self.setLayout(grid) buttonBox.button(QDialogButtonBox.Apply).clicked.connect(self.apply)
buttonBox.rejected.connect(self.reject)
self.setWindowTitle("Number format") def apply(self):
thousands = str(self.thousandsEdit.text())
decimal = str(self.decimalMarkerEdit.text())
if thousands == decimal:
QMessageBox.warning(self, "Thousands separator error")
self.thousandsEdit.selectAll()
self.thousandsEdit.setFocus()
return
if len(decimal) == 0:
QMessageBox.warning(self, "Decimal marker cannot is empty.")
self.decimalMarkerEdit.selectAll()
self.decimalMarkerEdit.setFocus()
return self.format["thousandsseparator"] = thousands
self.format["decimalmarker"] = decimal
self.format["decimalplaces"] = self.decimalPlacesSpinBox.value()
self.format["rednegatives"] = self.redNegativesCheckBox.isChecked() self.changed.emit() class NumberLiveDialog(QDialog):
changed = pyqtSignal() def __init__(self, format, callback, parent=None):
super(NumberLiveDialog, self).__init__(parent)
self.format = format
self.callback = callback self.setAttribute(Qt.WA_DeleteOnClose)
punctuationRe = QRegularExpression(r"[ ,;:.]") thousandsLabel = QLabel("&Thousands separator:")
self.thousandsEdit = QLineEdit(format["thousandsseparator"])
thousandsLabel.setBuddy(self.thousandsEdit)
self.thousandsEdit.setMaxLength(1)
self.thousandsEdit.setValidator(QRegularExpressionValidator(punctuationRe, self)) decimalMarkerLabel = QLabel("Decimal $marker:")
self.decimalMarkerEdit = QLineEdit(format["decimalmarker"])
decimalMarkerLabel.setBuddy(self.decimalMarkerEdit)
self.decimalMarkerEdit.setMaxLength(1)
self.decimalMarkerEdit.setValidator(QRegularExpressionValidator(punctuationRe, self)) decimalPlacesLabel = QLabel("&Decimal places:")
self.decimalPlacesSpinBox = QSpinBox()
decimalPlacesLabel.setBuddy(self.decimalPlacesSpinBox)
self.decimalPlacesSpinBox.setRange(0, 6)
self.decimalPlacesSpinBox.setValue(format["decimalplaces"]) self.redNegativesCheckBox = QCheckBox("&Red negative numbers")
self.redNegativesCheckBox.setChecked(format["rednegatives"]) grid = QGridLayout()
grid.addWidget(thousandsLabel, 0, 0)
grid.addWidget(self.thousandsEdit, 0, 1)
grid.addWidget(decimalMarkerLabel, 1, 0)
grid.addWidget(self.decimalMarkerEdit, 1, 1)
grid.addWidget(decimalPlacesLabel, 2, 0)
grid.addWidget(self.decimalPlacesSpinBox, 2, 1)
grid.addWidget(self.redNegativesCheckBox, 3, 0, 1, 2)
self.setLayout(grid) self.thousandsEdit.textEdited.connect(self.checkAndFix)
self.decimalMarkerEdit.textEdited.connect(self.checkAndFix)
self.decimalPlacesSpinBox.valueChanged.connect(self.apply)
self.redNegativesCheckBox.toggled.connect(self.apply) self.setWindowTitle("Number format") def checkAndFix(self):
thousands = self.thousandsEdit.text()
decimal = self.decimalMarkerEdit.text()
if thousands == decimal:
self.thousandsEdit.clear()
self.thousandsEdit.setFocus()
if len(decimal) == 0:
self.decimalMarkerEdit.setText(".")
self.decimalMarkerEdit.selectAll()
self.decimalMarkerEdit.setFocus()
self.apply() def apply(self):
thousands = self.thousandsEdit.text()
decimal = self.decimalMarkerEdit.text() self.format["thousandsseparator"] = thousands
self.format["decimalmarker"] = decimal
self.format["decimalplaces"] = self.decimalPlacesSpinBox.value()
self.format["rednegatives"] = self.redNegativesCheckBox.isChecked() self.callback() class Form(QDialog):
X_MAX = 26
Y_MAX = 60 def __init__(self, parent=None):
super(Form, self).__init__(parent) self.numberDlg = None
self.format = { "thousandsseparator":",", "decimalmarker":".",
"decimalplaces":2, "rednegatives": False }
self.numbers = {}
for x in range(self.X_MAX):
for y in range(self.Y_MAX):
self.numbers[(x,y)] = 10000 * random.random() - 5000 self.table = QTableWidget()
modalButton = QPushButton("Set numbe format...(&Modal)")
modelessButton = QPushButton("Set number format...(M&odeless)")
liveButton = QPushButton("Set number format...(&Live)") buttonLayout = QHBoxLayout()
buttonLayout.addStretch()
buttonLayout.addWidget(modalButton)
buttonLayout.addWidget(modelessButton)
buttonLayout.addWidget(liveButton)
layout = QVBoxLayout()
layout.addWidget(self.table)
layout.addLayout(buttonLayout)
self.setLayout(layout) modalButton.clicked.connect(self.setNumberFormatByModal)
modelessButton.clicked.connect(self.setNumberFormatByModeless)
liveButton.clicked.connect(self.setNumberFormatByLive) self.setWindowTitle("Set Number Format")
self.refreshTable() def refreshTable(self):
self.table.clear()
self.table.setRowCount(self.Y_MAX)
self.table.setColumnCount(self.X_MAX)
self.table.setHorizontalHeaderLabels(list(string.ascii_uppercase)) for x in range(self.X_MAX):
for y in range(self.Y_MAX):
fraction, whole = math.modf(self.numbers[(x,y)])
sign = "-" if whole < 0 else ""
whole = "{0}".format(int(math.floor(abs(whole))))
digits = []
for i, digit in enumerate(reversed(whole)):
if i and i % 3 == 0:
digits.insert(0, self.format["thousandsseparator"])
digits.insert(0, digit)
if self.format["decimalplaces"]:
fraction = "{0:.7f}".format(abs(fraction))
fraction = self.format["decimalmarker"] + fraction[2:self.format["decimalplaces"]+2]
else:
fraction = ""
text = "{0}{1}{2}".format(sign, "".join(digits), fraction)
item = QTableWidgetItem(text)
item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
if sign and self.format["rednegatives"]:
item.setBackground(Qt.red)
self.table.setItem(y, x, item) def setNumberFormatByModal(self):
dlg = NumberDialog(self.format, self)
if dlg.exec_():
self.format = dlg.numberFormat()
self.refreshTable() def setNumberFormatByModeless(self):
dlg = NumberModelessDialog(self.format, self)
dlg.show()
dlg.changed.connect(self.refreshTable) def setNumberFormatByLive(self):
if self.numberDlg is None:
self.numberDlg = NumberLiveDialog(self.format, self.refreshTable, self)
self.numberDlg.show()
self.numberDlg.raise_()
self.numberDlg.activateWindow() if __name__ == "__main__":
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()

numberdlg.py

关于主窗口 (fileload function need add a bool parameter for recentfiles) 的代码:imagechanger

运行效果图如下:

《Python GUI Qt 快速开放指南》部分例子:PyQt5-Code

PyQt5 signal and slot的更多相关文章

  1. 深入了解Qt(三)之元signal和slot

    深入了解Qt主要内容来源于Inside Qt系列,本文做了部分删改,以便于理解.在此向原作者表示感谢! 在Qt 信号和槽函数这篇文章中已经详细地介绍了信号和槽的使用及注意事项.在这里对其使用方面的知识 ...

  2. 【golang-GUI开发】qt之signal和slot(一)

    想了很久,我决定还是先从signal和slot(信号槽)开始讲起. signal和slot大家一定不陌生,先看一段示例(选自文档): class Counter : public QObject { ...

  3. Qt Signal and Slot

    Qt4中的信号槽 Qt4中的信号槽是通过SIGNAL,SLOT两个宏,将参数转换成字符串.Qt编译前,会从源码的头文件中提取由signal和slot声明的信号和槽的函数, 将其组成一张信号和槽对应的字 ...

  4. qt的signal和slot机制

    signal和slot是QT中的一大特点 signal/slot是Qt对象以及其派生类对象之间的一种高效通信接口 用户可以将N多个信号和单个槽相连接, 或者将将N个槽和单个信号连接, 甚至是一个信号和 ...

  5. [C++_QT] Error: Not a signal or slot declaration

    问题: 在Qt工程中添加了一个新的窗口之后 一直报错 如下 单单从错误描述上看 是缺少信号或者槽 但是我确定没有缺少啊 然后第二个错误显示了一个mox_xxxx文件 然后我就去那个目录下去找那个文件 ...

  6. 【golang-GUI开发】qt之signal和slot(二)

    上一篇文章里我们详细介绍了signal的用法. 今天我们将介绍slot的使用.在qt中slot和signal十分相像,这次我们将实现一个能显示16进制数字的SpinBox,它继承自QSpinbox并重 ...

  7. QT 中 关键字讲解(emit,signal,slot)

    Qt中的类库有接近一半是从基类QObject上继承下来,信号与反应槽(signals/slot)机制就是用来在QObject类或其子类间通讯的方法.作为一种通用的处理机制,信号与反应槽非常灵活,可以携 ...

  8. qt信号signal和槽slot机制

    内容: 一.概述 二.信号 三.槽 四.信号与槽的关联 五.元对象工具 六.程序样例 七.应注意的问题 信号与槽作为QT的核心机制在QT编程中有着广泛的应用,本文介绍了信号与槽的一些基本概念.元对象工 ...

  9. signal & slot

    The Qt signals/slots and property system are based on the ability to introspect the objects at runti ...

随机推荐

  1. ZT 获得/修改共享互斥量属性:pthread_mutexattr_t

    bbs.chinaunix.net/thread-965755-1-1.html 5.   获得/修改共享互斥量属性:    #include<pthread.h>    intpthre ...

  2. 今天开始每天一点ffmpeg知识。千里之行 。

    今天开始每天一点ffmpeg知识.千里之行 .

  3. [BZOJ 3992][SDOI2015]序列统计

    3992: [SDOI2015]序列统计 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 2275  Solved: 1090[Submit][Stat ...

  4. HTTP协议图--HTTP 报文实体

    1. HTTP 报文实体概述   HTTP 报文结构 大家请仔细看看上面示例中,各个组成部分对应的内容. 接着,我们来看看报文和实体的概念.如果把 HTTP 报文想象成因特网货运系统中的箱子,那么 H ...

  5. java数组回顾---线性查找最大值最小值---二分查找

    import java.util.Scanner; public class ArrayDemo { public static void main(String []args) { //------ ...

  6. html5和CSS3中新特性

    H5 1.语义化标签 header.footer.aside.nav.section.article 2.表单输入类型 email.url.number.range.Date Pickers.sear ...

  7. 「bzoj 4184: shallot」

    权限题 线段树分治加线性基 首先这个题要求删除线性基肯定是没法处理的 于是我们套上一个线段树分治 线段树分治就是一种能够避免删除的神仙操作 我们发现询问是对一个时间的单点询问,而每一个数存在的时间却是 ...

  8. 解决windows7无法连接CentOS7系统中oracle问题:ORA-12514 TNS 监听程序当前无法识别

    linux开启后终端按下面输入(容易忘记,记录下): [oracle@localhost ~]$ lsnrctl stop                #先关闭监听服务 [oracle@localh ...

  9. Mysql 创建普通用户、数据库、表、插入记录,用户赋权

    C:\phpStudy\MySQL\bin>mysql -uroot -proot -h127.0.0.1 //创建用户 mysql> insert into mysql.user (ho ...

  10. 推荐一个WPF仪表盘开源控件

    前段时间,做服务器端监控系统,为了界面好看,采用WPF.硬件相关监控,比如CPU.内存等,想用仪表盘控件.网上找了很多这种控件,基本上都是第三方商业控件(虽然很漂亮,不过得money...).最后在C ...