pyqt5-布局控件


 

 

繼承圖:

 

 

在布局中添加控件用addWidght(),添加布局用addLayout()

 

QBoxLayout:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QBoxLayout
from PyQt5.QtCore import QSize

class Label(QLabel):
    def minimumSizeHint(self):  #建議的最小尺寸函數
        return QSize(50,50)

class Demo(QWidget):

    def __init__(self):
        super(Demo, self).__init__()
        self.resize(300,300)
        self.label1 = Label('標簽1')
        self.label2 = QLabel('標簽2')
        self.label3 = QLabel('標簽3')
        self.label1.setStyleSheet('background-color: rgb(255, 0, 0)')
        self.label2.setStyleSheet('background-color: rgb(0, 255, 0)')
        self.label3.setStyleSheet('background-color: rgb(0, 0, 255)')

        layout=QBoxLayout(QBoxLayout.RightToLeft)  #創建一個盒子布局
        #參數1  布局方向:  --必須有
            #QBoxLayout.TopToBottom=2   從上往下
            #QBoxLayout.BottomToTop=3  從下往上
            #QBoxLayout.LeftToRight=0   從左往右
            #QBoxLayout.RightToLeft=1  從右往左

        self.setLayout(layout)  #給self設置布局管理器

        layout.addWidget(self.label1)  #給布局管理器添加控件
        # 這是QLayout的指令

        #layout.addSpacing(50)  #添加間距-間距
        #參數   像素

        layout.addWidget(self.label2)
        layout.addWidget(self.label3)



        layout.setSpacing(2)  #設置內邊距---控件之間的距離
        #這是QLayout的指令

        layout.setContentsMargins(20,30,40,50)  #設置外邊距--控件到窗口邊框的距離
        # 這是QLayout的指令
        # 參數1 左邊距離
        # 參數2 上邊距離
        # 參數3 右邊距離
        # 參數4 下邊距離

        self.label4 = QLabel('標簽4')
        self.label4.setStyleSheet('background-color: yellow')

        layout.replaceWidget(self.label2,self.label4)   #替換控件
        #把self.label2替換成self.label4
        #注意:被替換掉的控件不在受布局管理器的控制,要把它隱藏或刪除或脫離或添加到別的布局管理器中
        # 這是QLayout的指令

        #self.label2.hide()  #隱藏控件
        self.label2.setParent(None)  #脫離父對象

        #布局的嵌套:
        self.label5 = QLabel('標簽5')
        self.label5.setStyleSheet('background-color: rgb(255, 255, 0)')
        self.label6 = QLabel('標簽6')
        self.label6.setStyleSheet('background-color: rgb(255, 0, 255)')
        self.label7 = QLabel('標簽7')
        self.label7.setStyleSheet('background-color: rgb(0, 255, 255)')
        layout1=QBoxLayout(QBoxLayout.BottomToTop)
        layout1.addWidget(self.label5)
        layout1.addWidget(self.label6)
        layout1.addWidget(self.label7)

        #layout.addLayout(layout1)  #添加布局管理器
        # 這是QLayout的指令

        layout.setDirection(QBoxLayout.LeftToRight)  # 設置方向
        # direction()  返回方向

        layout.insertWidget(3,self.label2)    #插入控件
        #參數1   位置序號

        layout.insertLayout(2,layout1)   #插入布局
        # 參數1   位置序號

        #layout.removeWidget(self.label1)  #從布局中移除控件
        #不是刪除控件

        layout.insertSpacing(4,50)  #插入空白-間距
        #參數1  位置索引--不包括已有空白
        #參數2  空白像素


        layout.setEnabled(True)  #是否可用
        #默認 True

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

 

 

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QBoxLayout

class Demo(QWidget):

    def __init__(self):
        super(Demo, self).__init__()
        self.resize(300,300)
        self.label1 = QLabel('標簽1')
        self.label2 = QLabel('標簽2')
        self.label3 = QLabel('標簽3')
        self.label1.setStyleSheet('background-color: rgb(255, 0, 0)')
        self.label2.setStyleSheet('background-color: rgb(0, 255, 0)')
        self.label3.setStyleSheet('background-color: rgb(0, 0, 255)')

        layout=QBoxLayout(QBoxLayout.RightToLeft)
        self.setLayout(layout)
        # layout.addWidget(self.label1,1)
        # layout.addWidget(self.label2,2)
        # layout.addWidget(self.label3,3)
        #參數2 伸縮因子:就是占用的份數(倍數);總的分成6份,label1占1份,label2占2份,label3占3份
        # 0  不伸縮


        # layout.addWidget(self.label1, 1)
        # #layout.addStretch(2)  #添加空白伸縮因子
        # #注意:這個空白伸縮可以壓縮成0;只有足夠大時才有效
        # layout.addWidget(self.label2, 2)
        # layout.addWidget(self.label3, 3)
        #
        # layout.insertStretch(1,2)  #插入空白伸縮因子
        # #參數1 位置序號   參數2 伸縮份數

        layout.addWidget(self.label1)
        layout.addStretch()
        layout.addWidget(self.label2)
        layout.addStretch()
        layout.addWidget(self.label3)
        #此時的伸縮因子都是0,控件不在伸縮,會把多余部分都給空白

        layout.setStretchFactor(self.label2,1)  #設置伸縮因子
        #參數1   可以是控件   可以是子布局

        layout.setStretchFactor(self.label1, 1)





