You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt6中如何让关联页面的QPushButton保持按下高亮状态?

问题

我开发了一个PyQt6界面,包含两个QPushButton(btn1、btn2)以及一个带有两个页面(page1、page2)的QStackedWidget。需求是点击btn1时显示page1,点击btn2时显示page2;同时处于page1时btn1保持按下/高亮状态,处于page2时btn2同理。

我的初始代码如下:

from PyQt6 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        MainWindow.setStyleSheet("QPushButton:pressed,\n"
        "QPushButton:clicked,\n"
        "QPushButton:checked,\n"
        "QPushButton:hover {\n"
        "    background-color: rgb(0, 0, 0);\n"
        "    color: rgb(255, 255, 255);\n"
        "}")
        self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.btn1 = QtWidgets.QPushButton(parent=self.centralwidget)
        self.btn1.setGeometry(QtCore.QRect(50, 50, 75, 24))
        self.btn1.setStyleSheet("\n"
        "\n"
        "")
        self.btn1.setObjectName("btn1")
        self.btn2 = QtWidgets.QPushButton(parent=self.centralwidget)
        self.btn2.setGeometry(QtCore.QRect(50, 90, 75, 24))
        self.btn2.setObjectName("btn2")
        self.stackedWidget = QtWidgets.QStackedWidget(parent=self.centralwidget)
        self.stackedWidget.setGeometry(QtCore.QRect(180, 40, 361, 221))
        self.stackedWidget.setObjectName("stackedWidget")
        self.page1 = QtWidgets.QWidget()
        self.page1.setObjectName("page1")
        self.stackedWidget.addWidget(self.page1)
        self.page2 = QtWidgets.QWidget()
        self.page2.setObjectName("page2")
        self.stackedWidget.addWidget(self.page2)
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
    _translate = QtCore.QCoreApplication.translate
    MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
    self.btn1.setText(_translate("MainWindow", "PushButton"))
    self.btn2.setText(_translate("MainWindow", "PushButton"))

我尝试了如下代码但未生效:

self.ui.btn1.clicked.connect(self.btn1Clicked)  #or should i select 'pressed' or 'toggled'signal instead       

self.ui.btn2.clicked.connect(self.btn2Clicked)

def btn1Clicked(self):
        self.ui.stackWidget.setCurrentWidget(self.ui.page1)

        if self.ui.stackWidget.setCurrentIndex(0):
            self.ui.btn1.setCheckable(True)
        else:
            self.ui.btn1.setCheckable(False)

请问该如何实现这一功能?

解决方案

要实现按钮点击切换页面并保持高亮状态,核心是利用QPushButton的**可勾选(checkable)**属性,配合信号槽联动控制按钮选中状态的互斥,具体实现如下:

关键修正点

  1. 给按钮设置setCheckable(True),让按钮具备保持选中状态的能力
  2. 点击按钮时,切换对应页面的同时,手动设置当前按钮为选中、另一个按钮为未选中(实现互斥)
  3. 优化样式,区分选中状态与其他状态的视觉效果,避免混淆

完整可运行代码

from PyQt6 import QtCore, QtGui, QtWidgets
import sys

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        # 调整样式,明确区分不同状态
        MainWindow.setStyleSheet("""
            QPushButton {
                background-color: #f0f0f0;
                color: #000;
                border: 1px solid #ccc;
                padding: 4px 8px;
            }
            QPushButton:hover {
                background-color: #e0e0e0;
            }
            QPushButton:checked {
                background-color: #000;
                color: #fff;
                border-color: #000;
            }
        """)
        self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        
        self.btn1 = QtWidgets.QPushButton(parent=self.centralwidget)
        self.btn1.setGeometry(QtCore.QRect(50, 50, 100, 28))
        self.btn1.setObjectName("btn1")
        self.btn1.setCheckable(True)  # 开启可勾选状态
        
        self.btn2 = QtWidgets.QPushButton(parent=self.centralwidget)
        self.btn2.setGeometry(QtCore.QRect(50, 90, 100, 28))
        self.btn2.setObjectName("btn2")
        self.btn2.setCheckable(True)  # 开启可勾选状态
        
        self.stackedWidget = QtWidgets.QStackedWidget(parent=self.centralwidget)
        self.stackedWidget.setGeometry(QtCore.QRect(180, 40, 361, 221))
        self.stackedWidget.setObjectName("stackedWidget")
        
        self.page1 = QtWidgets.QWidget()
        self.page1.setObjectName("page1")
        # 添加标签方便区分页面
        self.label_page1 = QtWidgets.QLabel(parent=self.page1)
        self.label_page1.setGeometry(QtCore.QRect(60, 80, 240, 30))
        self.label_page1.setText("当前显示:Page 1")
        self.label_page1.setStyleSheet("font-size: 16px;")
        self.stackedWidget.addWidget(self.page1)
        
        self.page2 = QtWidgets.QWidget()
        self.page2.setObjectName("page2")
        # 添加标签方便区分页面
        self.label_page2 = QtWidgets.QLabel(parent=self.page2)
        self.label_page2.setGeometry(QtCore.QRect(60, 80, 240, 30))
        self.label_page2.setText("当前显示:Page 2")
        self.label_page2.setStyleSheet("font-size: 16px;")
        self.stackedWidget.addWidget(self.page2)
        
        MainWindow.setCentralWidget(self.centralwidget)
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "页面切换Demo"))
        self.btn1.setText(_translate("MainWindow", "切换到Page1"))
        self.btn2.setText(_translate("MainWindow", "切换到Page2"))

class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        # 绑定信号与槽函数
        self.btn1.clicked.connect(self.switch_to_page1)
        self.btn2.clicked.connect(self.switch_to_page2)
        # 默认初始化状态:选中btn1,显示page1
        self.btn1.setChecked(True)
        self.stackedWidget.setCurrentWidget(self.page1)

    def switch_to_page1(self):
        self.stackedWidget.setCurrentWidget(self.page1)
        self.btn1.setChecked(True)
        self.btn2.setChecked(False)  # 互斥取消另一个按钮的选中状态

    def switch_to_page2(self):
        self.stackedWidget.setCurrentWidget(self.page2)
        self.btn2.setChecked(True)
        self.btn1.setChecked(False)  # 互斥取消另一个按钮的选中状态

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

说明

  • setCheckable(True)是实现按钮保持高亮的核心,没有这个属性,按钮点击后会立刻恢复原状
  • 手动设置另一个按钮为未选中,确保同一时间只有一个按钮处于高亮状态
  • 优化后的样式让选中状态的视觉反馈更清晰,避免和hover、pressed状态混淆
  • 采用UI类与业务逻辑类分离的结构,是PyQt开发的最佳实践,便于后续维护和扩展

内容的提问来源于stack exchange,提问作者Bob Wallace

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 14:53:15