首页 » 软件开发 » Python入坑系列-pyside6桌面开发之QmainWindow自定义标题栏(窗口停靠工具栏设置部件)

Python入坑系列-pyside6桌面开发之QmainWindow自定义标题栏(窗口停靠工具栏设置部件)

admin 2024-07-24 14:27:17 0

扫一扫用手机浏览

文章目录 [+]

主窗口提供了用于构建应用程序的用户界面的框架,其主要布局如下

Menu Bar:菜单栏,通过添加QMenuBar

# 实例化QMenuBarself.menuBarInstance = QMenuBar(self)# 创建菜单fileMenu = self.menuBarInstance.addMenu("文件")# 创建动作exitAction = QAction("退出", self)exitAction.triggered.connect(self.close)# 将动作添加到菜单fileMenu.addAction(exitAction)Toolbars:工具栏,通过往窗口添加QToolBar

# 实例化QToolBartoolBar = QToolBar("我的工具栏", self)self.addToolBar(toolBar)# 创建动作exitAction = QAction("退出", self)exitAction.triggered.connect(self.close)# 将动作添加到菜单fileMenu.addAction(exitAction)Dock Widgets:停靠部件,比如浮窗的拖动部件,通过往窗口添加QDockWidgets

# 创建一个QDockWidgetdock = QDockWidget("菜单", self)self.addDockWidget(Qt.LeftDockWidgetArea, dock)# 创建一个列表作为菜单项容器menuList = QListWidget()dock.setWidget(menuList)Central Widget:占据主窗口中心区域的部件,通常是标准 Qt 小部,通过添加Widget部件

# 实例化一个QWidget作为中心部件centralWidget = QWidget()self.setCentralWidget(centralWidget)# 创建一个布局layout = QVBoxLayout()# 添加一些控件到布局中layout.addWidget(QLabel("这是一个标签"))# 将布局设置给中心部件centralWidget.setLayout(layout)Status Bar:状态栏显示,通过添加QStatusBar

# 实例化一个QStatusBarstatusBar = QStatusBar()# 将状态栏设置为主窗口的状态栏self.setStatusBar(statusBar)# 在状态栏中添加一些信息statusBar.addWidget(QLabel("这是状态栏信息"))

2、QMainWindow常用属性和方法

属性windowTitle::窗口的标题。
menuBar:窗口的菜单栏。
statusBar:窗口的状态栏。
centralWidget:窗口的中心部件。
toolBars:窗口的工具栏列表。
dockWidgets:窗口的停靠窗口列表。
animated:操作停靠小部件和工具栏是否有动画dockNestingEnabled:停靠部件是否可以嵌套dockOptions:QMainWindow的停靠行为documentMode:选项卡式停靠小部件的选项卡栏是否设置为文档模式iconSize:此主窗口中工具栏图标的大小tabShape:用于选项卡式停靠小部件的选项卡形状toolButtonStyle:主窗口中工具栏按钮的样式unifiedTitleAndToolBarOnMac:窗口是否在macOS上使用统一的标题和工具栏外观方法setWindowFlags(Qt.WindowFlags flags):用于指定窗口的各种属性和行为。
例如,你可以设置窗口为无边框、始终在顶层显示、不显示在任务栏等

窗口装饰标志

Python入坑系列-pyside6桌面开发之QmainWindow自定义标题栏(窗口停靠工具栏设置部件) 软件开发
(图片来自网络侵删)

Qt.MSWindowsFixedSizeDialogHint

Windows平台上,使对话框窗口的大小固定,不能被用户调整。

Qt.X11BypassWindowManagerHint

在X11平台(Linux/Unix)上,使窗口绕过窗口管理器,直接与系统交互。
这通常用于需要完全控制窗口显示和行为的特殊窗口

Qt.FramelessWindowHint

创建一个无边框窗口。
这通常用于自定义窗口的外观。

Qt.NoDropShadowWindowHint

禁用窗口的阴影效果。
这在自定义窗口绘制时可能有用,特别是在需要精确控制窗口外观的情况下。

Qt.WindowTitleHint

窗口将包含一个标题栏。
这是大多数窗口的默认行为。

Qt.WindowSystemMenuHint

窗口将包含一个系统菜单,通常位于标题栏的左上角。

Qt.WindowMinimizeButtonHint

窗口将包含一个最小化按钮。

Qt.WindowMaximizeButtonHint

窗口将包含一个最大化按钮。

Qt.WindowCloseButtonHint

窗口将包含一个关闭按钮。