if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

 

 

 

垂直布局QVBoxLayout

需要導入  from PyQt5.QtWidgets import QVBoxLayout

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout
from PyQt5.QtCore import Qt

class Demo(QWidget):

    def __init__(self):
        super(Demo, self).__init__()
        self.label1 = QLabel('標簽1')
        self.label2 = QLabel('標簽2')
        self.label3 = QLabel('標簽3')
        self.label1.setStyleSheet('background-color: rgb(255, 0, 0)')
        self.label2.setStyleSheet('background-color: rgb(0, 255, 0)')
        self.label3.setStyleSheet('background-color: rgb(0, 0, 255)')
        self.v_layout = QVBoxLayout()  #實例化一個垂直布局管理器
        self.v_layout.addWidget(self.label1)  #將控件添加到垂直布局中,最先添加的出現在最上方
        self.v_layout.addWidget(self.label2)
        self.v_layout.addWidget(self.label3)

        self.v_layout.setContentsMargins(20,30,40,50) #設置外邊距--到窗口邊框的距離
        #參數1 左邊距離
        #參數2 上邊距離
        #參數3 右邊距離
        #參數4 下邊距離

        self.v_layout.setSpacing(20)  #設置內邊距---各控件之間的距離


        self.setLayout(self.v_layout)  #將self.v_layout設為整個窗口的最終布局方式
        #給self設置布局管理器;給布局管理器設置父對象

        


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

 

 

 

 

 

 

水平布局QHBoxLayout

需要  from PyQt5.QtWidgets import QHBoxLayout

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QHBoxLayout
from PyQt5.QtCore import Qt

class Demo(QWidget):

