配色: 字号:
Pyqt5系列(二)
2016-09-24 | 阅:  转:  |  分享 
  
Pyqt5系列(二)

五基本界面组件之inputDialog

QInputDialog类提供了一种简单方面的对话框来获得用户的单个输入信息,可以是一个字符串,一个Int类型数据,一个double类型数据或是一个下拉列表框的条目。

对应的Dialog其中包括一个提示标签,一个输入控件(若是调用字符串输入框,则为一个QLineEdit,若是调用Int类型或double类型,则为一个QSpinBox,若是调用列表条目输入框,则为一个QComboBox),还包括一个确定输入(Ok)按钮和一个取消输入(Cancel)按钮。

QInputDialog:



classQInputDialog(QDialog)

|QInputDialog(QWidgetparent=None,Qt.WindowFlagsflags=0)

QInputDialog同样继承自QDialog,提供简单输入的对话框,



代码示例:



示例代码如下:



#--coding:utf-8--

''''''

inputDialog

''''''

__author__=''TonyZhu''



fromPyQt5.QtWidgetsimportQApplication,QWidget,QLineEdit,QInputDialog,QGridLayout,QLabel,QPushButton,QFrame



classInputDialog(QWidget):

def__init__(self):

super(InputDialog,self).__init__()

self.initUi()



definitUi(self):

self.setWindowTitle("项目信息")

self.setGeometry(400,400,300,260)



label1=QLabel("项目名称:")

label2=QLabel("项目类型:")

label3=QLabel("项目人员:")

label4=QLabel("项目成本:")

label5=QLabel("项目介绍:")



self.nameLable=QLabel("PyQt5")

self.nameLable.setFrameStyle(QFrame.Panel|QFrame.Sunken)

self.styleLable=QLabel("外包")

self.styleLable.setFrameStyle(QFrame.Panel|QFrame.Sunken)

self.numberLable=QLabel("40")

self.numberLable.setFrameStyle(QFrame.Panel|QFrame.Sunken)

self.costLable=QLabel("400.98")

self.costLable.setFrameStyle(QFrame.Panel|QFrame.Sunken)

self.introductionLable=QLabel("服务外包第三方公司")

self.introductionLable.setFrameStyle(QFrame.Panel|QFrame.Sunken)



nameButton=QPushButton("...")

nameButton.clicked.connect(self.selectName)

styleButton=QPushButton("...")

styleButton.clicked.connect(self.selectStyle)

numberButton=QPushButton("...")

numberButton.clicked.connect(self.selectNumber)

costButton=QPushButton("...")

costButton.clicked.connect(self.selectCost)

introductionButton=QPushButton("...")

introductionButton.clicked.connect(self.selectIntroduction)



mainLayout=QGridLayout()

mainLayout.addWidget(label1,0,0)

mainLayout.addWidget(self.nameLable,0,1)

mainLayout.addWidget(nameButton,0,2)

mainLayout.addWidget(label2,1,0)

mainLayout.addWidget(self.styleLable,1,1)

mainLayout.addWidget(styleButton,1,2)

mainLayout.addWidget(label3,2,0)

mainLayout.addWidget(self.numberLable,2,1)

mainLayout.addWidget(numberButton,2,2)

mainLayout.addWidget(label4,3,0)

mainLayout.addWidget(self.costLable,3,1)

mainLayout.addWidget(costButton,3,2)

mainLayout.addWidget(label5,4,0)

mainLayout.addWidget(self.introductionLable,4,1)

mainLayout.addWidget(introductionButton,4,2)



self.setLayout(mainLayout)







defselectName(self):

name,ok=QInputDialog.getText(self,"项目名称","输入项目名称:",

QLineEdit.Normal,self.nameLable.text())

ifokand(len(name)!=0):

self.nameLable.setText(name)

defselectStyle(self):

list=["外包","自研"]



style,ok=QInputDialog.getItem(self,"项目性质","请选择项目性质:",list)

ifok:

self.styleLable.setText(style)



defselectNumber(self):

number,ok=QInputDialog.getInt(self,"项目成员","请输入项目成员人数:",int(self.numberLable.text()),20,100,2)

ifok:

self.numberLable.setText(str(number))



defselectCost(self):

cost,ok=QInputDialog.getDouble(self,"项目成本","请输入项目成员人数:",float(self.costLable.text()),100.00,500.00,2)

ifok:

self.costLable.setText(str(cost))



defselectIntroduction(self):

introduction,ok=QInputDialog.getMultiLineText(self,"项目介绍","介绍:","服务外包第三方公司\nPythonproject")

ifok:

self.introductionLable.setText(introduction)







if__name__=="__main__":

importsys

app=QApplication(sys.argv)

myshow=InputDialog()

myshow.show()

sys.exit(app.exec_())



示例说明:

通过点击不同的按钮,来选择不同类型的输入对话框,从而选择所需的数据。

代码分析:

L18~22:



label1=QLabel("项目名称:")

label2=QLabel("项目类型:")

label3=QLabel("项目人员:")

label4=QLabel("项目成本:")

label5=QLabel("项目介绍:")

定义了数据项名称的标签。



L24~33:



self.nameLable=QLabel("PyQt5")

self.nameLable.setFrameStyle(QFrame.Panel|QFrame.Sunken)

self.styleLable=QLabel("外包")

self.styleLable.setFrameStyle(QFrame.Panel|QFrame.Sunken)

self.numberLable=QLabel("40")

self.numberLable.setFrameStyle(QFrame.Panel|QFrame.Sunken)

self.costLable=QLabel("400.98")

self.costLable.setFrameStyle(QFrame.Panel|QFrame.Sunken)

self.introductionLable=QLabel("服务外包第三方公司")

self.introductionLable.setFrameStyle(QFrame.Panel|QFrame.Sunken)

定义了项目数据项中的数据内容,数据内容显示在对应的标签中。

setFrameStyle()设定标签的样式,有如下的样式:

QFrame.Box

QFrame.Panel

QFrame.WinPanel

QFrame.HLine

QFrame.VLine

QFrame.StyledPanel

QFrame.Sunken

QFrame.Raised



L35~L44:



nameButton=QPushButton("...")

nameButton.clicked.connect(self.selectName)

styleButton=QPushButton("...")

styleButton.clicked.connect(self.selectStyle)

numberButton=QPushButton("...")

numberButton.clicked.connect(self.selectNumber)

costButton=QPushButton("...")

costButton.clicked.connect(self.selectCost)

introductionButton=QPushButton("...")

introductionButton.clicked.connect(self.selectIntroduction)

实例化QPushButton对象,并将对应的clicked信号和自定义的槽函数绑定起来。



L46~61:

实例化网格布局,并将对应的控件添加到网格布局中。



功能分析:



1:获取项目名称:



defselectName(self):

name,ok=QInputDialog.getText(self,"项目名称","输入项目名称:",QLineEdit.Normal,self.nameLable.text())

ifokand(len(name)!=0):

self.nameLable.setText(name)

QInputDialog中很多方法均为静态方法,因此不需要实例化直接可以调用。调用QInputDialog的getText()函数弹出标准字符串输入对话框,getText()函数原型如下:



|getText(...)

|QInputDialog.getText(QWidget,str,str,QLineEdit.EchoModeecho=QLineEdit.Normal,strtext=QString(),Qt.WindowFlagsflags=0,Qt.InputMethodHintsinputMethodHints=Qt.ImhNone)->(str,bool)

第1个参数parent,用于指定父组件;



第2个参数str,是标准输入对话框的标题名;



第3个参数str,标准输入对话框的标签提示;



第4个参数echo,mode指定标准输入对话框中QLineEdit控件的输入模式;



第5个参数str,标准输入对话框中QLineEdit控件的默认值;



第6个参数flags,指明标准输入对话框的窗体标识;



第7个参数inputMethodHints,通过选择不同的inputMethodHints值来实现不同的键盘布局;



单击nameButton之后的效果:



若用户单击了“OK”按钮,则把新输入的名称更新至显示标签。



2:获取项目属性:



defselectStyle(self):

list=["外包","自研"]

style,ok=QInputDialog.getItem(self,"项目性质","请选择项目性质:",list)

ifok:

self.styleLable.setText(style)

调用QInputDialog的getItem()函数弹出标准条目选择对话框,getItem()函数原型如下:



|getItem(...)

|QInputDialog.getItem(QWidget,str,str,list-of-str,intcurrent=0,booleditable=True,Qt.WindowFlagsflags=0,Qt.InputMethodHintsinputMethodHints=Qt.ImhNone)->(str,bool)

第1个参数parent,用于指定父组件;



第2个参数str,是标准条目选择对话框的标题名;



第3个参数str,标准条目选择对话框的标签提示;