Qt.WindowContextHelpButtonHint

窗口将包含一个上下文帮助按钮,在用户点击时通常会显示帮助信息。

Qt.WindowStaysOnTopHint

窗口将始终保持在其他窗口之上。

Qt.WindowStaysOnBottomHint

窗口将始终保持在其他窗口之下。

Qt.CustomizeWindowHint

允许窗口被自定义,通常与其他窗口标志一起使用,以提供特定的窗口外观和行为。

常用窗口标志

Qt.Widget

默认值,指示对象是一个控件

Qt.Window

使控件成为一个窗口,这会给它提供窗口装饰

Qt.Dialog

示窗口是一个对话框

Qt.Sheet

指示窗口是一个Mac风格的表单(仅在Mac OS X中有效)

Qt.Drawer

指示窗口是一个Mac风格的抽屉(仅在Mac OS X中有效)

Qt.Popup

指示窗口是一个弹出窗口

Qt.Tool

指示窗口是一个工具窗口。
工具窗口是一个小窗口,通常用于提供模式或非模式对话框

Qt.ToolTip

指示窗口是一个工具提示

Qt.SplashScreen

指示窗口是一个启动画面

Qt.Desktop

指示窗口是桌面。
这是一个特殊的窗口,不能创建

Qt.SubWindow

指示窗口是一个子窗口

addDockWidget(area, dockwidget, orientation): 在指定区域和方向添加一个停靠窗口。
以下是停靠的枚举值

常用的停靠窗口标志

QMainWindow.AnimatedDocks

与属性相同animated。

QMainWindow.AllowNestedDocks

与属性相同dockNestingEnabled。

QMainWindow.AllowTabbedDocks

用户可以将一个停靠小部件放置在另一个停靠小部件的“顶部”。
这两个小部件堆叠在一起,并出现一个选项卡栏,用于选择哪个小部件可见。

QMainWindow.ForceTabbedDocks

每个停靠区域都包含一堆选项卡式停靠小部件。
换句话说,停靠小部件不能在停靠区域中彼此相邻放置。
如果设置此选项,AllowNestedDocks 不起作用。

QMainWindow.VerticalTabs

主窗口两侧的两个垂直停靠区域垂直显示其选项卡。
如果未设置此选项,所有停靠区域都会在底部显示其选项卡。
暗示AllowTabbedDocks。
也可以看看setTabPosition()。

QMainWindow.GroupedDragging

