先上原来的代码,共是四个文件: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()
========================================================