第4个参数list-of-str,标准条目选择对话框中对应条目的list;



第5个参数editable,标准条目选择对话框条目是否可编辑标识,默认为不可编辑;



第6个参数flags,指明标准输入对话框的窗体标识;



第7个参数inputMethodHints,通过选择不同的inputMethodHints值来实现不同的键盘布局.;



单击styleButton之后的效果:



若用户单击了“OK”按钮,则把新选择的类型更新至显示标签。



3:获取项目成员:



defselectNumber(self):

number,ok=QInputDialog.getInt(self,"项目成员","请输入项目成员人数:",int(self.numberLable.text()),20,100,2)

ifok:

self.numberLable.setText(str(number))

调用QInputDialog的getInt()函数弹出标准int类型输入对话框,getInt()函数原型如下:



|getInt(...)

|QInputDialog.getInt(QWidget,str,str,intvalue=0,intmin=-2147483647,intmax=2147483647,intstep=1,Qt.WindowFlagsflags=0)->(int,bool)



第1个参数parent,用于指定父组件;



第2个参数str,是标准int类型输入对话框的标题名;



第3个参数str,标准int类型输入对话框的标签提示;



第4个参数value,标准int类型输入对话框中的默认值;



第5个参数min,标准int类型输入对话框中的最小值;



第6个参数max,标准int类型输入对话框中的最大值;



第7个参数step,标准int类型输入对话框中的步长,即QSpinBox中上下选择是数据变化的步长;



第8个参数inputMethodHints,通过选择不同的inputMethodHints值来实现不同的键盘布局;



单击numberButton之后的效果:





若用户单击了“OK”按钮,则把新选择的成员数据更新至显示标签。



4:获取项目成本:



defselectCost(self):

cost,ok=QInputDialog.getDouble(self,"项目成本","请输入项目成员人数:",float(self.costLable.text()),100.00,500.00,2)

ifok:

self.costLable.setText(str(cost))

调用QInputDialog的getDouble()函数弹出标准float类型输入对话框,getDouble()函数原型如下:



|getDouble(...)

|QInputDialog.getDouble(QWidget,str,str,floatvalue=0,floatmin=-2147483647,floatmax=2147483647,intdecimals=1,Qt.WindowFlagsflags=0)->(float,bool)



第1个参数parent,用于指定父组件;



第2个参数str,输入对话框的标题名;



第3个参数str,输入对话框的标签提示;



第4个参数value,标准float类型输入对话框中的默认值;



第5个参数min,标准float类型输入对话框中的最小值;



第6个参数max,标准float类型输入对话框中的最大值;



第7个参数decimals,小数点后面保留的位数;



第8个参数inputMethodHints,通过选择不同的inputMethodHints值来实现不同的键盘布局;



单击costButton之后的效果:



若用户单击了“OK”按钮,则把新选择的成本数据更新至显示标签



5:获取项目介绍:



defselectIntroduction(self):

introduction,ok=QInputDialog.getMultiLineText(self,"项目介绍","介绍:","服务外包第三方公司\nPythonproject")

ifok:

self.introductionLable.setText(introduction)

调用QInputDialog的getMultiLineText()函数弹出标准多行文本类型输入对话框,getMultiLineText()函数原型如下:



|getMultiLineText(...)