拖动扩展坞的标题栏时,所有与其关联的选项卡都将被拖动。
暗示AllowTabbedDocks。
如果某些 QDockWidget 在允许的区域有限制,则效果不佳。
(这个枚举值是在 Qt 5.6 中添加的。

addDockWidget(area, dockwidget): 在指定区域添加一个停靠窗口。
addToolBar(area, toolbar): 在指定区域添加一个工具栏。
addToolBar(title): 创建一个新的工具栏,使用提供的标题。
addToolBar(toolbar): 添加一个预先创建的工具栏。
addToolBarBreak([area=Qt.TopToolBarArea]): 在指定区域添加一个工具栏断点。
centralWidget(): 返回当前设置为中心部件的QWidget对象。
corner(corner): 返回指定角落的停靠区域。
dockOptions(): 返回当前的停靠选项。
dockWidgetArea(dockwidget): 返回指定停靠窗口所在的区域。
documentMode(): 返回文档模式的启用状态。
iconSize(): 返回工具栏图标的大小。
insertToolBar(before, toolbar): 在指定的工具栏之前插入一个工具栏。
insertToolBarBreak(before): 在指定的工具栏之前插入一个工具栏断点。
isAnimated(): 返回窗口是否启用动画。
isDockNestingEnabled(): 返回是否允许停靠窗口嵌套。
isSeparator(pos): 检查指定位置是否为分隔符。
menuBar(): 返回窗口的菜单栏。
menuWidget(): 返回设置为菜单栏的自定义QWidget对象。
removeDockWidget(dockwidget): 移除指定的停靠窗口。
removeToolBar(toolbar): 移除指定的工具栏。
removeToolBarBreak(before): 移除指定位置的工具栏断点。
resizeDocks(docks, sizes, orientation): 调整一组停靠窗口的大小。
restoreDockWidget(dockwidget): 恢复停靠窗口的状态。
restoreState(state[, version=0]): 恢复窗口的状态。
saveState([version=0]): 保存窗口的当前状态。
setCentralWidget(widget): 设置中心部件。
setCorner(corner, area): 设置窗口角落的停靠区域。
setDockOptions(options): 设置停靠选项。
setDocumentMode(enabled): 启用或禁用文档模式。
setIconSize(iconSize): 设置工具栏图标的大小。
setMenuBar(menubar): 设置窗口的菜单栏。
setMenuWidget(menubar): 设置自定义的菜单栏部件。
setStatusBar(statusbar): 设置窗口的状态栏。
setTabPosition(areas, tabPosition): 设置停靠窗口的标签位置。
setTabShape(tabShape): 设置停靠窗口的标签形状。
setToolButtonStyle(toolButtonStyle): 设置工具按钮的样式。
splitDockWidget(after, dockwidget, orientation): 将一个停靠窗口分割为两个。
statusBar(): 返回窗口的状态栏。
tabPosition(area): 返回指定区域的标签位置。
tabShape(): 返回停靠窗口的标签形状。
tabifiedDockWidgets(dockwidget): 返回与指定停靠窗口标签化的所有停靠窗口。
tabifyDockWidget(first, second): 将两个停靠窗口标签化。
takeCentralWidget(): 移除并返回中心部件。
toolBarArea(toolbar): 返回指定工具栏所在的区域toolBarBreak(toolbar): 检查指定工具栏之前是否有工具栏断点。
toolButtonStyle(): 返回工具按钮的样式。
unifiedTitleAndToolBarOnMac(): 返回是否在Mac OS上使用统一的标题栏和工具栏样式。
createPopupMenu(): 创建一个包含所有可停靠窗口和工具栏的可见性控制项的弹出菜单。
这个方法通常用于提供一个上下文菜单,允许用户选择哪些工具栏或停靠窗口是可见的。

3、QMainWindow图标和背景设置

设置logo图标

# 设置窗口图标self.setWindowIcon(QIcon('path/to/your/icon.png'))设置背景通过样式设置颜色

# 使用样式表设置背景颜色self.setStyleSheet("background-color: lightblue;")通过样式设置图片

# 使用样式表设置背景图片self.setStyleSheet("background-image: url('path/to/your/image.jpg');")通过QPainter绘制背景图片

class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("通过paintEvent设置背景") def paintEvent(self, event): painter = QPainter(self) pixmap = QPixmap("path/to/your/image.jpg") P·ainter.drawPixmap(self.rect(), pixmap)if __name__ == "__main__": app = QApplication(sys.argv) mainWindow = MainWindow() mainWindow.show() sys.exit(app.exec_())

4、QMainWindow无边框设计实现

实现无边框设计,pyside6目前没有很好的解决方案。
主要思路是设置无边框,通过自定义标题栏来实现窗口的基本属性,事件。
下面是具体例子:

from PySide6.QtCore import QSize, Qt, QEventfrom PySide6.QtGui import QPalette, QRegionfrom PySide6.QtWidgets import class CustomTitleBar(QWidget): def __init__(self, parent): super().__init__(parent) self.setAutoFillBackground(True) self.setBackgroundRole(QPalette.ColorRole.Highlight) self.initial_pos = None title_bar_layout = QHBoxLayout(self) title_bar_layout.setContentsMargins(1, 1, 1, 1) title_bar_layout.setSpacing(2) self.title = QLabel("自定义工具栏", self) self.title.setStyleSheet( """font-weight: bold; border: 2px solid black; border-radius: 12px; margin: 2px; """ ) self.title.setAlignment(Qt.AlignmentFlag.AlignCenter) if title := parent.windowTitle(): self.title.setText(title) # 只设置自定义标题拖动 self.title.mousePressEvent = parent.title_mousePressEvent self.title.mouseMoveEvent = parent.title_mouseMoveEvent self.title.mouseReleaseEvent = parent.title_mouseReleaseEvent title_bar_layout.addWidget(self.title) # Min button self.min_button = QToolButton(self) min_icon = self.style().standardIcon( QStyle.StandardPixmap.SP_TitleBarMinButton ) self.min_button.setIcon(min_icon) self.min_button.clicked.connect(self.window().showMinimized) # Max button self.max_button = QToolButton(self) max_icon = self.style().standardIcon( QStyle.StandardPixmap.SP_TitleBarMaxButton ) self.max_button.setIcon(max_icon) self.max_button.clicked.connect(self.window().showMaximized) # Close button self.close_button = QToolButton(self) close_icon = self.style().standardIcon( QStyle.StandardPixmap.SP_TitleBarCloseButton ) self.close_button.setIcon(close_icon) self.close_button.clicked.connect(self.window().close) # Normal button self.normal_button = QToolButton(self) normal_icon = self.style().standardIcon( QStyle.StandardPixmap.SP_TitleBarNormalButton ) self.normal_button.setIcon(normal_icon) self.normal_button.clicked.connect(self.window().showNormal) self.normal_button.setVisible(False) # Add buttons buttons = [ self.min_button, self.normal_button, self.max_button, self.close_button, ] for button in buttons: button.setFocusPolicy(Qt.FocusPolicy.NoFocus) button.setFixedSize(QSize(28, 28)) button.setStyleSheet( """QToolButton { border: 2px solid white; border-radius: 12px; } """ ) title_bar_layout.addWidget(button) def window_state_changed(self, state): if state == Qt.WindowState.WindowMaximized: self.normal_button.setVisible(True) self.max_button.setVisible(False) else: self.normal_button.setVisible(False) self.max_button.setVisible(True)class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("Custom Title Bar") self.setMinimumSize(600, 400) self.setWindowFlags(Qt.FramelessWindowHint) # 使用QSS设置边框样式为圆角 self.setStyleSheet("MainWindow{border-radius: 1px;}") central_widget = QWidget() self.title_bar = CustomTitleBar(self) work_space_layout = QVBoxLayout() work_space_layout.setContentsMargins(11, 11, 11, 11) work_space_layout.addWidget(QLabel("Hello, World!", self)) centra_widget_layout = QVBoxLayout() centra_widget_layout.setContentsMargins(0, 0, 0, 0) centra_widget_layout.setAlignment(Qt.AlignmentFlag.AlignTop) centra_widget_layout.addWidget(self.title_bar) centra_widget_layout.addLayout(work_space_layout) central_widget.setLayout(centra_widget_layout) self.setCentralWidget(central_widget) def changeEvent(self, event): if event.type() == QEvent.Type.WindowStateChange: self.title_bar.window_state_changed(self.windowState()) super().changeEvent(event) event.accept() def window_state_changed(self, state): self.normal_button.setVisible(state == Qt.WindowState.WindowMaximized) self.max_button.setVisible(state != Qt.WindowState.WindowMaximized) def title_mousePressEvent(self, event): if event.button() == Qt.MouseButton.LeftButton: self.initial_pos = event.position().toPoint() super().mousePressEvent(event) event.accept() def title_mouseMoveEvent(self, event): if self.initial_pos is not None: delta = event.position().toPoint() - self.initial_pos self.window().move( self.window().x() + delta.x(), self.window().y() + delta.y(), ) super().mouseMoveEvent(event) event.accept() def title_mouseReleaseEvent(self, event): self.initial_pos = None super().mouseReleaseEvent(event) event.accept()if __name__ == "__main__": app = QApplication([]) window = MainWindow() window.show() app.exec()

效果如下,可以实现放大,缩小,标题栏拖动功能:

效果图

上面例子没有实现窗口边框可拖动放大缩小的功能,是个遗憾。
github上的有实现,可以参考:https://github.com/alexpdev/QtFrameless。

标签:

相关文章

语言中的借用,文化交融的桥梁

自古以来,人类社会的交流与发展离不开语言的传播。在漫长的历史长河中,各民族、各地区之间的文化相互碰撞、交融,产生了许多独特的语言现...

软件开发 2025-01-01 阅读1 评论0

机顶盒协议,守护数字生活的新卫士

随着科技的飞速发展,数字家庭逐渐走进千家万户。在这个时代,机顶盒成为了连接我们与丰富多彩的数字世界的重要桥梁。而机顶盒协议,作为保...

软件开发 2025-01-01 阅读1 评论0

语言基础在现代社会的重要性及方法步骤

语言是人类沟通的桥梁,是社会发展的基础。语言基础作为语言学习的基石,对于个人、社会乃至国家的发展具有重要意义。本文将从语言基础在现...

软件开发 2025-01-01 阅读2 评论0

粤语电影,传承文化,点亮时代之光

粤语电影,作为中国电影产业的一朵奇葩,以其独特的地域特色、丰富的文化内涵和鲜明的艺术风格,赢得了广大观众的喜爱。本文将从粤语电影的...

软件开发 2025-01-01 阅读3 评论0

苹果游戏语言,塑造未来娱乐体验的基石

随着科技的飞速发展,游戏产业逐渐成为全球娱乐市场的重要支柱。在我国,游戏产业更是蓬勃发展,吸引了无数玩家和投资者的目光。而在这其中...

软件开发 2025-01-01 阅读1 评论0