news 2026/1/17 7:39:05

PySide6 自定义侧边栏 实现思路与代码详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PySide6 自定义侧边栏 实现思路与代码详解

PySide6 自定义侧边栏 实现思路与代码详解

PySide6虽然得益于Qt框架的强大与Python语法的快速开发,但是默认提供的主题不符合现代UI的省美!比如:侧边栏一般也叫导航栏(更多是手机平板的等设备)。

写在前边

笔者使用的是LinuxGnome桌面系统,其他显示效果请自行尝试!

为了更方便的描述,这里分为如下俩中情况:

  1. 默认展开 => 切换后先收缩
  2. 默认收缩 => 切换后先放大

效果演示


默认展开

注意:

  • 紫色为:QFrame嵌套QVboxLayout是主窗口
  • 绿色为:QFrame嵌套QVboxLayout是侧边栏(父类为主窗口的QFrame)
实现思路

显示与隐藏核心:

  • 默认展开:QFrame设置最大与最小宽度为155
  • 切换:重新设置QFrame的最小宽度

温馨提示:
setFixedWidth<=>setMinimumWidth+setMaximumWidth
选择QFrame一是参考Qt Designer,二是继承QWidget更好的设置 属性

核心代码解读
deftoggle_sidebar(self):"""show or hide toggle button text"""self.anim=QPropertyAnimation(self.__sidebar_frame,b"minimumWidth")self.anim.stop()ifself.__sidebar_visible==False:# hide: right to leftself.anim.setStartValue(self.__sidebar_frame.width())self.anim.setEndValue(40)else:# show: left to rightself.anim.setStartValue(self.__sidebar_frame.width())self.anim.setEndValue(155)self.__sidebar_frame.setFixedWidth(40)self.anim.setEasingCurve(QEasingCurve.Type.InOutQuad)self.anim.setDuration(500)self.anim.start()self.__sidebar_visible=notself.__sidebar_visible

重点如下:

  1. QPropertyAnimation:实现显示与隐藏的动画效果;官方文档
  2. QEasingCurve:使得动画更丝滑;官方文档
  3. setDuration:设置动画的持续时间;官方文档

⚠️注意

  1. 取消self.__sidebar_frame.setFixedWidth(40)将无法正常收缩
  2. 改变整体布局为QHBoxLayout,展开与收缩就会从QFrame中心垂线收缩展开

完整代码:

#hide_sidebar.pyimportsysfromPySide6.QtWidgetsimport(QWidget,QFrame,QVBoxLayout,QPushButton,QApplication)fromPySide6.QtCoreimportQPropertyAnimation,QEasingCurveclassQCustomeWidget(QWidget):"""Custome sidebar """def__init__(self):self.__sidebar_visible=Falsesuper().__init__()self.__setup_ui()self.__setup_event_handel()def__setup_ui(self):# widget sizeself.setFixedSize(400,300)# global layout use framelayout then vboxlayoutself.__global_frame=QFrame(self)self.__global_frame.setContentsMargins(0,0,0,0)self.__global_layout=QVBoxLayout(self.__global_frame)self.__global_layout.setSpacing(0)self.__global_layout.setContentsMargins(0,0,0,0)# sidebar frame framelayoutself.__sidebar_frame=QFrame(self.__global_frame)self.__sidebar_layout=QVBoxLayout(self.__sidebar_frame)self.__sidebar_frame.setLayout(self.__sidebar_layout)self.__sidebar_frame.setContentsMargins(0,0,0,0)self.__sidebar_layout.setContentsMargins(0,0,0,0)self.__sidebar_layout.setSpacing(0)# form sizeself.__sidebar_frame.setFixedSize(155,self.height())self.__sidebar_frame.setStyleSheet("background-color:grey;")# toggle and home buttonself.__toggle_btn=QPushButton('show: button text',self.__sidebar_frame)self.__toggle_btn.setStyleSheet(".QPushButton {background-color: rgb(56, 56, 60);text-align: left;}")self.__home_btn=QPushButton('home: button text',self.__sidebar_frame)self.__home_btn.setStyleSheet(".QPushButton {background-color: rgb(56, 56, 60);text-align: left;}")# add buttonself.__sidebar_layout.addWidget(self.__toggle_btn)self.__sidebar_layout.addWidget(self.__home_btn)# add Widgetself.__global_layout.addWidget(self.__sidebar_frame)def__setup_event_handel(self):self.__toggle_btn.clicked.connect(self.toggle_sidebar)deftoggle_sidebar(self):"""show or hide toggle button text"""self.anim=QPropertyAnimation(self.__sidebar_frame,b"minimumWidth")self.anim.stop()ifself.__sidebar_visible==False:# hide: right to leftself.anim.setStartValue(self.__sidebar_frame.width())self.anim.setEndValue(40)else:# show: left to rightself.anim.setStartValue(self.__sidebar_frame.width())self.anim.setEndValue(155)self.__sidebar_frame.setFixedWidth(40)self.anim.setEasingCurve(QEasingCurve.Type.OutQuad)self.anim.setDuration(500)self.anim.start()self.__sidebar_visible=notself.__sidebar_visibledefmain():app=QApplication([])sidebar=QCustomeWidget()sidebar.show()sys.exit(app.exec())if__name__=="__main__":main()

默认隐藏

注意:

  • 紫色为:QFrame嵌套QVboxLayoutQHboxLayout是主窗口
  • 绿色为:QFrame嵌套QVboxLayout是侧边栏(父类为主窗口的QFrame)
实现思路

与默认展开不同的是:

  • 右侧需要控件用于占用剩余的空间.
