PyQt5 - QWidgets部件入门教程

来源:互联网 发布:淘宝搞笑收件人名字 编辑:程序博客网 时间:2024/05/21 21:44

  • 前述
  • 主程序视窗
  • 案例
    • 创建一个视窗
    • 子部件
    • 使用布局
    • 嵌套布局
      • 设置Model
  • 相关类
  • 相关方法

前述

窗口部件是用Qt创建GUI的基础模块,每个GUI组件(例如按钮、标签、文本编辑器)都是在用户界面窗口内某处放置的一个窗口部件,或作为独立窗口显示。每个部件类型都由QWidget子类提供(QWidget是QObject子类)。QWidget不是一个抽象类,它可以作为其他窗口部件的容器使用,也可以被子类化来创建新的自定义部件,QWidget经常用于在其他被放置的QWidgets内创建一个窗口
与QObjects相同,QWidgets可以用父对象创建来表明所属权,确保当对象不再使用时删除,这些部件的父-子关系有深层含义:每个子部件在屏幕内的显示区域被他的父部件占有,这意味着当你删除窗口部件时,所有它包含的子部件都被删除。


主程序视窗

与cpp主程序不同,在python下,一个典型的主程序结构如下:

from PyQt5.QtWidgets import *import sys# 模块导入class MainWindow(QMainWindow):# 构建主程序类,继承自QMainWindow    def __init__(self):    # 重写初始化方法        super(MainWindow, self).__init__()    #  自定义方法if __name__ == '__main__':    app = QApplication(sys.argv)    # 关于QApplication详见下方相关类    mw = MainWindow()    # 实例化类    mw.show()    app.exec_()    # 执行app,exec_()是PyQt方法

案例

创建一个视窗

from PyQt5.QtWidgets import *import sysclass Window(QWidget):    def __init__(self):        super(Window, self).__init__()        self.resize(320, 240)        # 重定义视窗尺寸        self.setWindowTitle('Top-level widget')        # 设置视窗标题app = QApplication(sys.argv)win = Window()win.show()app.exec_()

Create a Window

这个案例使用了QWidget类继承,若为主视窗则使用QMainWindow(见上一个案例)。

子部件

from PyQt5.QtWidgets import *import sysclass Window(QWidget):    def __init__(self):        super(Window, self).__init__()        self.resize(320, 240)        self.setWindowTitle('Top-level widget')        self.button = QPushButton('Press Me', self)        self.button.move(100, 100)app = QApplication(sys.argv)win = Window()win.show()app.exec_()

Child Widget

这个按钮现在是视窗的子部件,若视窗删除则都删除。注意:关闭或隐藏视窗不会关闭按钮,它只有当视窗退出时才会关闭。

使用布局

相比指定位置和明确定义尺寸而言,子部件更通常使用layout对象在视窗内进行排列。这个案例中,我们将构建一个标签和行编辑,并进行平行排列。

from PyQt5.QtWidgets import *import sysclass Window(QWidget):    def __init__(self):        super(Window, self).__init__()        self.setWindowTitle('Top-level widget')        self.label = QLabel('WindowLayout', self)        self.lineEdit = QLineEdit()        self.hBox = QHBoxLayout()        self.hBox.addWidget(self.label)        self.hBox.addWidget(self.lineEdit)        self.setLayout(self.hBox)app = QApplication(sys.argv)win = Window()win.show()app.exec_()

Layout

我们构建的layout对象管理窗口内组建的位置和大小,layout对象内插入对象使用addWidget()函数,视窗调用布局使用setLayout()函数。
在上一个案例中,窗口内的每个部件的所属关系并不能立即明确,我们构建无父对象的部件和布局后,可以看到一个空窗口和两个独立的窗口部件(label和line edit)。当我们告知layout来管理label和line edit,并设置窗口布局时(即setLayout后),两个部件和布局本身就变成了视窗的子类。

嵌套布局

像组件可以包含其他组件,布局也可以用来提供不同层级的部件组,本案例中,我们想在窗口顶部显示一个长边的行编辑标签,在一个表格下显示查询结果。我们通过创建两个layout实现该案例,查询layout是一个QHBoxLayout,包含平行的QLabel和QLineEdit部件;主layout是一个QVBoxLayout,包含查询layout和一个QTableView垂直排列。

