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

切换QStackWidget栈时QPushButton自动获取焦点且焦点状态无法取消的问题

Fixing Unwanted Focus on QPushButton After Switching QStackedWidget

Let's break down what's happening here and how to fix it:

The Problem

When you switch back to the first stack from the second one (after clicking the QListWidget), the "First" button gets a blue focus border—even though you never clicked it, and it's not set as checkable. This border won't go away unless you click another focusable element.

Why This Happens

Qt's focus management system automatically assigns focus to a focusable widget when its parent (the stack in this case) becomes visible. Since the "First" button is the first focusable widget in the first stack, it grabs the focus as soon as the stack is switched back to. That blue border is just Qt's default focus indicator, not a selected/check state.

Solutions

1. Redirect Focus to the Central Widget After Switching

The simplest fix is to explicitly give focus to the central widget instead of letting the button take it. Modify your switch_stack method like this:

def switch_stack(self, index_):
    self.stack_widget.setCurrentIndex(index_)
    # Shift focus to the central widget to remove it from the button
    self.central_widget.setFocus()

2. Disable Focus for the Button

If you don't want the button to ever receive focus (which makes sense if it's just a trigger for actions), set its focus policy to NoFocus when creating it:

from PyQt5.QtCore import Qt  # Don't forget this import

# ...

button_1 = QPushButton('First')
button_1.setFocusPolicy(Qt.NoFocus)  # Add this line
button_2 = QPushButton('Second')
button_2.setFocusPolicy(Qt.NoFocus)  # Optional, if you want the same for this button

3. Clear Focus in the First Stack Explicitly

If you want to keep the button's focus capability but just prevent it from grabbing focus on stack switch, you can clear focus for all widgets in the first stack:

def switch_stack(self, index_):
    self.stack_widget.setCurrentIndex(index_)
    if index_ == 0:
        # Clear focus from all widgets in the first sub-widget
        for widget in self.first_sub_widget.findChildren(QWidget):
            widget.clearFocus()

Tested Modified Code (Using Solution 1)

Here's your full code with the first solution applied (plus fixing the commented-out central widget line):

#!/usr/bin/env python3
import sys
from PyQt5.QtGui import QGradient
from PyQt5.QtWidgets import QGridLayout, QHBoxLayout, QListWidget, QMainWindow, QPushButton, QStackedWidget, QWidget, QApplication

class M(QMainWindow):
    def __init__(self):
        super().__init__()
        self.set()
    def set(self):
        self.central_widget = QWidget(self)
        self.central_layout = QGridLayout()
        self.central_widget.setLayout(self.central_layout)
        self.setCentralWidget(self.central_widget)  # Uncommented for proper widget hierarchy

        self.first_button = QPushButton('first stack')
        self.second_button = QPushButton('second stack')
        self.central_layout.addWidget(self.first_button, 0, 0, 1, 1)
        self.central_layout.addWidget(self.second_button, 0, 1, 1, 1)

        self.stack_widget = QStackedWidget()
        self.central_layout.addWidget(self.stack_widget, 1, 0, 1, 2)

        # add sub widget for stackwidget
        self.add_sub_widget_for_stack()

        # add func for button
        self.first_button.clicked.connect(
            lambda checked, x=0: self.switch_stack(x)
        )
        self.second_button.clicked.connect(
            lambda checked, x=1: self.switch_stack(x)
        )

    def add_sub_widget_for_stack(self):
        print('add')
        # add first sub widget
        self.first_sub_widget = QWidget()
        self.first_sub_widget.setLayout(QHBoxLayout())
        button_1 = QPushButton('First')
        button_2 = QPushButton('Second')
        self.first_sub_widget.layout().addWidget(button_1)
        self.first_sub_widget.layout().addWidget(button_2)
        self.stack_widget.addWidget(self.first_sub_widget)

        # add second sub widget
        self.second_sub_widget = QWidget()
        self.second_sub_widget.setLayout(QHBoxLayout())
        list_ = QListWidget()
        self.second_sub_widget.layout().addWidget(list_)
        self.stack_widget.addWidget(self.second_sub_widget)

    def switch_stack(self, index_):
        self.stack_widget.setCurrentIndex(index_)
        # Redirect focus to central widget
        self.central_widget.setFocus()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    m = M()
    m.show()
    sys.exit(app.exec_())

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 15:47:45