|QInputDialog.getMultiLineText(QWidget,str,str,strtext='''',Qt.WindowFlagsflags=0,Qt.InputMethodHintsinputMethodHints=Qt.ImhNone)->(str,bool)



第1个参数parent,用于指定父组件;



第2个参数str,输入对话框的标题名;



第3个参数str,输入对话框的标签提示;



第4个参数text,输入对话框中LineEdit的默认值;



第5个参数flags,指明标准输入对话框的窗体标识;



第6个参数inputMethodHints,通过选择不同的inputMethodHints值来实现不同的键盘布局;



单击introductionButton之后的效果:



若用户单击了“OK”按钮,则把新修改的项目介绍信息更新至显示标签



六基本界面组件之MessageBox

消息框针对某个场景以文本的形式向用户进行提示,为了获取用户的响应消息框可以显示图标和标准按钮。在实际的界面交互中,经常会看到各种类型的消息框,显示关于消息框,显示严重错误消息框,显示警告消息框等等。由于这些对话框在各个程序中都是一样的,所以QT中就统一提供了一个QMessageBox的类,这样在所有程序中都可以直接使用。

QMessageBox提供两套接口来实现,一种是staticfunctions(静态方法调用),另外一种theproperty-baseAPI(基于属性的API)。直接调用静态方法是一种比较简单的途径,但是没有基于属性API的方式灵活。在QT的官网上推荐使用theproperty-baseAPI。



Staticfunctions方式:



QMessageBox用于显示消息提示。一般会使用到其提供的几个static函数(C++层的函数原型,其参数类型和python中的一样):



通过一个示例来进行说明各个方法的使用:



#--coding:utf-8--

''''''

MessageBox

''''''

__author__=''TonyZhu''



fromPyQt5.QtWidgetsimportQApplication,QWidget,QLineEdit,QMessageBox,QGridLayout,QLabel,QPushButton,QFrame



classMessageBox(QWidget):

def__init__(self):

super(MessageBox,self).__init__()

self.initUi()



definitUi(self):

self.setWindowTitle("MessageBox")

self.setGeometry(400,400,300,290)





self.questionLabel=QLabel("Question:")

self.questionLabel.setFrameStyle(QFrame.Panel|QFrame.Sunken)

self.infoLabel=QLabel("Information:")

self.infoLabel.setFrameStyle(QFrame.Panel|QFrame.Sunken)

self.warningLabel=QLabel("Warning:")

self.warningLabel.setFrameStyle(QFrame.Panel|QFrame.Sunken)

self.criticalLabel=QLabel("Critical:")

self.criticalLabel.setFrameStyle(QFrame.Panel|QFrame.Sunken)

self.aboutLabel=QLabel("About:")

self.aboutLabel.setFrameStyle(QFrame.Panel|QFrame.Sunken)

self.aboutQtLabel=QLabel("AboutQT:")

self.aboutQtLabel.setFrameStyle(QFrame.Panel|QFrame.Sunken)

self.resultLabel=QLabel("Result:")

self.resultLabel.setFrameStyle(QFrame.Panel|QFrame.Sunken)



questButton=QPushButton("...")

questButton.clicked.connect(self.selectQuestion)

infoButton=QPushButton("...")

infoButton.clicked.connect(self.selectInfo)

warningButton=QPushButton("...")

warningButton.clicked.connect(self.selectWarning)

criticalButton=QPushButton("...")

criticalButton.clicked.connect(self.selectCritical)

aboutButton=QPushButton("...")

aboutButton.clicked.connect(self.selectAbout)

aboutQtButton=QPushButton("...")

aboutQtButton.clicked.connect(self.selectAboutQt)



mainLayout=QGridLayout()

mainLayout.addWidget(self.questionLabel,0,0)

mainLayout.addWidget(questButton,0,1)

mainLayout.addWidget(self.infoLabel,1,0)

mainLayout.addWidget(infoButton,1,1)

mainLayout.addWidget(self.warningLabel,2,0)

mainLayout.addWidget(warningButton,2,1)

mainLayout.addWidget(self.criticalLabel,3,0)

mainLayout.addWidget(criticalButton,3,1)

mainLayout.addWidget(self.aboutLabel,4,0)

mainLayout.addWidget(aboutButton,4,1)

mainLayout.addWidget(self.aboutQtLabel,5,0)

mainLayout.addWidget(aboutQtButton,5,1)

mainLayout.addWidget(self.resultLabel,6,1)



self.setLayout(mainLayout)







defselectQuestion(self):

button=QMessageBox.question(self,"Question","检测到程序有更新,是否安装最新版本?",

QMessageBox.Ok|QMessageBox.Cancel,QMessageBox.Ok)



ifbutton==QMessageBox.Ok:

self.resultLabel.setText("

Question:OK

")

elifbutton==QMessageBox.Cancel:

self.resultLabel.setText("

Question:Cancel

")

else:

return



defselectInfo(self):

QMessageBox.information(self,"Information","程序当前版本为V3.11")

self.resultLabel.setText("Information")

4

defselectWarning(self):

button=QMessageBox.warning(self,"Warning","恢复出厂设置将导致用户数据丢失,是否继续操作?",

QMessageBox.Reset|QMessageBox.Help|QMessageBox.Cancel,QMessageBox.Reset)



ifbutton==QMessageBox.Reset:

self.resultLabel.setText("

Warning:Reset

")

elifbutton==QMessageBox.Help:

self.resultLabel.setText("

Warning:Help

")

elifbutton==QMessageBox.Cancel:

self.resultLabel.setText("

Warning:Cancel

")

else:

return



defselectCritical(self):

QMessageBox.critical(self,"Critical","服务器宕机!")

self.resultLabel.setText("

Critical

")



defselectAbout(self):

QMessageBox.about(self,"About","Copyright2015Tonyzhu.\nAllRightreserved.")

self.resultLabel.setText("About")



defselectAboutQt(self):

QMessageBox.aboutQt(self,"AboutQt")

self.resultLabel.setText("AboutQt")



if__name__=="__main__":

importsys

app=QApplication(sys.argv)

myshow=MessageBox()

myshow.show()

sys.exit(app.exec_())



示例说明:

通过点击不同的按钮,来选择不同类型的消息框,并将处理的结果显示在resultLabel中。

代码分析:

L19~32:



self.questionLabel=QLabel("Question:")self.questionLabel.setFrameStyle(QFrame.Panel|QFrame.Sunken)



.......



self.resultLabel=QLabel("Result:")self.resultLabel.setFrameStyle(QFrame.Panel|QFrame.Sunken)



定义不同消息类型的标签,其中resultLabel显示不同messagebox执行的结果。



L34~45:



questButton=QPushButton("...")

questButton.clicked.connect(self.selectQuestion)



.....



aboutQtButton=QPushButton("...")

aboutQtButton.clicked.connect(self.selectAboutQt)



定义针对不同类型操作的按钮,并且将对应按钮的clicked信号和自定义的槽函数绑定在一起。



L47~60:



mainLayout=QGridLayout()

mainLayout.addWidget(self.questionLabel,0,0)

mainLayout.addWidget(questButton,0,1)



.......



mainLayout.addWidget(self.aboutQtLabel,5,0)

mainLayout.addWidget(aboutQtButton,5,1)

mainLayout.addWidget(self.resultLabel,6,1)

实例化网格布局,并将定义的标签和按钮添加到布局的对应位置。



1、question类型

question类型的执行代码段如下:



defselectQuestion(self):

button=QMessageBox.question(self,"Question","检测到程序有更新,是否安装最新版本?",

QMessageBox.Ok|QMessageBox.Cancel,QMessageBox.Ok)



ifbutton==QMessageBox.Ok:

self.resultLabel.setText("

Question:OK

")

elifbutton==QMessageBox.Cancel:

self.resultLabel.setText("

Question:Cancel

")

else:

return



调用static方法question()生产question类型的消息框(Ok和cancel按钮,默认选择Ok按钮),该执行之后返回用户选择的按钮。通过判断返回的按钮类型,在resultLabel中显示对应的内容。



question(QWidgetparent,constQString&title,constQString&text,StandardButtonsbuttons=StandardButtons(Yes|No),StandardButtondefaultButton=NoButton)

第1个参数parent,用于指定父组件;



第2个参数title,是消息框中的标题;



第3个参数text,消息框中显示的内容。



第4个参数buttons,消息框中显示的button,它的取值是StandardButtons,每个选项可以使用|运算组合起来。如QMessageBox.Ok|QMessageBox.Cancel,



第5个参数button,消息框中默认选中的button。



这个函数有一个返回值,用于确定用户点击的是哪一个按钮。我们可以直接获取其返回值。如果返回值是Ok,也就是说用户点击了Ok按钮,



QLabel支持HTML形式的文本显示,在resultLabel中是通过HTML的语法形式进行显示的。具体可以参考一下HTML语法。



执行的结果:



2、information类型

information类型的执行代码段如下:



defselectInfo(self):

QMessageBox.information(self,"Information","程序当前版本为V3.11")

self.resultLabel.setText("Information")

调用static方法information()生产information类型的消息框,该类型默认有一个Ok按钮。



information(QWidgetparent,constQString&title,constQString&text,StandardButtonsbuttons=Ok,StandardButtondefaultButton=NoButton)

第1,2,3参数,同question类型的说明。



第4个参数buttons,默认参数,默认为Ok按钮。



执行的结果:



3、warning类型

warning类型的执行代码段如下:



defselectWarning(self):

button=QMessageBox.warning(self,"Warning","恢复出厂设置将导致用户数据丢失,是否继续操作?",

QMessageBox.Reset|QMessageBox.Help|QMessageBox.Cancel,QMessageBox.Reset)



ifbutton==QMessageBox.Reset:

self.resultLabel.setText("

Warning:Reset

")

elifbutton==QMessageBox.Help:

self.resultLabel.setText("

Warning:Help

")

elifbutton==QMessageBox.Cancel:

self.resultLabel.setText("

Warning:Cancel

")

else:

return

调用static方法warning()生产warning类型的消息框(Reset、Help和Cancel按钮,默认选择Reset按钮),该执行之后返回用户选择的按钮。通过判断返回的按钮类型,在resultLabel中显示对应的内容。



warning(QWidgetparent,constQString&title,constQString&text,StandardButtonsbuttons=Ok,StandardButtondefaultButton=NoButton)



4、critical类型

critical类型的执行代码段如下:



defselectCritical(self):

QMessageBox.critical(self,"Critical","服务器宕机!")

self.resultLabel.setText("

Critical

")

调用static方法critical()生产critical类型的消息框。



critical(QWidgetparent,constQString&title,constQString&text,StandardButtonsbuttons=Ok,StandardButtondefaultButton=NoButton)

参数说明同information类型。



5、about类型

about类型的执行代码段如下:



defselectAbout(self):

QMessageBox.about(self,"About","Copyright2015Tonyzhu.\nAllRightreserved.")

self.resultLabel.setText("About")

调用static方法about()生产about类型的消息框。



about(QWidgetparent,constQString&title,constQString&text)

第1个参数parent,用于指定父组件;



第2个参数title,是消息框中的标题;



第3个参数text,消息框中显示的内容。



执行的结果:



6、aboutQt类型

aboutQt类型的执行代码段如下:



defselectAboutQt(self):

QMessageBox.aboutQt(self,"AboutQt")

self.resultLabel.setText("AboutQt")

调用static方法aboutQt()生产aboutQt类型的消息框。



aboutQt(QWidgetparent,constQString&title=QString())

第1个参数parent,用于指定父组件;



第2个参数title,是消息框中的标题;



其中提示内容来自QT的about中的信息。



执行的结果:



Theproperty-baseAPI方式:



通过上述的例子可以看出直接调用QMessageBox的static方法可以很方便的生成各种类型的消息框,但是这种方式是一种既定的显示风格。

QMessageBox类的static函数优点是方便使用,缺点也很明显:非常不灵活。我们只能使用简单的几种形式。为了能够定制QMessageBox细节,我们必须使用QMessageBox的属性设置API。

实例说明:



#--coding:utf-8--

''''''

MessageBox

''''''

__author__=''TonyZhu''



fromPyQt5.QtWidgetsimportQApplication,QWidget,QLineEdit,QMessageBox,QHBoxLayout,QLabel,QPushButton,QFrame



classMessageBox(QWidget):

def__init__(self):

super(MessageBox,self).__init__()

self.initUi()



definitUi(self):

self.setWindowTitle("MessageBox")

self.setGeometry(400,400,300,290)



mainLayout=QHBoxLayout()

self.displayLabel=QLabel("")

self.displayLabel.setFrameStyle(QFrame.Panel|QFrame.Sunken)

mainLayout.addWidget(self.displayLabel)

self.setLayout(mainLayout)



msgBox=QMessageBox()

msgBox.setIcon(QMessageBox.Information)

msgBox.setWindowTitle("Theproperty-baseAPI")

msgBox.setText("ThePythonfilehasbeenmodified.");

msgBox.setInformativeText("Doyouwanttosaveyourchanges?");

msgBox.setDetailedText("Pythonispowerful...andfast;\nplayswellwithothers;\n\

runseverywhere;\nisfriendly&easytolearn;\nisOpen.")

msgBox.setStandardButtons(QMessageBox.Save|QMessageBox.Discard|QMessageBox.Cancel);

msgBox.setDefaultButton(QMessageBox.Save);



ret=msgBox.exec()

ifret==QMessageBox.Save:

self.displayLabel.setText("Save")

elifret==QMessageBox.Discard:

self.displayLabel.setText("Discard")

elifret==QMessageBox.Cancel:

self.displayLabel.setText("Cancel")

else:

pass





if__name__=="__main__":

importsys

app=QApplication(sys.argv)

myshow=MessageBox()

myshow.show()

sys.exit(app.exec_())

执行的结果:



示例说明:

程序启动的时候直接显示自定义的messagebox,并且在resultLabel中显示选择的结果。

代码分析:

L26:

msgBox.setWindowTitle(“Theproperty-baseAPI”)

通过setWindowTitle()设定消息框的标题。



L27:

msgBox.setText(“ThePythonfilehasbeenmodified.”);

通过setText()设定消息框的提示信息。



L28:

msgBox.setInformativeText(“Doyouwanttosaveyourchanges?”)

setInformativeText(),在对话框中显示的简单说明文字



L29:

msgBox.setDetailedText(“Pythonispowerful…andfast;\nplayswellwithothers;\n\

runseverywhere;\nisfriendly&easytolearn;\nisOpen.”)



setDetailedText(),设定消息框中的详细文本信息。当设定详细文本的时候,对话框自动增加“ShowDetails”按钮。



通过上述的例子,可以发现通过theproperty-baseAPI的方式,可以更灵活的定义messagebox。



QMessageBox常用属性:







七信号与槽机制

信号和槽机制是QT的核心机制,要精通QT编程就必须对信号和槽有所了解。信号和槽是一种高级接口,应用于对象之间的通信,它是QT的核心特性,也是QT区别于其它工具包的重要地方。

在linux、windows等GUI工具包中,GUI组件都会注册回调函数用于处理组件所触发的动作,通常是注册对应的函数的函数指针。在之前关于Button的文章中提到了信号与槽的机制的使用,通过该机制可以很好的将组件的信号(如button的clocked、toggled、pressed等)和处理该信号的槽关联起来。通过信号与槽机制,能够让我们很简洁和快速的来完成相关的功能。

信号和槽是用来在对象间传递数据的方法:当一个特定事件发生的时候,signal会被emit出来,slot调用是用来响应相应的signal的。Qt中对象已经包含了许多预定义的signal(基本组件都有各自特有的预定义的信号),根据使用的场景我们可以添加新的signal。Qt的对象中已经包含了许多预定义的槽函数,但我们也根据使用的场景添加新的槽函数。



信号:



当对象的状态发生改变的时候,信号就由该对象发射(emit)出去。当一个信号被发射(emit)时候,与其关联的槽函数被立刻执行。其中该对象只负责发送信号,发射该信号的对象并不知道是那个对象在接收这个信号。这样保证了对象与对象之间的低耦合。

如果存在信号和多个槽函数相关联的时候,当信号被发射时,这些槽的执行顺序将会是随机的、不确定的。



槽:



用于接受信号,而且槽只是普通的对象成员函数。当和槽连接的信号被发射时,槽会被调用。一个槽并不知道是否有任何信号与自己相连接。



信号和槽的绑定:



通过调用QObject对象的connect函数来将某个对象的信号与另外一个对象的槽函数相关联,这样当发射者发射信号时,接收者的槽函数将被调用。该函数的定义如下::



connect(slot[,type=PyQt5.QtCore.Qt.AutoConnection[,no_receiver_check=False]])

Parameters:

slot–theslottoconnectto,eitheraPythoncallableoranotherboundsignal.

type–thetypeoftheconnectiontomake.

no_receiver_check–suppressthecheckthattheunderlyingC++receiverinstancestillexistsanddeliverthesignalanyway.



当信号与槽没有必要继续保持关联时,我们可以使用disconnect函数来断开连接。其定义如下:



disconnect([slot])

Parameters:slot–theoptionalslottodisconnectfrom,eitheraPythoncallableoranotherboundsignal.Ifitisomittedthenallslotsconnectedtothesignalaredisconnected.



信号和槽的特点:



1、一个信号可以连接到多个槽;

当信号发出后,槽函数都会被调用,但是调用的顺序是随机的,不确定的。



self.slider.valueChanged.connect(self.pBar.setValue)self.slider.valueChanged.connect(self.lcdNumber.display)



QSlider数据的变化同时绑定在setValue()和display()两个槽上。



2、多个信号可以连接到同一个槽;

其中任何一个信号发出,槽函数都会被执行。



self.buttonOn.clicked.connect(self.showMessage)

self.buttonOff.clicked.connect(self.showMessage)



showMessage()同时绑定在两个button的clicked信号上。



3、信号的参数可以是任何的Python类型;

如list,dict等python独有的类型。自定义信号的时候举例说明。



4、信号和槽的连接可以被移除;

比如断开某个特定信号的关联。



self.buttonOn.clicked.connect(self.showMessage)

5、信号可以和另外一个信号进行关联;

第一个信号发出后,第二个信号也同时发送。比如关闭系统的信号发出之后,同时会发出保存数据的信号。



代码示例:



关于信号和槽的式样代码如下:



#--coding:utf-8--

''''''

Signal&Slot

''''''

__author__=''TonyZhu''



importsys

fromPyQt5.QtCoreimportQt

fromPyQt5.QtWidgetsimport(QWidget,QLCDNumber,QSlider,QGridLayout,QLabel,QHBoxLayout,QGroupBox,

QVBoxLayout,QApplication,QProgressBar,QPushButton,QMessageBox)





classSignalSlot(QWidget):



def__init__(self):

super(SignalSlot,self).__init__()

self.initUI()





definitUI(self):



self.controlsGroup=QGroupBox("运行样本")

self.lcdNumber=QLCDNumber(self)

self.slider=QSlider(Qt.Horizontal,self)

self.pBar=QProgressBar(self)

vbox=QVBoxLayout()

vbox.addWidget(self.pBar)

vbox.addWidget(self.lcdNumber)

vbox.addWidget(self.slider)

self.controlsGroup.setLayout(vbox)



controlsLayout=QGridLayout()

self.label1=QLabel("保存状态:")

self.saveLabel=QLabel()

self.label2=QLabel("运行状态:")

self.runLabel=QLabel()

self.buttonSave=QPushButton("保存")

self.buttonRun=QPushButton("运行")

self.buttonStop=QPushButton("停止")

self.buttonDisconnect=QPushButton("解除关联")

self.buttonConnect=QPushButton("绑定关联")



controlsLayout.addWidget(self.label1,0,0)

controlsLayout.addWidget(self.saveLabel,0,1)

controlsLayout.addWidget(self.label2,1,0)

controlsLayout.addWidget(self.runLabel,1,1)

controlsLayout.addWidget(self.buttonSave,2,0)

controlsLayout.addWidget(self.buttonRun,2,1)

controlsLayout.addWidget(self.buttonStop,2,2)

controlsLayout.addWidget(self.buttonDisconnect,3,0)

controlsLayout.addWidget(self.buttonConnect,3,1)



layout=QHBoxLayout()

layout.addWidget(self.controlsGroup)

layout.addLayout(controlsLayout)

self.setLayout(layout)



self.buttonRun.clicked.connect(self.buttonSave.clicked)

self.slider.valueChanged.connect(self.pBar.setValue)

self.slider.valueChanged.connect(self.lcdNumber.display)

self.buttonSave.clicked.connect(self.showMessage)

self.buttonRun.clicked.connect(self.showMessage)

self.buttonDisconnect.clicked.connect(self.unbindConnection)

self.buttonConnect.clicked.connect(self.bindConnection)

self.buttonStop.clicked.connect(self.stop)



self.setGeometry(300,500,500,180)

self.setWindowTitle(''信号和槽'')



defshowMessage(self):

ifself.sender().text()=="保存":

self.saveLabel.setText("Saved")

elifself.sender().text()=="运行":

self.saveLabel.setText("Saved")

self.runLabel.setText("Running")



defunbindConnection(self):

self.slider.valueChanged.disconnect()

defbindConnection(self):

self.slider.valueChanged.connect(self.pBar.setValue)

self.slider.valueChanged.connect(self.lcdNumber.display)

defstop(self):

self.saveLabel.setText("")

self.runLabel.setText("")



if__name__==''__main__'':



app=QApplication(sys.argv)

ex=SignalSlot()

ex.show()

sys.exit(app.exec_())







示例说明:

程序样本运行的界面逻辑,先设定运行的程序样本数量,然后先保存后运行的逻辑状态。通过slider的滑动来改变progressBar和LCD的显示数据;“保存”按钮保存运行的样本;“运行”按钮运行程序样本;“解除关联”解除slider.valueChanged信号的绑定,此时slider的滑动,不会改变progressBar和LCD的显示

示例说明:

L22~30:



self.controlsGroup=QGroupBox("运行样本")

self.lcdNumber=QLCDNumber(self)

self.slider=QSlider(Qt.Horizontal,self)

self.pBar=QProgressBar(self)

vbox=QVBoxLayout()

vbox.addWidget(self.pBar)

vbox.addWidget(self.lcdNumber)

vbox.addWidget(self.slider)

self.controlsGroup.setLayout(vbox)

实例化一个QGroupBox,在其中添加QSlider,QProgressBar,QLCDNumber控件。



L32~41:



controlsLayout=QGridLayout()

self.label1=QLabel("保存状态:")



.....



self.buttonDisconnect=QPushButton("解除关联")

self.buttonConnect=QPushButton("绑定关联")

实例化,界面中右半部分的控件。



L58~65:



self.buttonRun.clicked.connect(self.buttonSave.clicked)

self.slider.valueChanged.connect(self.pBar.setValue)

self.slider.valueChanged.connect(self.lcdNumber.display)

self.buttonSave.clicked.connect(self.showMessage)

self.buttonRun.clicked.connect(self.showMessage)

self.buttonDisconnect.clicked.connect(self.unbindConnection)

self.buttonConnect.clicked.connect(self.bindConnection)

self.buttonStop.clicked.connect(self.stop



signal和slot进行绑定。

1、一个信号绑定多个槽:

self.slider.valueChanged.connect(self.pBar.setValue)self.slider.valueChanged.connect(self.lcdNumber.display)

slider控件的valueChanged信号,同时与QProgressBar的setValue(),QLCDNumber的display()槽函数绑定,当valueChanged信号触发的时候,这两个槽函数均会被调用。



2、多个信号绑定到一个槽:

self.buttonSave.clicked.connect(self.showMessage)

self.buttonRun.clicked.connect(self.showMessage)



buttonSave和buttonRun这两个对象的clicked信号,同时绑定到showMessage()这个槽函数。无论哪一个信号被触发,showMessage()这个槽函数均会被调用。



3、信号和槽的连接可以被移除:

self.buttonDisconnect.clicked.connect(self.unbindConnection)



当buttonDisconnect信号触发之后,与其关联的槽函数unbindConnection()中就会执行disconnect()方法,如下:



defunbindConnection(self):

self.slider.valueChanged.disconnect()



其中执行disconnect()的时候可以指定解除与某个特定的slot槽的关联,比如self.slider.valueChanged.disconnect(self.pBar.setValue),此时解除和QProgressBar的setValue()的关联;或者不指定,在不指定slot的场景下这样将解除和这个信号所有关联的槽。



4、信号与信号的关联:

self.buttonRun.clicked.connect(self.buttonSave.clicked)

在示例说明中提到,在运行之前要对样本进行保存,所以为了保证运行的时候执行了保存的操作,所以将buttonRun.clicked信号和buttonSave.clicked信号关联起来。



示例中在没有执行“保存”(buttonSave)的时候,执行“运行”(buttonRun),此时由于两个对象的clicked信号已经关联,所以buttonSave的clicked同样会执行。



八自定义信号

PyQt5已经自动定义了很多QT内建的信号。但是在实际的使用中为了灵活使用信号与槽机制,我们可以根据需要自定义signal。可以使用pyqtSignal()方法定义新的信号,新的信号作为类的属性。



自定义signal说明:



pyqtSignal()方法原型(PyQt官网的定义):



PyQt5.QtCore.pyqtSignal(types[,name[,revision=0[,arguments=[]]]])

Createoneormoreoverloadedunboundsignalsasaclassattribute.



Parameters:

types–thetypesthatdefinetheC++signatureofthesignal.EachtypemaybeaPythontypeobjectorastringthatisthenameofaC++type.Alternativelyeachmaybeasequenceoftypearguments.Inthiscaseeachsequencedefinesthesignatureofadifferentsignaloverload.Thefirstoverloadwillbethedefault.



name–thenameofthesignal.Ifitisomittedthenthenameoftheclassattributeisused.Thismayonlybegivenasakeywordargument.



revision–therevisionofthesignalthatisexportedtoQML.Thismayonlybegivenasakeywordargument.



arguments–thesequenceofthenamesofthesignal’sargumentsthatisexportedtoQML.Thismayonlybegivenasakeywordargument.

Returntype:anunboundsignal



新的信号应该定义在QObject的子类中。新的信号必须作为定义类的一部分,不允许将信号作为类的属性在类定义之后通过动态的方式进行添加。通过这种方式新的信号才能自动的添加到QMetaObject类中。这就意味这新定义的信号将会出现在QtDesigner,并且可以通过QMetaObjectAPI实现内省。

通过下面的例子,了解一下关于signal的定义:



fromPyQt5.QtCoreimportQObject,pyqtSignal



classNewSignal(QObject):



#定义了一个“closed”信号,该信号没有参数据

closed=pyqtSignal()



#定义了一个"range_changed"信号,该信号有两个int类型的参数

range_changed=pyqtSignal(int,int,name=''rangeChanged'')



自定义信号的发射,通过emit()方法类实现,具体参见该函数的原型:



emit(args)

Parameters:args–theoptionalsequenceofargumentstopasstoanyconnectedslots.



通过下面的例子,了解一下关于emit()的使用:



fromPyQt5.QtCoreimportQObject,pyqtSignal



classNewSignal(QObject):



#一个valueChanged的信号,该信号没有参数.

valueChanged=pyqtSignal()



defconnect_and_emit_valueChanged(self):

#绑定信号和槽函数

self.valueChanged.connect(self.handle_valueChanged)



#发射信号.

self.trigger.emit()



defhandle_valueChanged(self):

print("triggersignalreceived")



示例说明:



自定义信号的一般流程如下:

1、定义信号

2、定义槽函数

3、绑定信号和槽

4、发射信号



通过代码示例来了解一下信号的自定义过程:



#--coding:utf-8--

''''''

definedSignal

''''''

__author__=''TonyZhu''

importsys

fromPyQt5.QtCoreimportpyqtSignal,QObject,Qt,pyqtSlot

fromPyQt5.QtWidgetsimwww.sm136.comportQWidget,QApplication,QGroupBox,QPushButton,QLabel,QCheckBox,QSpinBox,QHBoxLayout,QComboBox,QGridLayout





classSignalEmit(QWidget):

helpSignal=pyqtSignal(str)

printSignal=pyqtSignal(list)

#声明一个多重载版本的信号,包括了一个带int和str类型参数的信号,以及带str参数的信号

previewSignal=pyqtSignal([int,str],[str])

def__init__(self):

super().__init__()

self.initUI()





definitUI(self):



self.creatContorls("打印控制:")

self.creatResult("操作结果:")



layout=QHBoxLayout()

layout.addWidget(self.controlsGroup)

layout.addWidget(self.resultGroup)

self.setLayout(layout)



self.helpSignal.connect(self.showHelpMessage)

self.printSignal.connect(self.printPaper)

self.previewSignal[str].connect(self.previewPaper)

self.previewSignal[int,str].connect(self.previewPaperWithArgs)

self.printButton.clicked.connect(self.emitPrintSignal)

self.previewButton.clicked.connect(self.emitPreviewSignal)



self.setGeometry(300,300,290,150)

self.setWindowTitle(''definedsignal'')

self.show()



defcreatContorls(self,title):

self.controlsGroup=QGroupBox(title)

self.printButton=QPushButton("打印")

self.previewButton=QPushButton("预览")

numberLabel=QLabel("打印份数:")

pageLabel=QLabel("纸张类型:")

self.previewStatus=QCheckBox("全屏预览")

self.numberSpinBox=QSpinBox()

self.numberSpinBox.setRange(1,100)

self.styleCombo=QComboBox(self)

self.styleCombo.addItem("A4")

self.styleCombo.addItem("A5")



controlsLayout=QGridLayout()

controlsLayout.addWidget(numberLabel,0,0)

controlsLayout.addWidget(self.numberSpinBox,0,1)

controlsLayout.addWidget(pageLabel,0,2)

controlsLayout.addWidget(self.styleCombo,0,3)

controlsLayout.addWidget(self.printButton,0,4)

controlsLayout.addWidget(self.previewStatus,3,0)

controlsLayout.addWidget(self.previewButton,3,1)

self.controlsGroup.setLayout(controlsLayout)



defcreatResult(self,title):

self.resultGroup=QGroupBox(title)

self.resultLabel=QLabel("")

layout=QHBoxLayout()

layout.addWidget(self.resultLabel)

self.resultGroup.setLayout(layout)



defemitPreviewSignal(self):

ifself.previewStatus.isChecked()==True:

self.previewSignal[int,str].emit(1080,"FullScreen")

elifself.previewStatus.isChecked()==False:

self.previewSignal[str].emit("Preview")



defemitPrintSignal(self):

pList=[]

pList.append(self.numberSpinBox.value())

pList.append(self.styleCombo.currentText())

self.printSignal.ewww.shanxiwang.netmit(pList)



defprintPaper(self,list):

self.resultLabel.setText("Print:"+"份数:"+str(list[0])+"纸张:"+str(list[1]))



defpreviewPaperWithArgs(self,style,text):

self.resultLabel.setText(str(style)+text)



defpreviewPaper(self,text):

self.resultLabel.setText(text)



defkeyPressEvent(self,event):



ifevent.key()==Qt.Key_F1:

self.helpSignal.emit("helpmessage")



defshowHelpMessage(self,message):

self.resultLabel.setText(message)

#self.statusBar().showMessage(message)





if__name__==''__main__'':



app=QApplication(sys.argv)

dispatch=SignalEmit()

sys.exit(app.exec_())





示例说明:

通过一个模拟打印的界面来详细说明一下关于信号的自定义,在打印的时候可以设定打印的分数,纸张类型,触发“打印”按钮之后,将执行结果显示到右侧;通过全屏预览QCheckBox来选择是否通过全屏模式进行预览,将执行结果显示到右侧。

通过点击F1快捷键,可以显示helpMessage信息。

代码分析:

L12~15:



helpSignal=pyqtSignal(str)

printSignal=pyqtSignal(list)

#声明一个多重载版本的信号,包括了一个带int和str类型参数的信号,以及带str参数的信号

previewSignal=pyqtSignal([int,str],[str])



通过pyqtSignal()定义了三个信号,helpSignal,printSignal,previewSignal。其中:

helpSignal为str参数类型的信号;

printSignal为list参数类型的信号;

previewSignal为一个多重载版本的信号,包括了一个带int和str类型参数的信号,以及str类行的参数。



L31~36:



self.helpSignal.connect(self.showHelpMessage)

self.printSignal.connect(self.printPaper)

self.previewSignal[str].connect(self.previewPaper)self.previewSignal[int,str].connect(self.previewPaperWithArgs)self.printButton.clicked.connect(self.emitPrintSignal)self.previewButton.clicked.connect(self.emitPreviewSignal)



绑定信号和槽;着重说明一下多重载版本的信号的绑定,previewSignal有两个版本previewSignal(str),previewSignal(int,str)。由于存在两个版本,从因此在绑定的时候需要显式的指定信号和槽的绑定关系。



具体如下:

self.previewSignal[str].connect(self.previewPaper)self.previewSignal[int,str].connect(self.previewPaperWithArgs)

其中[str]参数的previewSignal信号绑定previewPaper();[int,str]的previewSignal信号绑定previewPaperWithArgs()



L72~76:



defemitPreviewSignal(self):

ifself.previewStatus.isChecked()==True:

self.previewSignal[int,str].emit(1080,"FullScreen")

elifself.previewStatus.isChecked()==False:

self.previewSignal[str].emit("Preview")



多重载版本的信号的发射也需要制定对应发射的版本,类似同信号的版定。



L78~82:



defemitPrintSignal(self):

pList=[]

pList.append(self.numberSpinBox.value())

pList.append(self.styleCombo.currentText())

self.printSignal.emit(pList)



如代码中所示,在信号发射的时候可以传递python数据类型的参数,在本例中传递list类型的参数pList.



L93~96:



defkeyPressEvent(self,event):

ifevent.key()==Qt.Key_F1:

self.helpSignal.emit("helpmessage")



通过复写keyPressEvent()方法,将F1快捷键进行功能的拓展。在windows的大部分应用,我们都会使用一些快捷键来快速的完成某些特定的功能。比如F1键,会快速调出帮助界面。那我们就可以复写keyPressEvent()方法来模拟发送所需的信号,来完成我们的对应任务.



注意事项:



1、自定义的信号在init()函数之前定义;

2、自定义型号可以传递,str、int、list、object、float、tuple、dict等很多类型的参数;

3、注意signal和slot的调用逻辑,避免signal和slot之间出现死循环。如在slot方法中继续发射该信号;



九基本布局管理

GUI的布局管理是GUI开发中非常重要的一个环节,一个设计良好的GUI界面,其对应的布局排布也是非常必须的。其中布局管理就是要管理窗口中部件的放置。常用两种方式来实现布局:绝对位置布局(AbsoluteLayout)实现,布局类(QLayout)实现。

绝对位置布局(AbsoluteLayout)主要是在程序中通过指定每一个组件显示的坐标和大小。由于影响绝对布局显示的因素很多(平台的差异,窗口大小的差异,显示字体大小等因素),所以在本文中主要以QLayout的基本布局进行说明。



布局定义



常用到的布局类有QHBoxLayout,QVBoxLayout,QGridLayout,QFormLayout4种,分别水平排列布局,垂直排列布局,表格排列布局,以及。布局中最常用的方法有addWidget()和addLayout(),addWidget()方法用于在布局中插入控件,addLayout()用于在布局中插入子布局。



水平布局管理器(QHBoxLayout)可以把添加的控件以水平的顺序依次排开;

垂直布局管理器(QVBoxLayout)可以把添加的控件以垂直的顺序依次排开;

网格布局管理器(QGridLayout)可以以网格的形式,把添加的控件以一定矩阵排列;

窗体布局管理器(QFormLayout)可以以两列的形式排列所添加的控件



-水平(垂直)布局管理:

QHBoxLayout,按照从左到右的顺序进行添加控件。

QVBoxLayout,按照从上到下的顺序进行添加控件。

QHBoxLayout和QVBoxLayout用法基本相同。这里以水平布局管理器QHBoxLayout为例来说明。



classQHBoxLayout(QBoxLayout)

|QHBoxLayout()

|QHBoxLayout(QWidget)



常用方法:

|addLayout(…)

|QBoxLayout.addLayout(QLayout,intstretch=0)

在box的底部添加布局,其中默认的拉伸因子为0



|addWidget(…)

|QBoxLayout.addWidget(QWidget,intstretch=0,Qt.Alignmentalignment=0)

为布局中添加控件,stretch(拉伸因子)只适用与QBoxLayout,widget和box会随着stretch的变大而增大;alignment指定对齐的方式



|addSpacing(…)

|QBoxLayout.addSpacing(int)

通过该方法增加额外的space。



-网格布局管理器:

将窗体分隔成行和列的网格来进行排列(可以认为是二维的数据排布)。通常可以使用函数addWidget()或者addLayout()来将被管理的widget或者layout添加到窗格中。也可以通过重载的函数addWidget()或者addLayout()的行和列跨度实现占据多个窗格。



classQGridLayout(QLayout)

|QGridLayout(QWidget)

|QGridLayout()



常用方法:



添加组件

|addWidget(…)

|QGridLayout.addWidget(QWidget)

|QGridLayout.addWidget(QWidgetwidget,introw,intcolumn,Qt.Alignmentalignment=0)

QWidget:为所添加的组件

row:为组件要添加的行数,默认从0开始

column:为组件要添加到的列数,默认从0开始

alignment:对齐的方式



|QGridLayout.addWidget(QWidgetwidget,intfromRow,intfromColumn,introwSpan,intcolumnSpan,Qt.Alignmentalignment=0)

当添加的组件跨越很多行或者列的时候,使用该方法。

QWidget:为所添加的组件

fromRow:为组件起始的行数

fromColumn:为组件起始的列数

rowSpan:为组件跨越的行数

columnSpan:为组件跨越的列数

alignment:对齐的方式



|addLayout(…)

|QGridLayout.addLayout(QLayout,int,int,Qt.Alignmentalignment=0)

|QGridLayout.addLayout(QLayout,int,int,int,int,Qt.Alignmentalignment=0)



其中参数说明同addWidget.



-窗体布局管理器:

在窗口中按照两列的形式排列控件,两列控件的类型可以根据使用的场景不同而不同。



classQFormLayout(QLayout)

|QFormLayout(QWidgetparent=None)



常用方法:

|addRow(…)

|QFormLayout.addRow(QWidget,QWidget)

|QFormLayout.addRow(QWidget,QLayout)

|QFormLayout.addRow(str,QWidget)

|QFormLayout.addRow(str,QLayout)

|QFormLayout.addRow(QWidget)

|QFormLayout.addRow(QLayout)



示例说明





QVBoxLayout(mainLayout)中包含QHBoxLayout和QFormLayout.其中QHBoxLayout中嵌套了QGridLayout和QVBoxLayout.

看一下具体的代码实现:



#--coding:utf-8--

''''''

BasicLayout

''''''

__author__=''TonyZhu''

importsys

fromPyQt5.QtGuiimportQPixmap

fromPyQt5.QtWidgetsimportQWidget,QApplication,QGroupBox,QPushButton,QLabel,QHBoxLayout,QVBoxLayout,QGridLayout,QFormLayout,QLineEdit,QTextEdit



classTianGong(QWidget):

def__init__(self):

super(TianGong,self).__init__()

self.initUi()



definitUi(self):

self.createGridGroupBox()

self.creatVboxGroupBox()

self.creatFormGroupBox()

mainLayout=QVBoxLayout()

hboxLayout=QHBoxLayout()

hboxLayout.addStretch()

hboxLayout.addWidget(self.gridGroupBox)

hboxLayout.addWidget(self.vboxGroupBox)

mainLayout.addLayout(hboxLayout)

mainLayout.addWidget(self.formGroupBox)

self.setLayout(mainLayout)



defcreateGridGroupBox(self):

self.gridGroupBox=QGroupBox("Gridlayout")

layout=QGridLayout()



nameLabel=QLabel("中文名称")

nameLineEdit=QLineEdit("天宫二号")

emitLabel=QLabel("发射地点")

emitLineEdit=QLineEdit("酒泉中心")

timeLabel=QLabel("发射时间")

timeLineEdit=QLineEdit("9月15日")

imgeLabel=QLabel()

pixMap=QPixmap("tiangong.png")

imgeLabel.setPixmap(pixMap)

layout.setSpacing(10)

layout.addWidget(nameLabel,1,0)

layout.addWidget(nameLineEdit,1,1)

layout.addWidget(emitLabel,2,0)

layout.addWidget(emitLineEdit,2,1)

layout.addWidget(timeLabel,3,0)

layout.addWidget(timeLineEdit,3,1)

layout.addWidget(imgeLabel,0,2,4,1)

layout.setColumnStretch(1,10)

self.gridGroupBox.setLayout(layout)

self.setWindowTitle(''BasicLayout'')



defcreatVboxGroupBox(self):

self.vboxGroupBox=QGroupBox("Vboxlayout")

layout=QVBoxLayout()

nameLabel=QLabel("科研任务:")

bigEditor=QTextEdit()

bigEditor.setPlainText("搭载了空间冷原子钟等14项应用载荷,以及失重心血管研究等航天医学实验设备"

"开展空间科学及技术试验.")

layout.addWidget(nameLabel)

layout.addWidget(bigEditor)

self.vboxGroupBox.setLayout(layout)



defcreatFormGroupBox(self):

self.formGroupBox=QGroupBox("Formlayout")

layout=QFormLayout()

performanceLabel=QLabel("性能特点:")

performanceEditor=QLineEdit("舱内设计更宜居方便天宫生活")

planLabel=QLabel("发射规划:")

planEditor=QTextEdit()

planEditor.setPlainText("2020年之前,中国计划初步完成空间站建设")

layout.addRow(performanceLabel,performanceEditor)

layout.addRow(planLabel,planEditor)



self.formGroupBox.setLayout(layout)





if__name__==''__main__'':

app=QApplication(sys.argv)

ex=TianGong()

ex.show()

sys.exit(app.exec_())



代码分析:

L28~51:



defcreateGridGroupBox(self):

self.gridGroupBox=QGroupBox("Gridlayout")

layout=QGridLayout()



nameLabel=QLabel("中文名称")

nameLineEdit=QLineEdit("天宫二号")

emitLabel=QLabel("发射地点")

emitLineEdit=QLineEdit("酒泉中心")

timeLabel=QLabel("发射时间")

timeLineEdit=QLineEdit("9月15日")

imgeLabel=QLabel()

pixMap=QPixmap("tiangong.png")

imgeLabel.setPixmap(pixMap)

layout.setSpacing(10)

layout.addWidget(nameLabel,1,0)

layout.addWidget(nameLineEdit,1,1)

layout.addWidget(emitLabel,2,0)

layout.addWidget(emitLineEdit,2,1)

layout.addWidget(timeLabel,3,0)

layout.addWidget(timeLineEdit,3,1)

layout.addWidget(imgeLabel,0,2,4,1)

layout.setColumnStretch(1,10)

self.gridGroupBox.setLayout(layout)

self.setWindowTitle(''BasicLayout'')



定义QGridLayout布局。其中增加QGroupBox(有标题的组合框在它里面地其它不同窗口部件),将QGridLayout添加到QGroupBox中。

在本例中使用了不同参数重载的addWidget()方法。



在QLabel中显示图片。

pixMap=QPixmap(“tiangong.png”)

imgeLabel.setPixmap(pixMap)



layout.setColumnStretch(1,10)指定的行,设定其拉伸因子为10。



addWidget(self,QWidget,int,int,Qt.Alignmentalignment=0)

addWidget(self,QWidget,int,int,int,int,Qt.Alignmentalignment=0)

QWidget参数为需插入的控件对象,后面的两个int参数为插入的行和列,再后面两上int参数为跨度的行数和跨度的列数,alignment参数描述各控件的对齐方式。



L53~62:



defcreatVboxGroupBox(self):

self.vboxGroupBox=QGroupBox("Vboxlayout")

layout=QVBoxLayout()

nameLabel=QLabel("科研任务:")

bigEditor=QTextEdit()

bigEditor.setPlainText("搭载了空间冷原子钟等14项应用载荷,以及失重心血管研究等航天医学实验设备"

"开展空间科学及技术试验.")

layout.addWidget(nameLabel)

layout.addWidget(bigEditor)

self.vboxGroupBox.setLayout(layout)



定义QVBoxLayout布局。将QVBoxLayout添加到QGroupBox中。通过addWidget()方法增加所需的控件。



L64~75:



defcreatFormGroupBox(self):

self.formGroupBox=QGroupBox("Formlayout")

layout=QFormLayout()

performanceLabel=QLabel("性能特点:")

performanceEditor=QLineEdit("舱内设计更宜居方便天宫生活")

planLabel=QLabel("发射规划:")

planEditor=QTextEdit()

planEditor.setPlainText("2020年之前,中国计划初步完成空间站建设")

layout.addRow(performanceLabel,performanceEditor)

layout.addRow(planLabel,planEditor)

self.formGroupBox.setLayout(layout



定义QFormLayout布局。将QFormLayout添加到QGroupBox中。通过addRow()方法增加所需的控件。



L19~25:



mainLayout=QVBoxLayout()

hboxLayout=QHBoxLayout()

hboxLayout.addStretch()

hboxLayout.addWidget(self.gridGroupBox)

hboxLayout.addWidget(self.vboxGroupBox)

mainLayout.addLayout(hboxLayout)

mainLayout.addWidget(self.formGroupBox)



定义QVBoxLayout类型的mainLayout,并将定义好的各个layout和groupbox按照嵌套的关系添加到mainLayout中。



十QtWidget的使用

在很多应用使用的场景中我们需要和各种类型的数据进行交互,通过表格的形式进行操作和呈现。在PyQt中提供了QTableWidget默认模式的表格类。

QTableWidget是QTableViewer的子类,其中QTableViewer可以使用自定义的数据模型来显示内容(通过setModel

()来绑定数据源),而QTableWidget提供了一套标准的数据模型,QTableWidgetItem对象作为QTableWidget中的单元数据来显示。使用QTableWidget就依赖于QTableWidgetItem。QTableWidgetItem用来表示表格中的一个单元格,通过一个个单元格组成整体的表。



QTableWidget简介:





如上图是QTableWidget的显示。



1.QTableWidgets实例化

根据QTableWidget的构造函数,我们在定义实例化的时候可以指定显示的行数和列数,也可以在QTableWidget实例化之后通过成员函数进行设定:



self.table=QTableWidget(5,2)

或者



self.table=QTableWidget()

self.table.setColumnCount(5)

self.table.setRowCount(2)



2.表头操作:

在table表头分为水平和垂直两种,及horizontalheader和verticalheader两类。



添加表头:

可以添加水平和垂直表头,QtWidgets提供两个方法(setHorizontalHeaderLabels()和setVerticalHeaderLabels())来添加,如下为添加水平表头。



horizontalHeader=["工号","姓名","性别","年龄","职称"]

self.table=QTableWidget()

self.table.setHorizontalHeaderLabels(horizontalHeader)

表头的隐藏和显示:

根据不同的应用场景可能需要对于表头进行隐藏和显示的操作,直接对表头进行操作。

如下隐藏了垂直的表头:



self.table=QTableWidget()

self.table.verticalHeader().setVisible(False)



表头字体,颜色的设定:

由于表头也是由多个item构成的,所以通过循环操作对每一个item进行操作。



self.table=QTableWidget()

forindexinrange(self.table.columnCount()):

headItem=self.table.horizontalHeaderItem(index)

headItem.setFont(QFont("song",12,QFont.Bold))

headItem.setForeground(QBrush(Qt.gray))

headItem.setTextAlignment(Qt.AlignLeft|Qt.AlignVCenter)



3.表格设置

在表格的应用中,我们需要对表格的样式,编辑模式,选择行为进行设置。

编辑方式:

对于表格中的数据,默认只要双击就可以修改其中的数据。如果文档是处于预览状态或者不可编辑状态,那就需要对表格设定为不可编辑模式。



self.table=QTableWidget()

self.table.setEditTriggers(QTableWidget.NoEditTriggers)



对于表格的编辑的设定通过setEditTriggers()方法来实现。如下都是触发修改单元格内容的条件:



QTableWidget.NoEditTriggers0Noeditingpossible.不能对表格内容进行修改

QTableWidget.CurrentChanged1Editingstartwhenevercurrentitemchanges.任何时候都能对单元格修改

QTableWidget.DoubleClicked2Editingstartswhenanitemisdoubleclicked.双击单元格

QTableWidget.SelectedClicked4Editingstartswhenclickingonanalreadyselecteditem.单击已选中的内容

QTableWidget.EditKeyPressed8Editingstartswhentheplatformeditkeyhasbeenpressedoveranitem.

QTableWidget.AnyKeyPressed16Editingstartswhenanykeyispressedoveranitem.按下任意键就能修改

QTableWidget.AllEditTriggers31Editingstartsforallaboveactions.以上条件全包括



单元格选择:

比如我们在单击某个单元格的时候,此时默认的行为是选中单元格,还是单元格所在的行或列,这个可以通过setSelectionBehavior()方法设定。如下为默认选中列:



self.table=QTableWidget()

self.table.setSelectionBehavior(QTableWidget.SelectColumns)



QTableWidget.SelectItems0Selectingsingleitems.选中单个单元格

QTableWidget.SelectRows1Selectingonlyrows.选中一行

QTableWidget.SelectColumns2Selectingonlycolumns.选中一列



行选择方式:

比如我们需要同时选择不相邻的多个函数的时候,在excell中我们通过按shift然后点击鼠标来选择多行。在QtWidget也存在类似行为,我们可以通过setSelectionMode()方法来实现:



self.table=QTableWidget()

self.table.setSelectionMode(QTableWidget.SingleSelection)



可以设定的选择模式:

QTableWidget.NoSelection不能选择

QTableWidget.SingleSelection选中单个目标

QTableWidget.MultiSelection选中多个目标

QTableWidget.ExtendedSelectionshift键的连续选择

QTableWidget.ContiguousSelectionctrl键的不连续的多个选择



网格的显示

通常默认的情况下需要显示表格的网格线,在一些场景下不需要显示网格线。则需要将对应的横竖线进行隐藏:



self.table=QTableWidget()

self.table.setShowGrid(False)

setShowGrid(),False不显示网格线,True显示网格线



添加表项

由于整个表格是由一个个单元格组成,所以需要将单个的表格项添加到整个表格中。通过setItem()进行操作,如下为添加一个为str类型内容的表格:



self.table=QTableWidget()

self.table.setItem(0,0,QTableWidgetItem("001"))



setItem(int,int,QTableWidgetItem)

第1个参数行号,从0开始

第2个参数列号,从0开始

第3个参数QTableWidgetItem对象。



表项添加自定义控件

比如在有些表项中需要QComboBox来实现下拉框的功能,比如性别选择的时候就可以通过下拉框来实现选择。



self.table=QTableWidget()

genderComb=QComboBox()

genderComb.addItem("男性")

genderComb.addItem("女性")

genderComb.setCurrentIndex(0)

self.table.setCellWidget(0,2,genderComb)



实例化一个QComboBox对象,通过setCellWidget()将QComboBox添加到指定的单元格中。通过行号和列号唯一确定一个单元格。

setCellWidget(intint,QWidget)

第1个参数行号,从0开始

第2个参数列号,从0开始

第3个参数QWidget对象。



4.单元格操作



单元格对齐方式

在单元格中操作字符显示的是否,常常需要操作各种对齐,比如水平的左对齐、右对齐、居中等,垂直的靠上、靠下对齐等方式。



headItem.setTextAlignment(Qt.AlignLeft|Qt.AlignVCenter)

通过setTextAlignment()方法来设定,由于需要同时考虑水平和垂直方向,所以通过或‘|’的方式将两个方向的对齐组合起来,如Qt.AlignLeft|Qt.AlignVCenter。

水平方向:

Qt.AlignLeft0x0001Alignswiththeleftedge.

Qt.AlignRight0x0002Alignswiththerightedge.

Qt.AlignHCenter0x0004Centershorizontallyintheavailablespace.

Qt.AlignJustify0x0008Justifiesthetextintheavailablespace.

垂直方向:

Qt.AlignTop0x0020Alignswiththetop.

Qt.AlignBottom0x0040Alignswiththebottom.

Qt.AlignVCenter0x0080Centersverticallyintheavailablespace.



单元格大小设定

有时候需要根据显示的要求来调整单元格的大小,行的宽度和列的高度。



self.table=QTableWidget()

self.table.setColumnWidth(4,200)

self.table.setRowHeight(0,40)



通过setColumnWidth()和setRowHeight()设定特定行或者列上的大小。



有时候需要根据显示的内容自动调整单元格的大小,类似office中的内容相匹配。



self.table=QTableWidget()

self.table.resizeColumnsToContents()

self.table.resizeRowsToContents()



动态插入行列

当初始的行数或者列数不能满足需要的时候,我们需要动态的调整表格的大小,如入动态的插入行:



self.table=QTableWidget()

row_count=self.table.rowCount()

self.table.insertRow(row_count)

本例中为插入到最后一行的后面。insertColumn()动态插入列。



insertRow(int)、insertColumn(int),指定位置插入行或者列



动态移除行列

removeColumn(intcolumn)移除column列及其内容。

removeRow(introw)移除第row行及其内容。



self.table=QTableWidget()

row_count=self.table.rowCount()

self.table.removeRow(row_count-1)



本例中为移除最后一行。



其他操作

clear()清除所有表项及表头

setSpan(int,int,int,int),合并单元格



代码示例



#--coding:utf-8--

''''''

TableWidget

''''''

__author__=''TonyZhu''

importsys

fromPyQt5.QtCoreimportQt

fromPyQt5.QtWidgetsimportQWidget,QApplication,QLabel,QTableWidget,QHBoxLayout,QTableWidgetItem,QComboBox,QFrame

fromPyQt5.QtGuiimportQFont,QColor,QBrush,QPixmap

classTableSheet(QWidget):

def__init__(self):

super().__init__()

self.initUi()



definitUi(self):

horizontalHeader=["工号","姓名","性别","年龄","职称"]

self.setWindowTitle(''TableWidgetUsage'')

self.table=QTableWidget()

self.table.setColumnCount(5)

self.table.setRowCount(2)

self.table.setHorizontalHeaderLabels(horizontalHeader)

self.table.setEditTriggers(QTableWidget.NoEditTriggers)

self.table.setSelectionBehavior(QTableWidget.SelectColumns)

self.table.setSelectionMode(QTableWidget.SingleSelection)



forindexinrange(self.table.columnCount()):

headItem=self.table.horizontalHeaderItem(index)

headItem.setFont(QFont("song",12,QFont.Bold))

headItem.setForeground(QBrush(Qt.gray))

headItem.setTextAlignment(Qt.AlignLeft|Qt.AlignVCenter)



self.table.setColumnWidth(4,200)

self.table.setRowHeight(0,40)

#self.table.setFrameShape(QFrame.HLine)#设定样式

#self.table.setShowGrid(False)#取消网格线

#self.table.verticalHeader().setVisible(False)#隐藏垂直表头



self.table.setItem(0,0,QTableWidgetItem("001"))

self.table.setItem(0,1,QTableWidgetItem("Tom"))

genderComb=QComboBox()

genderComb.addItem("男性")

genderComb.addItem("女性")

genderComb.setCurrentIndex(0)

self.table.setCellWidget(0,2,genderComb)

self.table.setItem(0,3,QTableWidgetItem("30"))

self.table.setItem(0,4,QTableWidgetItem("产品经理"))



self.table.setItem(1,0,QTableWidgetItem("005"))

self.table.setItem(1,1,QTableWidgetItem("Kitty"))

genderComb=QComboBox()

genderComb.addItem("男性")

genderComb.addItem("女性")

genderComb.setCurrentIndex(1)

self.table.setCellWidget(1,2,genderComb)

self.table.setItem(1,3,QTableWidgetItem("24"))

self.table.setItem(1,4,QTableWidgetItem("程序猿安慰师"))



row_count=self.table.rowCount()

self.table.insertRow(row_count)

mainLayout=QHBoxLayout()

mainLayout.addWidget(self.table)

self.setLayout(mainLayout)



if__name__==''__main__'':



app=QApplication(sys.argv)

table=TableSheet()

table.show()

sys.exit(app.exec_())





献花(0)
+1
(本文系网络学习天...首藏)