def __init__(self):
super(Demo, self).__init__()
self.label1 = QLabel('標簽1')
self.label2 = QLabel('標簽2')
self.label3 = QLabel('標簽3')
self.label1.setStyleSheet('">self.label2.setStyleSheet('">self.label3.setStyleSheet('">self.v_layout = QHBoxLayout() #實例化一個垂直布局管理器
self.v_layout.addWidget(self.label1) #將控件添加到垂直布局中,最先添加的出現在最上方
self.v_layout.addWidget(self.label2)
self.v_layout.addWidget(self.label3)

self.v_layout.setContentsMargins(20,30,40,50) #設置外邊距--到窗口邊框的距離
#參數1 左邊距離
#參數2 上邊距離
#參數3 右邊距離
#參數4 下邊距離

self.v_layout.setSpacing(20) #設置內邊距---各控件之間的距離


self.setLayout(self.v_layout) #將self.v_layout設為整個窗口的最終布局方式
#給self設置布局管理器;給布局管理器設置父對象

self.setLayoutDirection(Qt.RightToLeft) #設置布局方向
#Qt.RightToLeft 從右到左
#Qt.LeftToRight 從左到右
#Qt.LayoutDirectionAuto 自由布局

if __name__ == '__main__':
app = QApplication(sys.argv)
demo = Demo()
demo.show()
sys.exit(app.exec_())

效果圖:

 

 

 

 

 

表單布局QFormLayout

 兩列多行 分布的

 

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit,QFormLayout,QSpinBox,QPushButton,QRadioButton,QHBoxLayout
from PyQt5.QtCore import Qt

class Demo(QWidget):

    def __init__(self):
        super(Demo, self).__init__()
        self.resize(300,400)
        label1 = QLabel('姓名:')
        label2 = QLabel('年齡:')
        le=QLineEdit()
        sb=QSpinBox()
        btn=QPushButton('提交')
        label2.destroyed.connect(lambda :print('標簽2被銷毀'))
        sb.destroyed.connect(lambda :print('sb被銷毀'))

        fl=QFormLayout()  #創建表單控件
        self.setLayout(fl)

        fl.addRow(label1,le)  #添加行--方式一
        #也可以添加布局

        fl.addRow(label2,sb)

        # fl.addRow('姓名(&n):',le)  ##添加行--方式二--可以自動綁定小伙伴
        # fl.addRow('年齡(&g):',sb)

        fl.addRow(btn)  #只有一個控件時,添加到第1列

        rb1 = QRadioButton('')
        rb2 = QRadioButton('')
        h_layout=QHBoxLayout()
        h_layout.addWidget(rb1)
        h_layout.addWidget(rb2)
        label3 = QLabel('性別:')
        fl.insertRow(2,label3,h_layout)  #插入行
        #參數1  位置序號
        #如果序號越界就加在最后面

        s=fl.rowCount()  #返回總行數
        s=fl.getWidgetPosition(le)  #返回指定控件的位置信息
        #(0, 1)   第0行 第1列
        s=fl.getLayoutPosition(h_layout)  #返回指定布局的位置信息
        #(2, 1)

        s=fl.getWidgetPosition(rb2)
        #(-1, 1)   第一元素值返回-1 表示控件不在這個布局中

        #fl.removeRow(1)  #把指定行移出布局(釋放移除的控件)
        #參數 要移除的行序號

        #r=fl.takeRow(1)  #把指定行移出布局(不釋放移除的控件)
        #要把移出的控件隱藏或脫離或添加到其它布局

        #label2.hide()
        #sb.hide()

        #s=r.labelItem.widget()  #返回被移出的0列的控件
        #s = r.fieldItem.widget()  # 返回被移出的1列的控件

        #fl.removeRow(label2)  # 把指定行移出布局(釋放移除的控件)
        #把label2所在行的控件移除

        #fl.removeWidget(label2)  #移出指定的一個控件(不釋放)

        le5=QLineEdit()
        fl.addRow('班級:',le5)

        s=fl.labelForField(le5)  #根據第一列的控件返回第0列控件
        s.setText('學校:'*5)

        fl.setRowWrapPolicy(QFormLayout.WrapLongRows)  #設置行策略
        #QFormLayout.WrapLongRows   標簽要顯示完整,如果字段列空間不足就移到下一行----沒有效果????
        #QFormLayout.WrapAllRows    標簽列和字段列分成兩行顯示
        #QFormLayout.DontWrapRows   字段列總是放在標簽列旁邊

        s=fl.formAlignment()  #返回表單的對齊方式
        if s==Qt.AlignLeft | Qt.AlignTop :
            print('左頂部對齊')
        fl.setFormAlignment(Qt.AlignLeft | Qt.AlignBottom)  #設置表單對齊方式
        #對齊看 https://www.cnblogs.com/liming19680104/p/10357263.html

        fl.setLabelAlignment(Qt.AlignRight)  #設置第0列標簽的對齊方式

        fl.setVerticalSpacing(20)  #設置垂直方向兩行間的間距
        fl.setHorizontalSpacing(20)  #設置水平方向兩列間的間距

        fl.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)  #第1列字段列水平增長策略
        #QFormLayout.FieldsStayAtSizeHint=0   保持建議大小,到了建議長度后不在增長
        #QFormLayout.ExpandingFieldsGrow=1   只有大小策略設置了Expanding或MinimumExpanding的控件才會被盡可能拉伸占滿布局,否則同FieldsStayAtSizeHint
        #QFormLayout.AllNonFixedFieldsGrow=2  所有字段欄都可以被拉伸來占滿布局。這是大多數樣式的默認策略


        print(s)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

 

 

 

 

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit,QFormLayout,QSpinBox,QPushButton,QRadioButton,QHBoxLayout

class Demo(QWidget):

    def __init__(self):
        super(Demo, self).__init__()

        label1 = QLabel('姓名:')
        label2 = QLabel('年齡:')
        le=QLineEdit()
        sb=QSpinBox()
        btn=QPushButton('提交')

        fl=QFormLayout()  #創建表單控件
        self.setLayout(fl)

        rb1 = QRadioButton('')
        rb2 = QRadioButton('')
        h_layout=QHBoxLayout()
        h_layout.addWidget(rb1)
        h_layout.addWidget(rb2)
        label3 = QLabel('性別:')

        fl.setWidget(0,QFormLayout.LabelRole,label1)  #設置控件--添加控件
        #參數1 行序號
        #參數2 控件角色---決定是0列還是1列:
            #QFormLayout.LabelRole   第0列
            #QFormLayout.FieldRole   第1列
        #參數3 控件
        #注意:如果位置已經存在指令就無效

        fl.setWidget(0, QFormLayout.FieldRole, le)
        fl.setLayout(1, QFormLayout.FieldRole,h_layout)  #設置布局--添加布局


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

 

 

 

 

