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学习---Django误删除sql表后,如何创建数据

    误删除sql表后,怎么创建数据? 仅仅适合单表,多表因为涉及约束, python mangage.py makemigrations  --> 生成migrations目录和根数据库对应的sql ...

  2. TCP协议那些事

    tcp三次握手                                     tcp四次挥手   tcp十种状态 tcp的2MSL问题 说明 2MSL即两倍的MSL,TCP的TIME_WAI ...

  3. System.Buffer 以字节数组(Byte[])操作基元类型数据

    1. Buffer.ByteLength:计算基元类型数组累计有多少字节组成. 该方法结果等于"基元类型字节长度 * 数组长度" , , }; , , }; , , }; Cons ...

  4. CRITICAL **: Couldn't acquire global lock, snapshots will not be consistent: Access denied

    报错如下:** (mydumper:56288): CRITICAL **: Couldn't acquire global lock, snapshots will not be consisten ...

  5. WebKit由三个模块组成-Webkit模块介绍

    2.       Webkit 源代码由三大模块组成: 1). WebCore, 2). WebKit, 3). JavaScriptCore. WebCore:排版引擎核心,WebCore包含主要以 ...

  6. [19/04/17-星期三] Java的动态性_反射(Reflection)机制

    一.前言 动态语言:程序运行时,可以改变程序结构或变量类型.典型的代表:Python,ruby,JavaScript 如JavaScript代码: function test(){ var s=&qu ...

  7. StackExchange.Redis学习笔记(二) Redis查询 五种数据类型的应用

    ConnectionMultiplexer ConnectionMultiplexer 是StackExchange.Redis的核心对象,用这个类的实例来进行Redis的一系列操作,对于一个整个应用 ...

  8. 关于CUDA C 项目中“ error C2059: 语法错误:“<” ”问题的解决方法

    该问题的关键在于理解CUDA项目中C\C++文件需要由c++编译器进行编译,而CUDA C的源文件需要由CUDA的编译器nvcc.exe进行编译. 发生该语法错误的原因是cu文件被C++编译器所编译, ...

  9. git用户限制ssh登录服务器

    服务器额外的防范措施: 搭建git服务器后通常会建立一个git账户,其它人共用这个账户来克隆或推送数据到git仓库中,通常也只需要这个功能,但是如果不加限制,那么其它人可以通过这个git账户登录到主机 ...

  10. Centos 7下Nagios的安装及配置

    简介 Nagios 是一款自动化运维工具,可以协助运维人员监控服务器的运行状况,并且拥有报警功能.本文章将介绍其安装方法和详细的配置方法. nagios 监控服务应用指南 本地资源:负载,CPU,磁盘 ...