PyQt编程之模态与非模态对话框(二)

在上一篇里,实现的模态对话框的功能就是修改数据显示的格式,并进行提交后验证。在未应用该对话框之前,用户不能与对话框的父窗口以及父窗口的兄弟窗口就行交互,这样就保证了应用程序相关部分的状态不会在该对话框关闭之前改变。

可是如果我们想并不确定这一次的设置效果如何,需要多次调整设置的时候,模态对话框就显得不那么方便了。 这时候就可以利用非模态对话框,点击“应用”(apply)按钮来预览设置修改后的结果。

一般来说,模态对话框含有“接受”(accept)按钮和“拒绝”(reject)按钮;非模态对话框则含有“应用”(apply)按钮。


同样的目的,这次是非模态对话框。

import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class MainWindow(QWidget):
    def __init__(self,parent=None):
        QWidget.__init__(self,parent)
        button  =   QPushButton("click me",self)
        button.clicked.connect(self.setNumberFormat)
        self.format     =   dict(thousandsseparator=',',decimalmarker='.',decimalplaces=2,rednegatives=True)

    def setNumberFormat(self):
        dialog  =   Intelligent(self.format,self)
        self.connect(dialog,SIGNAL('changed'),self.refreshTable)
        dialog.show()
    def refreshTable(self):
        print 1

class Intelligent(QDialog):
    def __init__(self,format,parent=None):
        super(Intelligent,self).__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)  # ensure the dialog box can be detele while you click the 'close'

        punctuationRe   =   QRegExp(r"[ ,;:.]")

        thousandsLabel  =   QLabel("&Thousands separator")
        self.thousandsEdit  =   QLineEdit(format["thousandsseparator"])
        thousandsLabel.setBuddy(self.thousandsEdit)
        self.thousandsEdit.setMaxLength(1)  #the new function setMaxLength
        self.thousandsEdit.setValidator(
            QRegExpValidator(punctuationRe, self))  #set the check

        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")        # the new function ,set the input,and the X means anything

        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|QDialogButtonBox.Ok)

        self.format =   format

        layout  =   QGridLayout()
        layout.addWidget(thousandsLabel,0,0)
        layout.addWidget(self.thousandsEdit,0,1)
        layout.addWidget(decimalMarkerLabel,1,0)
        layout.addWidget(self.decimalMarkerEdit,1,1)
        layout.addWidget(decimalPlacesLabel,2,0)
        layout.addWidget(self.decimalPlacesSpinBox,2,1)
        layout.addWidget(self.redNegativesCheckBox,3,0,1,2)
        layout.addWidget(buttonBox,4,0,1,2)
        self.setLayout(layout)

        self.connect(buttonBox.button(QDialogButtonBox.Apply),SIGNAL("clicked()"),self.apply)                                            self.connect(buttonBox,SIGNAL("rejected()"),self,SLOT("reject()"))
        self.connect(buttonBox,SIGNAL("accepted()"),self,SLOT("accept()"))
        self.setWindowTitle("Set Number Format (Mode;ess)")

    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 nor 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"))

app =   QApplication(sys.argv)
widget  =   MainWindow()
widget.show()
app.exec_()

框架讲解
这里的框架和上一篇差不多,不必过多讲解。

实现分析
1.这里有一句self.setAttribute(Qt.WA_DeleteOnClose) ,就是让用户点击“close”的时候关闭对话框而不是隐藏对话框。

2.self.decimalMarkerEdit.setInputMask("X")      设置输入掩码,推荐一篇博文,讲解得很详细。http://blog.csdn.net/xgbing/article/details/7776422

3.self.thousandsEdit.setValidator(QRegExpValidator(punctuationRe, self))    利用正则表达式验证。

4.self.format =   format;可以直接对对话框里面的格式字典进行改变而改变主窗口的格式字典。
与上一篇区别分析:
在这里结合预防验证和提交后验证,并利用正则表达式验证器和输入掩码进行预防式验证。效率得到提高。
能够在用户点击“apply‘得到预览效果,并和父窗口进行交互。


你可能感兴趣的:(#,PyQt(停更))