关于pyqt5/pyside6编写软件界面及美化界面的小技巧

查看 63|回复 10
作者:FeiyuYip   
最近使用pyside6写了若干个小工具,在学习的过程中,也积累了一些小技巧
现在来说一下常用的一个写界面的方式,算是自身的积累,也希望能给需要的朋友一些启发
一、关于界面
可以用qtdesigner来画,也可以用代码来生成
[Python] 纯文本查看 复制代码from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QStackedWidget, \
    QLabel, QSystemTrayIcon, QMenu
from PySide6.QtCore import Qt, QFile, QTextStream, QIODevice
from PySide6.QtGui import QIcon, QAction
import res_rc
import sys
import os
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initialize_tray()
        self.iniUI()
        # 加载qss
        style_qss = ":style/style.qss"
        stream = QFile(style_qss)
        stream.open(QIODevice.ReadOnly)
        content = QTextStream(stream).readAll()
        self.setStyleSheet(content)
        # 加载ico
        icon = ":ico/demo.png"
        self.setWindowIcon(QIcon(icon))
        self.center()
    def iniUI(self):
        self.setWindowTitle("Demo")
        self.setGeometry(200, 200, 800, 600)
        # self.setWindowIcon(QIcon("memo.ico"))  # 可替换为你的图标路径
        # 主窗口布局
        main_layout = QHBoxLayout()
        # 左侧导航栏
        self.button_names_list = ["界面1", "界面2", "界面3", "设置", "关于"]
        nav_widget, self.buttons = self.create_navigation()
        # 1.左侧导航栏
        main_layout.addWidget(nav_widget)
        # 2.右侧内容区,根据按钮数来创建新的界面
        self.stack = QStackedWidget()
        for i in range(1, len(self.button_names_list) + 1):
            if i == 1:
                # 第一个界面是已经确定的,直接调用
                self.page_work_memo = self.create_page(f"This is Page {i}", "#88C0D0")
                self.stack.addWidget(self.page_work_memo)
            else:
                self.page = self.create_page(f"This is Page {i}", "#88C0D0")
                self.stack.addWidget(self.page)
        main_layout.addWidget(self.stack)
        # 创建中央小部件
        central_widget = QWidget()
        central_widget.setLayout(main_layout)
        self.setCentralWidget(central_widget)
        # 连接按钮事件
        for i, button in enumerate(self.buttons):
            button.clicked.connect(lambda checked, idx=i: self.switch_page(idx))
    # 创建左侧导航栏
    def create_navigation(self):
        """创建导航栏"""
        nav_widget = QWidget()
        nav_layout = QVBoxLayout()
        nav_widget.setLayout(nav_layout)
        nav_widget.setFixedWidth(100)
        buttons = []
        for i, text in enumerate(self.button_names_list):
            button = QPushButton(text)
            button.setObjectName(f"btn_{i}")
            buttons.append(button)
            nav_layout.addWidget(button)
            # 在添加最后一个前,addstretch
            if i == len(self.button_names_list) - 3:
                nav_layout.addStretch()
        return nav_widget, buttons
    def switch_page(self, index):
        """切换页面并更新按钮样式"""
        self.stack.setCurrentIndex(index)
    def create_page(self, text, color):
        """创建页面内容"""
        page = QWidget()
        layout = QVBoxLayout()
        label = QLabel(text)
        label.setAlignment(Qt.AlignCenter)
        layout.addWidget(label)
        page.setLayout(layout)
        return page
    def initialize_tray(self):
        """初始化系统托盘图标"""
        self.tray_icon = QSystemTrayIcon(self)
        icon = ":ico/demo.png"
        if icon:
            self.tray_icon.setIcon(QIcon(icon))
        else:
            print("托盘图标未找到")
        self.tray_icon.setToolTip('Demo')
        self.tray_icon.setVisible(True)
        self.setup_tray_menu()
    def get_absolute_path(self, relative_path):
        """根据相对路径获取绝对路径"""
        if getattr(sys, 'frozen', False):
            # 如果程序是打包后的,则使用 sys._MEIPASS 获取临时目录路径
            base_dir = sys._MEIPASS
        else:
            # 如果是开发环境下运行,使用当前文件路径
            base_dir = os.path.dirname(__file__)
        absolute_path = os.path.join(base_dir, relative_path)  # 拼接出绝对路径
        return absolute_path if os.path.exists(absolute_path) else None
    def setup_tray_menu(self):
        """设置托盘菜单"""
        tray_menu = QMenu()
        show_action = QAction('显示界面', self)
        show_action.triggered.connect(self.show_window)
        tray_menu.addAction(show_action)
        quit_action = QAction('退出', self)
        quit_action.triggered.connect(self.quit)
        tray_menu.addAction(quit_action)
        self.tray_icon.setContextMenu(tray_menu)
        self.tray_icon.activated.connect(self.tray_icon_activated)
    def tray_icon_activated(self, reason):
        if reason == QSystemTrayIcon.Trigger:
            self.show_window()
    def quit(self):
        """保存数据并退出"""
        self.close()
        QApplication.quit()
    def show_window(self):
        """显示主窗口"""
        self.showNormal()
        self.activateWindow()
    def closeEvent(self, event):
        event.ignore()  # 忽略关闭事件
        self.hide()  # 隐藏主窗口
    def center(self):
        # 获取屏幕大小
        screen_geometry = QApplication.screens()[0].availableGeometry()
        screen_width = screen_geometry.width()
        screen_height = screen_geometry.height()
        # 计算窗口位置
        x = (screen_width - self.width()) // 2
        y = (screen_height - self.height()) // 2
        # 设置窗口位置
        self.move(x, y)