網格布局QGridLayout

當使用該布局管理器的時候,你可以把整個窗體想象成帶有格子的,然后只要把各個控件放在相應的格子就好了

需要  from PyQt5.QtWidgets import QGridLayout

 

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit,QSpinBox,QPushButton,QGridLayout,QVBoxLayout
from PyQt5.QtCore import Qt

class Demo(QWidget):

    def __init__(self):
        super(Demo, self).__init__()
        self.resize(300,400)
        label1 = QLabel('標簽1')
        label11 = QLabel('標簽11')
        label111 = QLabel('標簽111')
        label2 = QLabel('標簽2')
        label3 = QLabel('標簽3')
        label4 = QLabel('標簽4')
        label5 = QLabel('標簽5')
        label1.setStyleSheet('background-color: rgb(255,0,0)')
        label11.setStyleSheet('background-color: rgb(255,100,0)')
        label111.setStyleSheet('background-color: rgb(255,0,255)')
        label2.setStyleSheet('background-color: rgb(0, 251, 0)')
        label3.setStyleSheet('background-color: rgb(0, 0, 255)')
        label4.setStyleSheet('background-color: rgb(0, 255, 255)')
        label5.setStyleSheet('background-color: rgb(100, 0, 255)')
        le1=QLineEdit()
        sb2=QSpinBox()
        btn=QPushButton('提交')

        gl=QGridLayout()
        self.setLayout(gl)

        gl.addWidget(label1,0,0)  #添加控件
        #參數2  行序號      參數3 列序號

        gl.addWidget(label11, 0, 1)
        gl.addWidget(label111, 0, 2)
        gl.addWidget(le1,1,0,1,2)  #添加控件--帶合並功能
        #參數3 占用n行    參數4 占用n列

        v=QVBoxLayout()
        v.addWidget(label3)
        v.addWidget(label4)
        v.addWidget(label5)
        gl.addLayout(v,2,0)    #添加布局

        s=gl.getItemPosition(3)  #返回指定項目的位置信息
        #參數 索引序號;
        #(1, 0, 1, 2)    表示在第一行第0列,占用1行 占用2列

        s=gl.itemAtPosition(1,0).widget()  #返回指定位置的控件

        #gl.setColumnMinimumWidth(0,100)  #設置某列最小寬度
        #gl.setRowMinimumHeight(0, 50)  # 設置某行最小高度

        #gl.setColumnStretch(0,1)  #設置某列的拉伸系數
        #參數1  列序號   參數1 拉伸系數-倍數

        gl.setRowStretch(0, 1)  # 設置某行的拉伸系數
        #參數1  行序號   參數1 拉伸系數-倍數

        s=gl.spacing()  #返回控件之間的間距
        #如果水平間距=垂直間距 就返回間距值
        #如果水平間距不等於垂直間距 就返回-1

        s=gl.horizontalSpacing()  #返回水平間距

        s = gl.verticalSpacing()  # 返回垂直間距

        #gl.setHorizontalSpacing(30)  #設置控件之間的水平間距
        #gl.setVerticalSpacing(30)    #設置控件之間的垂直間距
        gl.setSpacing(30)  #設置控件之間的垂直間距和水平間距

        s=gl.rowCount()   #返回總行數
        s = gl.columnCount()  # 返回總列數






        #print(s)




if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    gl=demo.layout()  #返回布局控件
    print(gl)

    s = gl.cellRect(0, 1)  # 返回指定區域的大小
    # 參數1  行序號   參數1  列序號--返回0行1列的區域大小
    #注意:必須在主窗體顯示之后
    #PyQt5.QtCore.QRect(114, 11, 72, 202)
    
    print(s)
    sys.exit(app.exec_())

 

堆疊布局:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QStackedLayout,QPushButton,QHBoxLayout

