本实例综合应用前面介绍的布局方法实现一个复杂的窗口布局,实现效果图如下所示。其中包括了基本布局,分割窗以及堆栈窗。
首先对整个窗体的构成进行一个整体的分析。最外层的是一个分割窗体QSplitter,分割窗的左侧为一个QListWidget,右侧为一个QVBoxLayout布局,包括一个堆栈窗QStackWidget和一个按钮布局,在堆栈窗中包含3个窗体,每个窗体采用基本布局方式进行布局管理。窗体的布局可用如下的示意图表示。
堆栈窗中的3个页面分别定义了3个QWidget子类,包括“个人基本资料”页,由BaseInfo类实现,“联系方式”页,由Contact类实现,“详细信息”页,由Detail类实现。
“个人基本资料”页与实例12中的内容一样,可直接引用。
“联系方式”页和“详细信息”页都是采用表格布局的方式进行布局管理,用法与前面所介绍的类似,此处不再重复进行分析。
具体实现代码如下:
# -*- coding: utf-8 -*-
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys
QTextCodec.setCodecForTr(QTextCodec.codecForName("utf8"))
class StockDialog(QDialog):
def __init__(self,parent=None):
super(StockDialog,self).__init__(parent)
self.setWindowTitle(self.tr("综合布局实例"))
mainSplitter=QSplitter(Qt.Horizontal)
mainSplitter.setOpaqueResize(True)
listWidget=QListWidget(mainSplitter)
listWidget.insertItem(0,self.tr("个人基本资料"))
listWidget.insertItem(1,self.tr("联系方式"))
listWidget.insertItem(2,self.tr("详细信息"))
frame=QFrame(mainSplitter)
stack=QStackedWidget()
stack.setFrameStyle(QFrame.Panel|QFrame.Raised)
baseInfo=BaseInfo()
contact=Contact()
detail=Detail()
stack.addWidget(baseInfo)
stack.addWidget(contact)
stack.addWidget(detail)
amendPushButton=QPushButton(self.tr("修改"))
closePushButton=QPushButton(self.tr("关闭"))
buttonLayout=QHBoxLayout()
buttonLayout.addStretch(1)
buttonLayout.addWidget(amendPushButton)
buttonLayout.addWidget(closePushButton)
mainLayout=QVBoxLayout(frame)
mainLayout.setMargin(10)
mainLayout.setSpacing(6)
mainLayout.addWidget(stack)
mainLayout.addLayout(buttonLayout)
self.connect(listWidget,SIGNAL("currentRowChanged(int)"),stack,SLOT("setCurrentIndex(int)"))
self.connect(closePushButton,SIGNAL("clicked()"),self,SLOT("close()"))
layout=QHBoxLayout(self)
layout.addWidget(mainSplitter)
self.setLayout(layout)
class BaseInfo(QWidget):
def __init__(self,parent=None):
super(BaseInfo,self).__init__(parent)
label1=QLabel(self.tr("用户名:"))
label2=QLabel(self.tr("姓名:"))
label3=QLabel(self.tr("性别:"))
label4=QLabel(self.tr("部门:"))
label5=QLabel(self.tr("年龄:"))
otherLabel=QLabel(self.tr("备注:"))
otherLabel.setFrameStyle(QFrame.Panel|QFrame.Sunken)
userLineEdit=QLineEdit()
nameLineEdit=QLineEdit()
sexComboBox=QComboBox()
sexComboBox.insertItem(0,self.tr("男"))
sexComboBox.insertItem(1,self.tr("女"))
departmentTextEdit=QTextEdit()
ageLineEdit=QLineEdit()
labelCol=0
contentCol=1
leftLayout=QGridLayout()
leftLayout.addWidget(label1,0,labelCol)
leftLayout.addWidget(userLineEdit,0,contentCol)
leftLayout.addWidget(label2,1,labelCol)
leftLayout.addWidget(nameLineEdit,1,contentCol)
leftLayout.addWidget(label3,2,labelCol)
leftLayout.addWidget(sexComboBox,2,contentCol)
leftLayout.addWidget(label4,3,labelCol)
leftLayout.addWidget(departmentTextEdit,3,contentCol)
leftLayout.addWidget(label5,4,labelCol)
leftLayout.addWidget(ageLineEdit,4,contentCol)
leftLayout.addWidget(otherLabel,5,labelCol,1,2)
leftLayout.setColumnStretch(0,1)
leftLayout.setColumnStretch(1,3)
label6=QLabel(self.tr("头像:"))
iconLabel=QLabel()
icon=QPixmap("image/2.jpg")
iconLabel.setPixmap(icon)
iconLabel.resize(icon.width(),icon.height())
iconPushButton=QPushButton(self.tr("改变"))
hLayout=QHBoxLayout()
hLayout.setSpacing(20)
hLayout.addWidget(label6)
hLayout.addWidget(iconLabel)
hLayout.addWidget(iconPushButton)
label7=QLabel(self.tr("个人说明:"))
descTextEdit=QTextEdit()
rightLayout=QVBoxLayout()
rightLayout.setMargin(10)
rightLayout.addLayout(hLayout)
rightLayout.addWidget(label7)
rightLayout.addWidget(descTextEdit)
mainLayout=QGridLayout(self)
mainLayout.setMargin(15)
mainLayout.setSpacing(10)
mainLayout.addLayout(leftLayout,0,0)
mainLayout.addLayout(rightLayout,0,1)
mainLayout.setSizeConstraint(QLayout.SetFixedSize)
class Contact(QWidget):
def __init__(self,parent=None):
super(Contact,self).__init__(parent)
label1=QLabel(self.tr("电子邮件:"))
label2=QLabel(self.tr("联系地址:"))
label3=QLabel(self.tr("邮政编码:"))
label4=QLabel(self.tr("移动电话:"))
label5=QLabel(self.tr("办公电话:"))
mailLineEdit=QLineEdit()
addressLineEdit=QLineEdit()
codeLineEdit=QLineEdit()
mpLineEdit=QLineEdit()
phoneLineEdit=QLineEdit()
receiveCheckBox=QCheckBox(self.tr("接收留言"))
layout=QGridLayout(self)
layout.addWidget(label1,0,0)
layout.addWidget(mailLineEdit,0,1)
layout.addWidget(label2,1,0)
layout.addWidget(addressLineEdit,1,1)
layout.addWidget(label3,2,0)
layout.addWidget(codeLineEdit,2,1)
layout.addWidget(label4,3,0)
layout.addWidget(mpLineEdit,3,1)
layout.addWidget(receiveCheckBox,3,2)
layout.addWidget(label5,4,0)
layout.addWidget(phoneLineEdit,4,1)
class Detail(QWidget):
def __init__(self,parent=None):
super(Detail,self).__init__(parent)
label1=QLabel(self.tr("国家/地区:"))
label2=QLabel(self.tr("省份:"))
label3=QLabel(self.tr("城市:"))
label4=QLabel(self.tr("个人说明:"))
countryComboBox=QComboBox()
countryComboBox.addItem(self.tr("中华人民共和国"))
countryComboBox.addItem(self.tr("香港"))
countryComboBox.addItem(self.tr("台北"))
countryComboBox.addItem(self.tr("澳门"))
provinceComboBox=QComboBox()
provinceComboBox.addItem(self.tr("安徽省"))
provinceComboBox.addItem(self.tr("北京市"))
provinceComboBox.addItem(self.tr("江苏省"))
cityLineEdit=QLineEdit()
remarkTextEdit=QTextEdit()
layout=QGridLayout(self)
layout.addWidget(label1,0,0)
layout.addWidget(countryComboBox,0,1)
layout.addWidget(label2,1,0)
layout.addWidget(provinceComboBox,1,1)
layout.addWidget(label3,2,0)
layout.addWidget(cityLineEdit,2,1)
layout.addWidget(label4,3,0)
layout.addWidget(remarkTextEdit,3,1)
app=QApplication(sys.argv)
main=StockDialog()
main.show()
app.exec_()
第22-30行创建一个QStackWidget对象,第23行调用setFrameStyle()方法对堆栈窗的显示风格进行设置。
第28,29,30行在堆栈窗中顺序插入“个人基本资料”,“联系方式”,“详细信息”3个页面。
第32-38行创建两个按钮,并且QHBoxLayout对其进行布局。
第40-44行采用QVBoxLayout生成主布局。
第13行创建一个水平分割窗,作为主布局框。
第16-19行在水平分割窗的左侧窗体中插入一个QListWidget作为条目选择框,并在列表框中依次插入相应的条目。
第46行把列表框的currentRowChanged()信号与堆栈窗的setCurrentIndex()槽相连接,达到按用户选择的条目显示页面的要求。
本实例综合应用了各种布局方式,完成一个较为复杂的界面显示。包括了各种基本布局类的应用,堆栈窗的应用和分割窗的应用。
要达到同样的显示效果,会有多种可能的布局方案,在实际应用中,应根据具体情况进行选择,使用最方便合理的布局方式。一般来说,QGridLayout功能较为强大,能完成QHBoxLayout与QVBoxLayout的功能,但视具体情况,若只是简单的控件水平或竖直排列,使用QHBoxLayout和QVBoxLayout更加方便,QGridLayout适合较为整齐方正的界面布局。
注:本文基本上是经过改编的《Linux窗口程序设计--Qt4精彩实例分析》一书的PyQt4 for windows版本
转自:http://blog.csdn.net/chumpklutz/article/details/6077078