if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()
如上,是使用代码生成的一个简单界面,包含了左侧有一个导航栏,能够通过点击不同的按钮来切换不同的界面,并带有系统托盘


1.jpg (48.18 KB, 下载次数: 0)
下载附件
2025-1-13 22:51 上传

二、关于界面美化
如果光写出来的界面,美化效果肯定是不够的(看我贴子的朋友可以发现,最近的小工具界面似乎更美观了)
所以可以用以下方法
1.可以将软件界面各元素的美化(StyleSheet属性)写在ui界面中(或直接在qtdesigner中写)
例如:
[Python] 纯文本查看 复制代码button.setStyleSheet("""
                QPushButton {
                    background-color: #4C566A;
                    color: white;
                    font-size: 18px;
                    border: none;
                    padding: 10px;
                    text-align: left;
                }
                QPushButton:hover {
                    background-color: #5E81AC;
                }
            """)
2.为了更好地将界面与美化效果分离,可以使用新建qss文件的方法,定制ui中出现的元素的stylesheet
如下:
[Python] 纯文本查看 复制代码/* 主窗口背景颜色 */
QWidget {
    background-color: #2E3440;
    color: #ECEFF4;
    font-family: "Microsoft YaHei", sans-serif;
    font-size: 16px;
}
/* 按钮样式 */
QPushButton {
    background-color: #4C566A;
    color: #ECEFF4;
    font-size: 18px;
    border: 2px solid #4C566A;
    border-radius: 10px;
    padding: 8px 16px;
    text-align: center;
    transition: all 0.3s ease;
}
QPushButton:hover {
    background-color: #5E81AC;
    border-color: #81A1C1;
    color: #ECEFF4;
}
QPushButton:pressed {
    background-color: #3B4252;
    border-color: #88C0D0;
    color: #ECEFF4;
}
/* 标签样式 */
QLabel {
    font-size: 20px;
    font-weight: bold;
    color: #ECEFF4;
    background-color: #4C566A;
    border-radius: 8px;
    padding: 10px;
    text-align: center;
}
/* 左侧导航栏按钮样式 */
#btn_0, #btn_1, #btn_2 {
    background-color: #3B4252;
    color: #ECEFF4;
    border-radius: 10px;
    font-size: 16px;
    padding: 10px 8px;
}
#btn_0:hover, #btn_1:hover, #btn_2:hover {
    background-color: #5E81AC;
}
#btn_0:checked, #btn_1:checked, #btn_2:checked {
    background-color: #88C0D0;
    color: #2E3440;
}
/* 滚动条样式 */
QScrollBar:vertical {
    background: #2E3440;
    width: 10px;
    margin: 0px;
    border-radius: 5px;
}
QScrollBar::handle:vertical {
    background: #5E81AC;
    min-height: 20px;
    border-radius: 5px;
}
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
    background: none;
}
QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
    background: none;
}
/* 系统托盘菜单样式 */
QMenu {
    background-color: #3B4252;
    border: 1px solid #4C566A;
    color: #ECEFF4;
}
QMenu::item {
    padding: 8px 20px;
    background-color: transparent;
}
QMenu::item:selected {
    background-color: #5E81AC;
}
/* 提示文本样式 */
QToolTip {
    background-color: #4C566A;
    color: #ECEFF4;
    border: 1px solid #88C0D0;
    border-radius: 5px;
    padding: 4px;
}
然后呢,新建一个qrc文件,同样有两种方法
1.在qtdesigner中新建