class Demo(QWidget):

    def __init__(self):
        super(Demo, self).__init__()
        self.resize(300,400)
        label1 = QLabel('標簽1')
        label2 = QLabel('標簽2')
        label3 = QLabel('標簽3')
        label4 = QLabel('標簽4')
        label1.setStyleSheet('background-color: rgb(255,0,0)')
        label2.setStyleSheet('background-color: rgb(0, 251, 0)')
        label3.setStyleSheet('background-color: rgb(0, 0, 255)')
        label4.setStyleSheet('background-color: rgb(0, 255, 255)')
        btn=QPushButton('按鈕')
        bl=QHBoxLayout()

        def AA(self):
            sl.removeWidget(label4)  #從布局中移除控件
            #不是刪除控件
            pass
        btn.clicked.connect(AA)



        #********堆疊布局**********

        sl=QStackedLayout()
        self.setLayout(bl)
        bl.addLayout(sl)
        bl.addWidget(btn)

        s=sl.addWidget(label1)  #添加布局
        #返回值 位置索引號
        s=sl.addWidget(label2)
        sl.addWidget(label3)

        s=sl.currentIndex()   #返回當前顯示控件的位置索引號

        s=sl.insertWidget(0,label4)  #插入控件
        #參數1 位置索引號;如果越界,就是現有最大索引號+1

        s=sl.widget(0).text()
        #widget(0)   返回指定索引的控件

        sl.setCurrentIndex(2)  #顯示指定索引的控件
        sl.setCurrentWidget(label3)   #顯示指定的控件
        s=sl.count()  #返回所有控件的總數

        sl.setStackingMode(QStackedLayout.StackOne)   #設置控件的顯示模式
        #QStackedLayout.StackAll   所有控件都可見
        #QStackedLayout.StackOne  只有顯示控件可見  其它隱藏-----默認


        #信號:
        sl.currentChanged.connect(self.BB)  #顯示控件發生變化時發出信號
        #會向槽函數傳遞一個參數---當前顯示控件的序號

        sl.widgetRemoved.connect(self.CC)  #控件被移除時
        # 會向槽函數傳遞一個參數---刪除控件的序號

    def BB(self,i):
        print('顯示控件改變了',i)
    def CC(self,i):
        print('控件被移除',i)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

 

補充--尺寸策略: 

 

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel,QVBoxLayout,QSizePolicy
from PyQt5.QtCore import QSize

class Label(QLabel):
    def minimumSizeHint(self):  #最小尺寸函數
        return QSize(50,50)
    def sizeHint(self):       #建議尺寸函數
        return QSize(200,150)  #單位 像素

class Demo(QWidget):

    def __init__(self):
        super(Demo, self).__init__()
        self.resize(300,400)
        label1 = Label('標簽1')
        label2 = QLabel('標簽2')
        label3 = QLabel('標簽3')
        label4 = QLabel('標簽4')
        label1.setStyleSheet('background-color: rgb(255,0,0)')
        label2.setStyleSheet('background-color: rgb(0, 251, 0)')
        label3.setStyleSheet('background-color: rgb(0, 0, 255)')
        label4.setStyleSheet('background-color: rgb(0, 255, 255)')
        bl=QVBoxLayout()

        #********尺寸策略**********

        self.setLayout(bl)
        bl.addWidget(label1)
        bl.addWidget(label2)
        bl.addWidget(label3)

        label1.setMinimumSize(100,100)  #設置最小尺寸--修改minimumSizeHint函數值
        #label1.setMaximumSize(200,200)  #設置最大尺寸

        label1.setSizePolicy(QSizePolicy.Preferred,QSizePolicy.Preferred)  #設置控件的尺寸策略--方式一
        #QSizePolicy.Fixed    固定的---不能改變---尺寸保持sizeHint函數的建議尺寸
        #QSizePolicy.Minimum  可以拉伸,但是不能小於sizeHint函數的建議尺寸--sizeHint的尺寸是最小值
        #QSizePolicy.Maximum   可以拉伸,但是不能大於sizeHint函數的建議尺寸--sizeHint的尺寸是最大值
        #QSizePolicy.Preferred   可以拉伸,但是不能小於minimumSizeHint最小尺寸
        #QSizePolicy.Expanding    可以拉伸,拉伸時使本控件盡量占據空間,縮小時不能小於minimumSizeHint最小尺寸
        #QSizePolicy.MinimumExpanding  可以拉伸,拉伸時使本控件盡量占據空間,縮小時不能小於sizeHint的尺寸
        #QSizePolicy.Ignored  忽略minimumSizeHint尺寸,忽略sizeHint尺寸,縮小時可以為0
        #參數1 水平方向的尺寸策略  參數2 垂直方向的尺寸策略

        sp=QSizePolicy(QSizePolicy.Preferred,QSizePolicy.Preferred)  #創建尺寸策略對象
        sp.setRetainSizeWhenHidden(True)  # 控件隱藏時是否保留尺寸
        #一定要放在setSizePolicy之前
        label1.setSizePolicy(sp)  #設置控件的尺寸策略--方式二


        #label1.hide()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

 

 

 

天子驕龍 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM