wps2000 |
2016-10-20 16:49 |
解决第5章例子“numbers”对PyQt5+python3兼容性的问题
先上原来的代码,共是四个文件:numbers.pyw、numberformatdlg1.py、numberformatdlg2.py、numberformatdlg3.py
numbers.pyw
================================================================
import math import random import string import sys from PyQt4.QtCore import * from PyQt4.QtGui import * import numberformatdlg1 import numberformatdlg2 import numberformatdlg3
class Form(QDialog):
X_MAX = 26 Y_MAX = 60
def __init__(self, parent=None): super(Form, self).__init__(parent)
self.numberFormatDlg = None self.format = dict(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() formatButton1 = QPushButton("Set Number Format... " "(&Modal)") formatButton2 = QPushButton("Set Number Format... " "(Modele&ss)") formatButton3 = QPushButton("Set Number Format... " "(`&Live')")
buttonLayout = QHBoxLayout() buttonLayout.addStretch() buttonLayout.addWidget(formatButton1) buttonLayout.addWidget(formatButton2) buttonLayout.addWidget(formatButton3) layout = QVBoxLayout() layout.addWidget(self.table) layout.addLayout(buttonLayout) self.setLayout(layout)
self.connect(formatButton1, SIGNAL("clicked()"), self.setNumberFormat1) self.connect(formatButton2, SIGNAL("clicked()"), self.setNumberFormat2) self.connect(formatButton3, SIGNAL("clicked()"), self.setNumberFormat3) self.setWindowTitle("Numbers") self.refreshTable()
def refreshTable(self): self.table.clear() self.table.setColumnCount(self.X_MAX) self.table.setRowCount(self.Y_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 = "%d" % 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" % abs(fraction) fraction = (self.format["decimalmarker"] + fraction[2:self.format["decimalplaces"] + 2]) else: fraction = "" text = "%s%s%s" % (sign, "".join(digits), fraction) item = QTableWidgetItem(text) item.setTextAlignment(Qt.AlignRight|Qt.AlignVCenter) if sign and self.format["rednegatives"]: item.setBackgroundColor(Qt.red) self.table.setItem(y, x, item)
def setNumberFormat1(self): dialog = numberformatdlg1.NumberFormatDlg(self.format, self) if dialog.exec_(): self.format = dialog.numberFormat() self.refreshTable()
def setNumberFormat2(self): dialog = numberformatdlg2.NumberFormatDlg(self.format, self) self.connect(dialog, SIGNAL("changed"), self.refreshTable) dialog.show()
def setNumberFormat3(self): if self.numberFormatDlg is None: self.numberFormatDlg = numberformatdlg3.NumberFormatDlg( self.format, self.refreshTable, self) self.numberFormatDlg.show() self.numberFormatDlg.raise_() self.numberFormatDlg.activateWindow()
app = QApplication(sys.argv) form = Form() form.show() app.exec_()
===================================================================
numberformatdlg1.py
====================================================================
from PyQt4.QtCore import * from PyQt4.QtGui import *
class NumberFormatDlg(QDialog):
def __init__(self, format, parent=None): super(NumberFormatDlg, 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)
self.connect(buttonBox, SIGNAL("accepted()"), self, SLOT("accept()")) self.connect(buttonBox, SIGNAL("rejected()"), self, SLOT("reject()")) self.setWindowTitle("Set Number Format (Modal)")
def accept(self): class ThousandsError(Exception): pass class DecimalError(Exception): pass Punctuation = frozenset(" ,;:.")
thousands = unicode(self.thousandsEdit.text()) decimal = unicode(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 character.") if len(decimal) > 1: raise DecimalError, ("The decimal marker must be " "one character.") if thousands == decimal: raise ThousandsError, ("The thousands separator and " "the decimal marker must be different.") if thousands and thousands not in Punctuation: raise ThousandsError, ("The thousands separator must " "be a punctuation symbol.") if decimal not in Punctuation: raise DecimalError, ("The decimal marker must be a " "punctuation symbol.") except ThousandsError, e: QMessageBox.warning(self, "Thousands Separator Error", unicode(e)) self.thousandsEdit.selectAll() self.thousandsEdit.setFocus() return except DecimalError, e: QMessageBox.warning(self, "Decimal Marker Error", unicode(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
==============================================================
numberformatdlg2.py
======================================================================
from PyQt4.QtCore import * from PyQt4.QtGui import *
class NumberFormatDlg(QDialog):
def __init__(self, format, parent=None): super(NumberFormatDlg, self).__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose)
punctuationRe = QRegExp(r"[ ,;:.]")
thousandsLabel = QLabel("&Thousands separator") self.thousandsEdit = QLineEdit(format["thousandsseparator"]) thousandsLabel.setBuddy(self.thousandsEdit) self.thousandsEdit.setMaxLength(1) self.thousandsEdit.setValidator( QRegExpValidator(punctuationRe, self))
decimalMarkerLabel = QLabel("Decimal &marker") self.decimalMarkerEdit = QLineEdit(format["decimalmarker"]) decimalMarkerLabel.setBuddy(self.decimalMarkerEdit) self.decimalMarkerEdit.setMaxLength(1) self.decimalMarkerEdit.setValidator( QRegExpValidator(punctuationRe, self)) self.decimalMarkerEdit.setInputMask("X")
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)
self.connect(buttonBox.button(QDialogButtonBox.Apply), SIGNAL("clicked()"), self.apply) self.connect(buttonBox, SIGNAL("rejected()"), self, SLOT("reject()")) self.setWindowTitle("Set Number Format (Modeless)")
def apply(self): thousands = unicode(self.thousandsEdit.text()) decimal = unicode(self.decimalMarkerEdit.text()) if thousands == decimal: QMessageBox.warning(self, "Format Error", "The thousands separator and the decimal marker " "must be different.") self.thousandsEdit.selectAll() self.thousandsEdit.setFocus() return if len(decimal) == 0: QMessageBox.warning(self, "Format Error", "The decimal marker may not be 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.emit(SIGNAL("changed"))
============================================================ numberformatdlg3.py
================================================================
from PyQt4.QtCore import * from PyQt4.QtGui import *
class NumberFormatDlg(QDialog):
def __init__(self, format, callback, parent=None): super(NumberFormatDlg, self).__init__(parent)
punctuationRe = QRegExp(r"[ ,;:.]") thousandsLabel = QLabel("&Thousands separator") self.thousandsEdit = QLineEdit(format["thousandsseparator"]) thousandsLabel.setBuddy(self.thousandsEdit) self.thousandsEdit.setMaxLength(1) self.thousandsEdit.setValidator( QRegExpValidator(punctuationRe, self)) decimalMarkerLabel = QLabel("Decimal &marker") self.decimalMarkerEdit = QLineEdit(format["decimalmarker"]) decimalMarkerLabel.setBuddy(self.decimalMarkerEdit) self.decimalMarkerEdit.setMaxLength(1) self.decimalMarkerEdit.setValidator( QRegExpValidator(punctuationRe, self)) self.decimalMarkerEdit.setInputMask("X") 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"])
self.format = format self.callback = callback
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.connect(self.thousandsEdit, SIGNAL("textEdited(QString)"), self.checkAndFix) self.connect(self.decimalMarkerEdit, SIGNAL("textEdited(QString)"), self.checkAndFix) self.connect(self.decimalPlacesSpinBox, SIGNAL("valueChanged(int)"), self.apply) self.connect(self.redNegativesCheckBox, SIGNAL("toggled(bool)"), self.apply) self.setWindowTitle("Set Number Format (`Live')")
def checkAndFix(self): thousands = unicode(self.thousandsEdit.text()) decimal = unicode(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): self.format["thousandsseparator"] = \ unicode(self.thousandsEdit.text()) self.format["decimalmarker"] = \ unicode(self.decimalMarkerEdit.text()) self.format["decimalplaces"] = \ self.decimalPlacesSpinBox.value() self.format["rednegatives"] = \ self.redNegativesCheckBox.isChecked() self.callback()
========================================================
|
|