2.jpg (290.65 KB, 下载次数: 0)
下载附件
2025-1-13 23:00 上传

2.直接新建一个qrc文件,其代码如下(我这里是添加了icon文件及qss文件):
[Python] 纯文本查看 复制代码
  
    style.qss
  
  
    demo.png
  
TIPS:如有其他的可以继续添加
三、在界面中调用QSS文件
1.首先是相关配置,Setting-Tools-External Tools,添加qrc转换成py的功能
(此项可百度,我这里是添加了新建UI,打开UI,UI2PY,QRC2PY)


3.jpg (48.22 KB, 下载次数: 0)
下载附件
2025-1-13 23:04 上传

三句代码分别如下(第一句是找到rcc文件路径,pyqt5或pyqt6可能稍有不同,另用户名需要修改成你的):
[Python] 纯文本查看 复制代码C:\Users\用户名\AppData\Local\Programs\Python\Python310\Scripts\pyside6-rcc.exe
$FileName$ -o $FileNameWithoutExtension$_rc.py
$FileDir$
2.在代码中调用qss文件
(1)首先是执行转换,如图设置后,会生成一个**_rc.py文件


4.jpg (134.54 KB, 下载次数: 0)
下载附件
2025-1-13 23:14 上传

导入转换后的py文件
[Python] 纯文本查看 复制代码import res_rc
然后在代码中引用它
[Python] 纯文本查看 复制代码# 加载qss
        style_qss = ":style/style.qss"
        stream = QFile(style_qss)
        stream.open(QIODevice.ReadOnly)
        content = QTextStream(stream).readAll()
        self.setStyleSheet(content)
        # 加载ico
        icon = ":ico/demo.png"
        self.setWindowIcon(QIcon(icon))
这样做的好处是:
1.由于qss或ico文件均已经由qrc资源文件转换成二进制文件,所以不需要再单独引入它们(如在spec中重新定义路径)
2.在美化界面时,只需要修改qss文件,然后再次执行一次qrc文件转py文件,即可生效,比较方便,不需要修改主代码的逻辑
四、Demo示例代码
通过网盘分享的文件:Demo
链接: https://pan.baidu.com/s/1bho_QD460LlNLnqshn_nRg?pwd=r86h 提取码: r86h

界面, 文件

y5230024   

我发现还是用动态加载UI文件的方法比较好,不然每次改动界面都要重新生成py代码,重新打包,qss也支持动态加载吗
bester   

qtdesigner 可以自由画QVBOXLAYOUT的大小以及位置,但是用代码添加的,似乎不能指定位置和大小
bohong65   

很好的ui教程,我之前在想前端能不能用css+html写然后转换成pyside6
anning666   

用python写的这种GUI界面,美化的时候都得写一堆qss,没点css基础,还真玩不来~~~~
深爱成瘾   

喜欢直接用qtdesigner设计界面,不习惯用代码写界面~
yidodo   

做这么好看 你不要命了
九灬影   

谢谢分享界面美化的方法
FeiyuYip
OP
  


anning666 发表于 2025-1-14 08:36
用python写的这种GUI界面,美化的时候都得写一堆qss,没点css基础,还真玩不来~~~~

其实问gpt就行了,它会帮你改。配合自己能看懂,能指出自己的想法及少量的修改
pojiestudy   

好思路,好方法,值得学习
您需要登录后才可以回帖 登录 | 立即注册

返回顶部