完整代码
#show_sidebar.pyimportsysfromPySide6.QtWidgetsimport(QWidget,QFrame,QHBoxLayout,QVBoxLayout,QLabel,QPushButton,QApplication)fromPySide6.QtCoreimport(QPropertyAnimation,QEasingCurve)classQCustomeSideBar(QWidget):"""Custome sidebar """def__init__(self):self.__sidebar_visible=Falsesuper().__init__()self.__setup_ui()self.__setup_event_handel()def__setup_ui(self):# widget sizeself.setFixedSize(400,300)# global layout use framelayout then vboxlayoutself.__global_frame=QFrame(self)self.__global_frame.setContentsMargins(0,0,0,0)self.__global_layout=QVBoxLayout(self.__global_frame)# or use# self.__global_layout = QHBoxLayout(self.__global_frame)self.__global_layout.setSpacing(0)self.__global_layout.setContentsMargins(0,0,0,0)# content and sidebar frame framelayoutself.__sidebar_frame=QFrame(self.__global_frame)self.__sidebar_layout=QVBoxLayout(self.__sidebar_frame)self.__sidebar_frame.setLayout(self.__sidebar_layout)self.__sidebar_frame.setContentsMargins(0,0,0,0)self.__sidebar_layout.setContentsMargins(0,0,0,0)self.__sidebar_layout.setSpacing(0)# form sizeself.__sidebar_frame.setFixedSize(40,self.height())self.__sidebar_frame.setStyleSheet("background-color:grey;")# toggle and home buttonself.__toggle_btn=QPushButton('show: button text',self.__sidebar_frame)self.__toggle_btn.setStyleSheet(".QPushButton {background-color: rgb(56, 56, 60);text-align: left;}")self.__home_btn=QPushButton('home: button text',self.__sidebar_frame)self.__home_btn.setStyleSheet(".QPushButton {background-color: rgb(56, 56, 60);text-align: left;}")# add buttonself.__sidebar_layout.addWidget(self.__toggle_btn)self.__sidebar_layout.addWidget(self.__home_btn)# add Widgetself.__global_layout.addWidget(self.__sidebar_frame)self.__content_button=QLabel("text")self.__content_button.setStyleSheet("text-align: right; margin-left:115px;")self.__global_layout.addWidget(self.__content_button)def__setup_event_handel(self):self.__toggle_btn.clicked.connect(self.toggle_sidebar)deftoggle_sidebar(self):"""show or hide toggle button text"""self.anim=QPropertyAnimation(self.__sidebar_frame,b"minimumWidth",self.__global_frame)self.anim.stop()ifself.__sidebar_visible==False:# show: left to rightself.anim.setStartValue(self.__sidebar_frame.width())self.anim.setEndValue(155)else:# hide: right to leftself.anim.setStartValue(self.__sidebar_frame.width())self.anim.setEndValue(40)self.anim.setEasingCurve(QEasingCurve.Type.InOutQuad)self.anim.setDuration(500)self.anim.start()self.__sidebar_visible=notself.__sidebar_visibledefmain():app=QApplication([])sidebar=QCustomeSideBar()sidebar.show()sys.exit(app.exec())if__name__=="__main__":main()
一起学习与探讨

点击链接加入群聊【PySide6学习交流群】:

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/16 21:29:10

打印机驱动下载网站有哪些?手把手教您安装,新手也能快速完成

“打印机驱动失效了该去哪下&#xff1f;”“安装驱动总是失败&#xff0c;是不是网站选得不对&#xff1f;”其实&#xff0c;打印机无法正常工作&#xff0c;80%的问题都出在“驱动适配”上&#xff0c;而选对下载平台&#xff0c;就是解决问题的第一步。今天就来盘点市面上靠…

作者头像 李华
网站建设 2026/1/15 22:50:44

某大厂 M* 80 带火无网通信?别急,除了换手机,你还有个更聪明的选择

近日&#xff0c;某大厂 M* 80 凭借其首发的“700MHz 无网应急通信” 功能刷屏了朋友圈。这让很多户外爱好者和车队领队开始思考一个问题&#xff1a;在没有信号的野外&#xff0c;我们真的只能依靠那个挂在腰间多年的笨重“板砖”——传统对讲机吗&#xff1f; M*80 确实向我…

作者头像 李华
网站建设 2026/1/16 18:53:54

基于PHP的零食商城系统的设计与实现源码设计与文档

前言基于 PHP 的零食商城系统&#xff0c;直击 “零食品类分散、选购对比难、配送售后衔接不畅” 的核心痛点&#xff0c;依托 PHP 的高效后端处理能力与 Laravel 框架的快速开发优势&#xff0c;构建 “品类丰富 选购便捷 交易安全” 的一体化零食电商服务平台。传统模式下&…

作者头像 李华
网站建设 2026/1/12 7:48:40

5分钟零配置部署:Docker容器化语音合成系统全攻略

5分钟零配置部署&#xff1a;Docker容器化语音合成系统全攻略 【免费下载链接】ChatTTS-ui 匹配ChatTTS的web界面和api接口 项目地址: https://gitcode.com/GitHub_Trending/ch/ChatTTS-ui 还在为语音合成系统的环境配置而烦恼吗&#xff1f;CUDA版本冲突、Python依赖包…

作者头像 李华
网站建设 2026/1/16 4:16:56

CopyQ脚本编程终极指南:从零开始打造智能剪贴板

CopyQ脚本编程终极指南&#xff1a;从零开始打造智能剪贴板 【免费下载链接】CopyQ hluk/CopyQ: CopyQ 是一个高级剪贴板管理器&#xff0c;具有强大的编辑和脚本功能&#xff0c;可以保存系统剪贴板的内容并在以后使用。 项目地址: https://gitcode.com/gh_mirrors/co/CopyQ…

作者头像 李华