1 主窗口基础(QMainWindow)
QWidget 和 QMainWindow 在基本功能上无异,区别如下:
- 只有 QMainWindow 可使用状态栏、菜单栏和工具栏;
- 只有 QWidget 可以使用 QGridLayout、QHBoxLayout、QVBoxLayout 等布局管理器;
可通过在 QMainWindow 窗体中嵌入 QWidget 组件实现上述所有功能
1.1 窗口基本设置
窗口元素 |
|
python import sys from PyQt6.QtWidgets import (QWidget, QApplication) from PyQt6.QtWidgets import QToolTip from PyQt6.QtGui import QIcon, QFont class QWindow(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): # 1. 标题/图标 # 窗口标题命名 self.setWindowTitle('Name') # 窗口图标设置 self.setWindowIcon(QIcon('exit.png')) # 2. 尺寸/位置 # 窗体尺寸设置 self.setGeometry(300, 300, 300, 100) # 位置和大小 # 设置窗口位置、尺寸,位置可再更改 # self.setGeometry(左侧位置, 顶部位置, 宽度, 高度) self.resize(300, 300) # 仅大小 # 窗体位置居中 fg = self.frameGeometry() # 创建一个矩形框架,返回窗口对象 # 计算屏幕属性中的分辨率的中心坐标(屏幕) cp = self.screen().availableGeometry().center() # 移动矩形框架中心到cp坐标处(内存) fg.moveCenter(cp) # 移动部件窗口中心到cp坐标处(屏幕) self.move(fg.topLeft()) # 3. 窗体气泡提示框 # 应用程序内所有气泡提示框字体/字号设置 QToolTip.setFont(QFont('Calibri', 10)) # 注意部分字体可能会打不出中文 # 窗口设置气泡提示框 self.setToolTip('This is a <b>QMainWindow</b> widget') # 内部使用富文本 # 窗口最大化显示 self.showMaximized() # 窗口生成(从内存转到显存) self.show() def main(): app = QApplication(sys.argv) qw = QWindow() sys.exit(app.exec()) if __name__ == '__main__': main() |
1.2 窗口状态栏(QStatusBar)
窗口状态栏 — QStatusBar |
|
python import sys from PyQt6.QtWidgets import (QMainWindow, QApplication) class QWindow(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self.statusBar().showMessage('Ready') # 创建窗口状态栏并设定信息 # 该状态显示暂时的,一旦鼠标移动到菜单上,该信息消失 self.show() def main(): app = QApplication(sys.argv) qw = QWindow() sys.exit(app.exec()) if __name__ == '__main__': main() |
|
DLC |
|
[QStatusBar Class |
Qt Widgets 6.3.2](https://doc.qt.io/qt-6/qstatusbar.html) |
1.3 窗口菜单栏(QMenuBar)
1.3.1 普通菜单(QAction)
普通菜单 — QAction |
|
python import sys from PyQt6.QtWidgets import (QMainWindow, QApplication) from PyQt6.QtGui import QIcon # 菜单图标 from PyQt6.QtGui import QAction # 行为 class QWindow(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): # 创建窗口状态栏并设定信息 self.statusBar().showMessage('Ready') # 不设置的话,行为.setStatusTip 不能生效。故也可省略 .showMessage 参数 # 创建行为(退出) # 创建行为,并设置退出行为的图标、文字 act_exit = QAction(QIcon('exit.png'), '退出(&E)', self) # act = QAction(图标, 文字, 父级组件) # (&E)为设置 Alt+E 的快捷键,可省;图标参数可省 # 设置行为快捷键 act_exit.setShortcut('Ctrl+Q') # 设置行为在状态栏描述 act_exit.setStatusTip('Exit application') # 设置行为事件(退出) act_exit.triggered.connect(QApplication.instance().quit) # 行为.triggered 传出信号,由 connect 连接到 括号内的插槽 # 创建菜单栏 # 创建菜单栏对象 menubar = self.menuBar() # 创建菜单列,并命名 menu_file = menubar.addMenu('&File') # 在菜单列中添加行为 menu_file.addAction(act_exit) self.show() def main(): app = QApplication(sys.argv) qw = QWindow() sys.exit(app.exec()) if __name__ == '__main__': main() |
1.3.2 二级菜单(QMenu)
二级菜单 — QMenu |
|
python import sys from PyQt6.QtWidgets import (QMainWindow, QApplication) from PyQt6.QtWidgets import QMenu # 子菜单 from PyQt6.QtGui import QIcon # 菜单图标 from PyQt6.QtGui import QAction # 行为 class QWindow(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self.statusBar().showMessage('Ready') # 创建二级菜单 # 先建两个行为(快捷键、描述等略) act_test1 = QAction('test1', self) act_test2 = QAction('test2', self) # 创建子菜单 submenu_test = QMenu('&test',self) # &可省 # 子菜单添加行为 submenu_test.addAction(act_test1) submenu_test.addAction(act_test2) # 19-21可写入26-28:submenu_test.addAction('test1'),添加同时创建 # 创建菜单栏 menubar = self.menuBar() menu_file = menubar.addMenu('&File') # 在菜单列中添加二级菜单 menu_file.addMenu(submenu_test) self.show() def main(): app = QApplication(sys.argv) qw = QWindow() sys.exit(app.exec()) if __name__ == '__main__': main() |
1.3.3 勾选菜单(setCheckable)
勾选菜单 — setCheckable |
|
python import sys from PyQt6.QtWidgets import (QMainWindow, QApplication) from PyQt6.QtWidgets import QMenu # 子菜单 from PyQt6.QtGui import QAction # 行为 class QWindow(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): # 创建状态栏并返回对象 self.statusbar = self.statusBar() self.statusbar.showMessage('Ready') # 创建行为(check) # 行为增加 checkable 参数,填写是否行为为选框 act_check = QAction('check', self, checkable=True) act_check.setShortcut('Ctrl+C') act_check.setStatusTip('you can click') # 设置选框默认值 act_check.setChecked(True) # 设置行为事件(退出) act_check.triggered.connect(self.toggleMenu) # 关联参数可写类的实例属性 # 创建菜单栏 menubar = self.menuBar() menu_file = menubar.addMenu('&File') menu_file.addAction(act_check) self.show() # 创建实例方法(用于控制选框,状态栏显示的开关) def toggleMenu(self, state): if state: self.statusbar.show() else: self.statusbar.hide() def main(): app = QApplication(sys.argv) qw = QWindow() sys.exit(app.exec()) if __name__ == '__main__': main() |
1.3.4 上下文菜单(contextMenuEvent)
上下文菜单 — contextMenuEvent |
|
python import sys from PyQt6.QtWidgets import (QMainWindow, QApplication) from PyQt6.QtWidgets import QMenu # 子菜单 from PyQt6.QtGui import QAction # 行为 class QWindow(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self.show() # 点击事件:建议把上下文菜单全写在里面,方便调用 def contextMenuEvent(self, event): # 创建子菜单 submenu_desk = QMenu(self) # 仅父级对象一个参数 # 子菜单中新建行为 act_new = submenu_desk.addAction("New") act_open = submenu_desk.addAction("Open") act_exit = submenu_desk.addAction("Exit") # 行为进一步设置 act_exit.setShortcut('Ctrl+Q') act_exit.setStatusTip('Exit application') # act_exit.triggered.connect(QApplication.instance().quit) # 子菜单转换为桌面菜单,并返回菜单对象 action = submenu_desk.exec(self.mapToGlobal(event.pos())) # event.pos() 获得点击坐标;self.mapToGlobal() 把组件坐标设置成全局屏幕坐标; # submenu.exec() 调出上下文菜单 # 下两行可替代30行 if action == act_exit: QApplication.instance().quit() def main(): app = QApplication(sys.argv) qw = QWindow() sys.exit(app.exec()) if __name__ == '__main__': main() |
1.3.5 DLC
1.4 窗口工具栏(QToolBar)
窗口工具栏 — QToolBar |
|
python import sys from PyQt6.QtWidgets import QMainWindow, QApplication from PyQt6.QtGui import QIcon, QAction from PyQt6.QtCore import Qt, QSize class QWindow(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): # 创建行为 act1 = QAction(QIcon('exit.png'), 'act1', self) act2 = QAction(QIcon('exit.png'), 'act2', self) # 工具栏 # 创建工具栏 self.toolbar = self.addToolBar('toolbar') # 设置工具栏是否能移动(缺省值为 True) self.toolbar.setMovable(True) # 可通过 self.toolbar.isMovable() 返回是否能移动 # 设置工具栏可移动范围(缺省值为 AllToolBarAreas) self.toolbar.setAllowedAreas(Qt.ToolBarArea.TopToolBarArea) # ToolBar.isMovable() 为 True 时可用 # Qt.ToolBarArea.LeftToolBarArea 左侧区域 # Qt.ToolBarArea.RightToolBarArea 右侧区域 # Qt.ToolBarArea.TopToolBarArea 顶部区域 # Qt.ToolBarArea.BottomToolBarArea 底部区域 # Qt.ToolBarArea.AllToolBarAreas 全部区域(缺省值) # Qt.ToolBarArea.NoToolBarArea 不可放置 # 设置工具栏方向 self.toolbar.setOrientation(Qt.Orientation.Vertical) # Qt.Orientation.Vertical 纵向 # Qt.Orientation.Horizontal 横向(缺省值) # 工具栏按钮 # 工具栏添加行为按钮 self.toolbar.addAction(act1) # 工具栏添加分隔按钮 self.toolbar.addSeparator() self.toolbar.addAction(act2) # 设置工具按钮样式 self.toolbar.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextUnderIcon) # ToolButtonStyle.ToolButtonIconOnly 只显示图标 # ToolButtonStyle.ToolButtonTextOnly 只显示文本 # ToolButtonStyle.ToolButtonTextBesideIcon 文本在图标旁边 # ToolButtonStyle.ToolButtonTextUnderIcon 文本在图标下边 # ToolButtonStyle.ToolButtonFollowStyle 遵循系统风格 # 设置工具按钮图标大小 self.toolbar.setIconSize(QSize(20, 20)) # 可通过 self.toolbar.iconSize() 返回按钮大小; # 图标大小变化可发出 iconSizeChanged 信号; self.show() def main(): app = QApplication(sys.argv) qw = QWindow() sys.exit(app.exec()) if __name__ == '__main__': main() |
|
DLC |
|
[QToolBar Class |
Qt Widgets 6.3.2](https://doc.qt.io/qt-6/qtoolbar.html) |
1.5 停泊组件(QDockWidget)
- 停泊组件可以向上下左右边缘拖拽,其中上下优先于左右。例:上左各一组件,左上角重合部分属于上。
- 停泊组件拖拽至窗体外会变成悬浮窗口;双击悬浮窗口标题栏,组件可回到原位置。
- 停泊组件(self.addDockWidget)分布在窗体四周;与其对应的是中央组件(self.setCentralWidget)。停泊组件可以有很多个,且可在同一侧分布或重合;中央组件唯一。
停泊组件 — QDockWidget |
|
```python import sys from PyQt6.QtWidgets import QMainWindow, QWidget, QApplication, QHBoxLayout, QVBoxLayout from PyQt6.QtWidgets import QToolTip, QPushButton, QDockWidget, QTextEdit from PyQt6.QtGui import QIcon, QFont from PyQt6.QtCore import Qt class QWindow(QMainWindow): def init(self): super().init() self.Init_UI() def Init_UI(self): self.bt1 = QPushButton(‘按钮1’) self.bt1.clicked.connect(self.game) self.bt2 = QPushButton(‘按钮2’) self.bt2.clicked.connect(self.game) vbox = QVBoxLayout() vbox.addWidget(self.bt1) vbox.addWidget(self.bt2) rightdock1 = QWidget() rightdock1.setLayout(vbox) # 创建停泊组件 self.dock1 = QDockWidget(‘功能’,self) # 设置停泊组件停泊方式 self.dock1.setFeatures(QDockWidget.DockWidgetFeature.DockWidgetMovable |
QDockWidget.DockWidgetFeature.DockWidgetFloatable) # DockWidgetFeature.DockWidgetClosable 停泊组件仅可关闭 # DockWidgetFeature.DockWidgetMovable 停泊组件仅可移动 # DockWidgetFeature.DockWidgetFloatable 停泊组件仅可悬浮 # DockWidgetFeature.DockWidgetVerticalTitleBar 停泊组件垂直标题栏 # DockWidgetFeature.NoDockWidgetFeatures 停泊组件不可关闭/移动/悬浮 # self.dock1.features()返回停泊方式, # 缺省值为DockWidgetFeature.DockWidgetFloatable |
DockWidgetMovable |
DockWidgetClosable # 将按钮放入停泊组件中 self.dock1.setWidget(rightdock1) self.dock2 = QDockWidget(‘功能’,self) # 设置停泊组件默认为悬浮(缺省值为False) self.dock2.setFloating(True) self.tt = QTextEdit() # 窗口中设置中央组件 self.setCentralWidget(self.tt) # 窗口中添加停泊组件,并设置其初始位置 self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea,self.dock1) self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea,self.dock2) # Qt.DockWidgetArea.LeftDockWidgetArea 中央组件左侧停靠 # Qt.DockWidgetArea.RightDockWidgetArea 中央组件右侧停靠 # Qt.DockWidgetArea.TopDockWidgetArea 中央组件顶部停靠 # Qt.DockWidgetArea.BottomDockWidgetArea 中央组件底部停靠 # Qt.DockWidgetArea.AllDockWidgetAreas 中央组件随意停靠 # Qt.DockWidgetArea.NoDockWidgetArea 中央组件不会停靠 self.show() def game(self): self.tt.append(“你点我啦!”) if name == ‘main‘: app = QApplication(sys.argv) ex = QWindow() app.exit(app.exec()) ``` |
2 主窗口进阶
2.1 主窗口打开子窗口
主窗口打开子窗口 |
|
python import sys, os, time, re import pandas as pd from PyQt6.QtWidgets import * from PyQt6.QtGui import * from PyQt6.QtCore import * import sqlite3 # 子窗口代码类级 class PUimport30(QWidget): def __init__(self): super().__init__() class QWindow(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self._menubar = self.menuBar() self.act_pu_import30_prepare = QAction('准备 Import 3.0 文件',self) self.act_pu_import30_prepare.triggered.connect(self.openPUimport30) self.submenu_pu = QMenu('PU',self) self.submenu_pu.addAction(self.act_pu_import30_prepare) self.menu_function = self._menubar.addMenu('功能') self.menu_function.addMenu(self.submenu_pu) self.central = QMdiArea() self.setGeometry(250,250,500,250) self.setWindowTitle('宇哥帮你干TE(测试版)') self.setWindowIcon(QIcon('image/department.png')) self.setToolTip('测试版本') self.setCentralWidget(self.central) self.showMaximized() self.show() def openPUimport30(self): # 创建子窗口代码类级对象 self.puimport30 = PUimport30() # 显示子窗口 self.puimport30.show() def main(): app = QApplication(sys.argv) qw = QWindow() sys.exit(app.exec()) if __name__ == '__main__': main() |