from PyQt5.QtWidgets import *import sysclass Window(QWidget):    def __init__(self):        super(Window, self).__init__()        self.setWindowTitle('Query widget')        self.queryLabel = QLabel('Query', self)        self.queryEdit = QLineEdit()        self.queryView = QTableView()        self.queryLayout = QHBoxLayout()        self.queryLayout.addWidget(self.queryLabel)        self.queryLayout.addWidget(self.queryEdit)        self.mainLayout = QVBoxLayout()        self.mainLayout.addLayout(self.queryLayout)        self.mainLayout.addWidget(self.queryView)        self.setLayout(self.mainLayout)app = QApplication(sys.argv)win = Window()win.show()app.exec_()

Nested Layout

注意我们调用主布局的addLayout()函数,用来在结果视图表上插入查询布局。
除QHBoxLayout和QVBoxLayout外,Qt还提供QGridLayout和QFormLayout类来辅助更复杂的用户界面。

设置Model

在上面代码中,因为我们想专注于布局的使用,并没有展示表格的数据从哪来,下面我们看看如何设置model保存一些项的对应行,及每个项设置包含两列数据。

  • 构建QueryModel类
from PyQt5.QtGui import *class QueryModel(QStandardItemModel):    def __init__(self):        super(QueryModel, self).__init__()        self.queryViewHeader = ['Name', 'Office']        self.setHorizontalHeaderLabels(self.queryViewHeader)        data = {            "Verne Nilsen": "123",            "Carlos Tang": "77",            "Bronwyn Hawcroft": "119",            "Alessandro Hanssen": "32",            "Andrew John Bakken": "54",            "Vanessa Weatherley": "85",            "Rebecca Dickens": "17",            "David Bradley": "42",            "Knut Walters": "25",            "Andrea Jones": "34"        }        for key, value in data.items():            items = []            for text in [key, value]:                items.append(QStandardItem(text))            self.appendRow(items)

考虑到QString和Python String的特殊性,在构建该类时,我选择使用字典作为数据存储类型,在遍历时将字典的key和value转化为Qt中类似QStringList的遍历。字典在这里面有的问题就是无序性,所以每次执行程序时,Table中的次序都不同。
下面在Window类中添加一些方法:

class Window(QWidget):    def __init__(self):        super(Window, self).__init__()        self.setWindowTitle('Query widget')        self.queryLabel = QLabel('Query', self)        self.queryEdit = QLineEdit()        self.queryView = QTableView()        self.queryModel = QueryModel()        self.queryView.setModel(self.queryModel)        self.queryView.verticalHeader().hide()        self.queryView.horizontalHeader().setStretchLastSection(True)        self.queryLayout = QHBoxLayout()        self.queryLayout.addWidget(self.queryLabel)        self.queryLayout.addWidget(self.queryEdit)        self.mainLayout = QVBoxLayout()        self.mainLayout.addLayout(self.queryLayout)        self.mainLayout.addWidget(self.queryView)        self.setLayout(self.mainLayout)

那么最终的运行结果

这里写图片描述

  • 下面我提供一种解决列表无序的方法,方法可能很繁琐,仅供参考,希望大家可以提出宝贵意见
class QueryModel(QStandardItemModel):    def __init__(self):        super(QueryModel, self).__init__()        self.queryViewHeader = ['Name', 'Office']        self.setHorizontalHeaderLabels(self.queryViewHeader)        data = [            "Verne Nilsen", "123",            "Carlos Tang", "77",            "Bronwyn Hawcroft", "119",            "Alessandro Hanssen", "32",            "Andrew John Bakken", "54",            "Vanessa Weatherley", "85",            "Rebecca Dickens", "17",            "David Bradley", "42",            "Knut Walters", "25",            "Andrea Jones", "34"        ]        # 将数据变更为列表        for i in range(len(data)):            items = []            if i % 2 == 0:                for text in [data[i], data[i+1]]:                    items.append(QStandardItem(text))                self.appendRow(items)        # 因为数据只有两列,所以根据奇偶项进行遍历,形成QList导入QStandardItem

相关类

  • QMainWindow
  • QApplication()
  • QPushButton
  • QLineEdit
  • QHBoxLayout
  • QVBoxLayout
  • QTableView
  • QStandardItemModel

相关方法

  • resize()
  • setWindowTitle()
  • move()
  • addWidget()
  • addLayout()
  • setLayout()
  • setModel()
  • setHorizontalHeaderLabels()
  • verticalHeader()
  • horizontalHeader()
  • setStretchLastSection
  • appendRow()

1 0
原创粉丝点击