一个PyQt的应用通常需要至少一个窗口来完成,在一个窗口中往往需要多个多种控件相配合才能达到想要的结果,如何将这些控件合理有效的联系在一起,这就是布局所要解决的问题。
首先我们先放出完整代码,虽然我们逐步解释
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel
app = QApplication(sys.argv)
widgetHello = QWidget()
LabHello = QLabel(widgetHello)
LabHello.setText("Hello World")
widgetHello.show()
sys.exit(app.exec_())
在上述代码中
app = QApplication(sys.argv)
上述过程用到的是QtWidgets模块中的QApplication类,这个类是用来管理GUI应用程序的控制流程和设置的一个类。这里传入的参数可以是sys.argv
也可以是[]
,在这个例子中我们使用的是前者,后面我们为了方便将大量使用后者。
widgetHello = QWidget()
随后实例化QWidget类的对象widgetHello,这里的widgetHello就是我们的窗体对象
LabHello = QLabel(widgetHello) #创建标签,父容器为widgetHello
LabHello.setText("Hello World") #设置标签文字
这里将widgetHello传递给QLabel的构造函数,使得widgetHello作为LabHello的父容器,目的是为了能在窗体widgetHello上显示标签LabHello。
然后我们调用setText方法设置标签的文字。
widgetHello.show()
sys.exit(app.exec_())
最后这两行就是对框的显示
运行结果如下:
上述创建窗口的方式虽然也同样可靠,但是总会有些繁琐,为了增加程序的可读性,我们一般会采用类的方式来创建窗口。
在不使用布局控件的情况下可以使用控件自带的move方法来进行布局,但这种布局方式较为混乱,十分不推荐。但这里还是给出了相关的代码,move中的参数对应的是控件在窗口上的相对位置。这个相对位置一般会被称为(x, y),但坐标轴与我们在数学中常用的并不相同,坐标轴如下:
窗口的水平方向是X,竖直方向是Y
import sys
from PyQt5.QtWidgets import *
class Window(QWidget):
def __init__(self):
super().__init__()
self.resize(200, 200)
label1 = QLabel("label 1", self)
label2 = QLabel("label 2", self)
label1.move(-20, 0)
label2.move(50, 100)
if __name__ == "__main__":
app = QApplication([])
window = Window()
window.show()
sys.exit(app.exec())
在上述代码中展示了两个label在move的作用下移动到了不同位置的效果
由于label1的x坐标是负值,所以这里只能显示出他其中一部分。这里是故意为之,为的就是测试坐标值为负值的情况。
值得庆幸的是,PyQt中有专门用于布局的控件,首先我们来看垂直布局
import sys
from PyQt5.QtWidgets import *
class Window(QWidget):
def __init__(self):
super().__init__()
username = QLabel("Username:")
password = QLabel("Password:")
v_layout = QVBoxLayout()
v_layout.addWidget(username)
v_layout.addWidget(password)
self.setLayout(v_layout)
if __name__ == "__main__":
app =QApplication([])
window = Window()
window.show()
sys.exit(app.exec())
在代码中我们创建了一个布局的实例化对象v_layout,使用addWidget将两个标签项(username和password)添加到布局中,然后使用self.setLayout来设置窗口的布局,运行结果如下
水平布局与垂直布局类似,不过我们这里引入了一个新的控件QLineEdit,他是一个用于输入文本的控件。
import sys
from PyQt5.QtWidgets import *
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
username_label = QLabel("Username:")
username_line = QLineEdit()
h_layout = QHBoxLayout()
h_layout.addWidget(username_label)
h_layout.addWidget(username_line)
self.setLayout(h_layout)
if __name__ == "__main__":
app =QApplication([])
window = Window()
window.show()
sys.exit(app.exec())
运行效果如下:
表单布局是以表单的形式的布局,我们可以将控件以表单的形式传入表单布局。
import sys
from PyQt5.QtWidgets import *
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
username_label = QLabel("Username:")
password_label = QLabel("Password:")
username_edit = QLineEdit()
password_edit = QLineEdit()
f_layout = QFormLayout()
f_layout.addRow(username_label, username_edit)
f_layout.addRow(password_label, password_edit)
self.setLayout(f_layout)
if __name__ == "__main__":
app = QApplication([])
window = Window()
window.show()
sys.exit(app.exec())
运行结果如下:
网格布局的展示形式与表单布局相似,但是在传入空间时需要传入控件在网格布局中的位置。
import sys
from PyQt5.QtWidgets import *
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
username_label = QLabel("Username:")
password_label = QLabel("Password:")
username_line = QLineEdit()
password_line = QLineEdit()
g_layout = QGridLayout()
g_layout.addWidget(username_label, 0, 0)
g_layout.addWidget(username_line, 0, 1)
g_layout.addWidget(password_label, 1, 0)
g_layout.addWidget(password_line, 1, 1)
self.setLayout(g_layout)
if __name__ == "__main__":
app = QApplication([])
window = Window()
window.show()
sys.exit(app.exec())
运行结果如下:
在布局中可以使用addLayout
再次添加布局,这就实现了布局的嵌套。
import sys
from PyQt5.QtWidgets import *
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
username_label = QLabel("Username:")
password_label = QLabel("Password:")
username_line = QLineEdit()
password_line = QLineEdit()
v_layout = QVBoxLayout()
h1_layout = QHBoxLayout()
h2_layout = QHBoxLayout()
h1_layout.addWidget(username_label)
h1_layout.addWidget(username_line)
h2_layout.addWidget(password_label)
h2_layout.addWidget(password_line)
v_layout.addLayout(h1_layout)
v_layout.addLayout(h2_layout)
self.setLayout(v_layout)
if __name__ == "__main__":
app = QApplication([])
window = Window()
window.show()
sys.exit(app.exec())
运行结果如下
从中我们可以看到实现同一个效果实际上是有不同的方式的。