1. 程式人生 > >PyQt4 精彩例項分析* 例項12 基本佈局管理

PyQt4 精彩例項分析* 例項12 基本佈局管理

本例項利用基本佈局管理(QHBoxLayout,QVBoxLayout,QGridLayout)實現一個類似QQ的使用者資料修改頁面。實現效果圖如下圖所示。

Qt提供的佈局類以及它們之間的繼承關係如下圖所示。

 

常用到的佈局類有QHBoxLayout,QVBoxLayout,QGridLayout 3種,分別水平排列布局,垂直排列布局和表格排列布局。Qt3中的QHBox和QVBox到Qt4以後被廢棄。佈局中最常用的方法有addWidget()和addLayout(),addWidget()方法用於在佈局中插入控制元件,addLayout()用於在佈局中插入子佈局。

下面通過例項的實現過程瞭解佈局管理的使用方法。首先通過一個示意圖瞭解此對話方塊的佈局結構,如下圖所示。

從上圖中可知,本例項共用到4個佈局管理器,分別是LeftLayout,RightLayout,BottomLayout和MainLayout。

下面是具體的實現。

# -*- coding: utf-8 -*-
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys

QTextCodec.setCodecForTr(QTextCodec.codecForName("utf8"))

class LayoutDialog(QDialog):
    def __init__(self,parent=None):
        super(LayoutDialog,self).__init__(parent)
        self.setWindowTitle(self.tr("使用者資訊"))
        
        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)

        OKPushButton=QPushButton(self.tr("確定"))
        cancelPushButton=QPushButton(self.tr("取消"))
        bottomLayout=QHBoxLayout()
        bottomLayout.addStretch()
        bottomLayout.addWidget(OKPushButton)
        bottomLayout.addWidget(cancelPushButton)

        mainLayout=QGridLayout(self)
        mainLayout.setMargin(15)
        mainLayout.setSpacing(10)
        mainLayout.addLayout(leftLayout,0,0)
        mainLayout.addLayout(rightLayout,0,1)
        mainLayout.addLayout(bottomLayout,1,0,1,2)
        mainLayout.setSizeConstraint(QLayout.SetFixedSize)
 
app=QApplication(sys.argv)
dialog=LayoutDialog()
dialog.show()
app.exec_()


第13-26行定義對話方塊左側的控制元件。其中第19行設定控制元件的風格,setFrameStyle()是QFrame的方法,引數以或的方式設定控制元件的面板風格,由形式(QFrame.Shape)和陰影(QFrame.Shadow)兩項配合設定。其中,形狀有NoFrame,Panel,Box,HLine,VLine以及WinPanel 6種,陰影有Plain,Raised和Sunken 3種,具體的效果讀者可自行搭配試驗。

在定義程式碼中,可以不必為各個控制元件指定父視窗,使用佈局管理會自動指定佈局管理下的所有控制元件的父視窗。

第28-44行定義控制元件佈局,實現左部佈局。

第28行定義一個QGridLayout物件leftLayout,由於此佈局管理器並不是主佈局管理器,因此不用指定父視窗,最後由主佈局管理器統一指定。

QGridLayout類的addWidget()方法用來向佈局中加入需佈局的控制元件,第32-42行呼叫此方法插入需佈局的控制元件。addWidget()的函式原型如下:

addWidget (self, QWidget)
addWidget (self, QWidget, int, int, Qt.Alignment alignment = 0)
addWidget (self, QWidget, int, int, int, int, Qt.Alignment alignment = 0)

QWidget引數為需插入的控制元件物件,後面的兩個int引數為插入的行和列,再後面兩上int引數為跨度的行數和跨度的列數,alignment引數描述各控制元件的對齊方式。

第41行和42行設定兩列分別佔用的空間的比例,此處設定兩列的空間比為1:3。即使對話方塊框架大小改變了,兩列之間的寬度比依然保持不變。

第46-56行實現對話方塊右上側的頭像選擇區的佈局,此處採用一個QHBoxLayout類進行佈局管理。QHBoxLayout預設採取自左向右的方式順序排列插入的控制元件,也可通過呼叫setDirection()方法設定排列的順序,例如:

hLayout.setDirection(QBoxLayout.RightToLeft)

第53行呼叫QLayout的setSpacing()方法設定各個控制元件之間的間距為20。

第58-65行程式碼實現對話方塊右側的佈局。由一個QVBoxLayout實現佈局,QVBoxLayout預設自上而下順序排列插入的控制元件或子佈局,也可通過setDirection()方法改變排列的順序。由於右側上部的頭像選擇區已使用佈局,因此第63行呼叫addLayout()方法在佈局中插入子佈局。

第67-72行程式碼實現對話方塊下方兩個按鈕的佈局,採用QHBoxLayout實現。

第70行呼叫addStretch()方法在按鈕之前插入一個佔位符,使兩個按鈕能靠右對齊。並且在整個對話方塊的大小發生改變時,保證按鈕的大小不發生變化。合理使用addStretch()能讓介面的佈局效果增色不少。

最後實現主佈局,用一個QGridLayout實現,並在定義主佈局時指定父視窗self,也可呼叫self.setLayout(mainLayout)實現。

第75行設定對話方塊的邊距為15。

第79行插入的子佈局佔用了兩列,使用的函式方法和前面的是一樣的,也呼叫addLayout()方法,只是引數不同,原型如下:

addLayout (self, QLayout, int, int, int, int, Qt.Alignment alignment = 0)

QLayout引數為需插入的控制元件物件,後面的兩個int引數為插入的行和列,再後面兩上int引數為跨度的行數和跨度的列數,alignment引數描述各控制元件的對齊方式。

最後,第80行設定對話方塊的控制元件總是最優化顯示,並且使用者無法改變對話方塊的大小,所謂最優化顯示,即控制元件都按其sizeHint()的大小顯示。

在Qt3的佈局中,插入佔用多行或多列的方法為addMultiCellWidget()和addMultiCellLayout(),在Qt4中廢棄了這兩種方法,而是統一成addWidget()和addLayout()兩種方法。