import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Widget(QWidget):def __init__(self):QWidget.__init__(self)button = QPushButton(QIcon("web.png"),"click me",self)button.move(100,100)button.clicked.connect(self.setNumberFormat1)self.format = dict(thousandsseparator=',',decimalmarker='.',decimalplaces=2,rednegatives=True)self.resize(200,300)def setNumberFormat1(self): #the first Pointdialog = NumberFormatDlg(self.format,self)if dialog.exec_():self.format = dialog.numberFormat()self.refreshTable()class NumberFormatDlg(QDialog): #the second pointdef __init__(self,format,parent=None):super(NumberFormatDlg,self).__init__(parent) thousandsLabel = QLabel("&Thousands seperator") 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() # noticegrid = 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.Ok),SIGNAL("clicked()"),self,SLOT("accept()")) self.connect(buttonBox,SIGNAL("rejected()"),self,SLOT("reject()")) self.setWindowTitle("Set Number Format (Modal)")def numberFormat(self):return self.formatdef accept(self): #override 'accept()' methodclass ThousandsError(Exception): #inherit the class Exceptiondef __init__(self,message):Exception.__init__(self)self.message=messageclass DecimalError(Exception):def __init__(self,message):Exception.__init__(self)self.message=messagePunctuation = 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: #"and not in"raise ThousandsError("The thousands separator must be a punctuation sumbol.")except ThousandsError, e:QMessageBox.warning(self,"Thousands Separator", unicode(e.message)) #QMessageBox's warning can create a new 'warning widget'self.thousandsEdit.selectAll()self.thousandsEdit.setFocus()returnexcept DecimalError, e:QMessageBox.warning(self,"D",unicode(e.message))self.decimalMarkerEdit.selectAll()self.decimalMarkerEdit.setFocus()returnself.format['thousandsseparator'] = thousandsself.format['decimalmarker'] = decimalself.format['decimalplaces'] =\self.decimalPlacesSpinBox.value()self.format["rednegatives"] =\self.redNegativesCheckBox.isChecked() #the CheckBox has 'isChecked()' which can get the vaule of the CheckBoxQDialog.accept(self)app = QApplication(sys.argv)
widget = Widget()
widget.show()app.exec_()
好,然后咱就按照套路分析一下。
框架講解
框架就好比一篇文章的行文思路,是寫(xiě)這種代碼所必須的。
第一部分:setNumberFormat1這個(gè)函數(shù)就是來(lái)彈出格式設(shè)置對(duì)話(huà)框,并對(duì)主窗口里面的數(shù)據(jù)格式更新。可以把它看成主窗口和對(duì)話(huà)框之間的橋梁。
第二部分:第二部分就是對(duì)話(huà)框這個(gè)類(lèi)的實(shí)現(xiàn)了。
首先是init函數(shù),設(shè)置控件,排出布局,連接按鈕的信號(hào)和槽,前面的文章已經(jīng)分析過(guò)類(lèi)似的,所以也不需要多講。
然后就是accept函數(shù)了,我們這里對(duì)它進(jìn)行了重載。為什么要進(jìn)行重載呢??進(jìn)行重載一般是因?yàn)樵瓉?lái)的函數(shù)不能實(shí)現(xiàn)我們想要的功能。
我們這里想要的功能是當(dāng)我們點(diǎn)擊“Ok”這個(gè)button的時(shí)候,對(duì)‘對(duì)話(huà)框’的各項(xiàng)的值進(jìn)行驗(yàn)證,如果符合,則返回True給exec_(),否則回到對(duì)話(huà)框。而原來(lái)的accept函數(shù)只是簡(jiǎn)單地給exec_()返回一個(gè)True,除此之外什么都不干。(驗(yàn)證按驗(yàn)證的對(duì)象及其之間的關(guān)系分為窗口部件級(jí)驗(yàn)證和窗體級(jí)驗(yàn)證,按照時(shí)間先后分為預(yù)防式驗(yàn)證和提交后驗(yàn)證,這里明顯是窗口部件級(jí)驗(yàn)證和提交后驗(yàn)證)