news 2026/4/23 12:29:16

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/4/20 13:10:11

【蓝桥杯单片机】第二讲 过渡模拟二与LED模块

一、过渡模拟二 1 小数点输入 case 11://小数点输入if(Seg_Disp_Mode 0 && Point_Flag 0 && Seg_Input[0] ! 11)//处于温度采集界面、标志位为0、输入数组第一位有数据{Seg_Point[2Seg_Input_Index] 1;Point_Wela Seg_Input_Index;//记录此时指针状态 便于…

作者头像 李华
网站建设 2026/4/21 3:07:45

涪陵区市电路灯批发报价与成本分析

在城市照明基础设施建设中&#xff0c;涪陵区近年来持续推进智慧化、绿色化升级&#xff0c;尤其在市电路灯系统的优化与更新方面成效显著。作为连接城市功能与居民生活的重要载体&#xff0c;路灯不仅承担基础照明任务&#xff0c;更需契合不同应用场景对光效、安全、节能及维…

作者头像 李华
网站建设 2026/4/22 19:35:42

光学工程师面试真题

一、基础理论与原理类1. 请解释数值孔径&#xff08;NA&#xff09; 的定义及计算公式&#xff0c;它对光学系统&#xff08;如显微镜、光纤&#xff09;的分辨率和通光量有何影响&#xff1f;2. 什么是光学镀膜的“增透膜”和“高反膜”&#xff1f;分别基于什么光学原理实现&…

作者头像 李华
网站建设 2026/4/16 16:17:15

文献检索网站有哪些:常用文献检索网站推荐与使用指南

开题报告前那两个月&#xff0c;我电脑里塞满了乱七八糟的PDF&#xff0c;参考文献格式错得千奇百怪&#xff0c;导师一句“脉络不清”打回来三次。后来才发现&#xff0c;问题不是读得不够多&#xff0c;而是工具没用对。这三个工具帮我理清了思路&#xff0c;把一堆文献变成了…

作者头像 李华
网站建设 2026/4/22 17:23:29

谷歌学术搜索:高效学术文献检索与研究资源获取指南

开题报告前那两个月&#xff0c;我电脑里塞满了乱七八糟的PDF&#xff0c;参考文献格式错得千奇百怪&#xff0c;导师一句“脉络不清”打回来三次。后来才发现&#xff0c;问题不是读得不够多&#xff0c;而是工具没用对。这三个工具帮我理清了思路&#xff0c;把一堆文献变成了…

作者头像 李华