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. Python学习---网络编程 1217【all】

    OSI七层模型: 物理层, 数据链路层, 网络层,传输层,会话层,表达层,应用层 应用层:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等 传输层:TCP,UDP 网络层:I ...

  2. Linxu下 expect的安装与使用

    expect学习 1.什么是except        Expect是基于Tcl的一个相对简单的免费脚本文件语言工具,用于实现自动和交互式程序进行通信            is a software ...

  3. yaml 入手

    一.变量 YAML使用冒号加缩进的方式代表层级(属性)关系,使用短横杠(-)代表数组元素. YAML中允许表示三种格式,分别是常量值,对象和数组 #即表示url属性值: url: http://www ...

  4. Apache Spark : RDD

    Resilient Distributed Datasets Resilient Distributed Datasets (RDD) is a fundamental data structure ...

  5. Linux CPU的中断【转载】

    中断其实就是由硬件或软件所发送的一种称为IRQ(中断请求)的信号. 中断允许让设备,如键盘,串口卡,并口等设备表明它们需要CPU. 一旦CPU接收了中断请求,CPU就会暂时停止执行正在运行的程序,并且 ...

  6. Requests中文乱码解决方案

    分析: r = requests.get(“http://www.baidu.com“) **r.text返回的是Unicode型的数据. 使用r.content返回的是bytes型的数据. 也就是说 ...

  7. 把对象缓存到HttpRuntime.Cache里,你能安全地使用它吗?

    每每勤勤恳恳,思来想去,趁还有激情,先把它记录下来... 定义一个Stu的类: public class Stu { public string Name { get; set; } public i ...

  8. P2585 [ZJOI2006]三色二叉树

    题目描述 输入输出格式 输入格式: 输入文件名:TRO.IN 输入文件仅有一行,不超过500000个字符,表示一个二叉树序列. 输出格式: 输出文件名:TRO.OUT 输出文件也只有一行,包含两个数, ...

  9. Kali-linux无线网络嗅探工具Kismet

    如果要进行无线网络渗透测试,则必须先扫描所有有效的无线接入点.刚好在Kali Linux中,提供了一款嗅探无线网络工具Kismet.使用该工具可以测量周围的无线信号,并查看所有可用的无线接入点.本节将 ...

  10. wireMock快速伪造restful服务

    官网地址:http://wiremock.org/ Jar下载:http://repo1.maven.org/maven2/com/github/tomakehurst/wiremock/1.57/w ...