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

基于PyQt6实现Target控件聚焦显示、失焦隐藏Button的需求

解决PyQt6中控件聚焦状态关联按钮显示/隐藏的问题

需求说明

当Target输入框获得焦点时,按钮控件可见;当Target失去焦点(例如点击Secondary输入框)时,按钮隐藏,实现焦点状态与按钮可见性的绑定。

原代码问题分析

原代码中直接通过Wn.button访问按钮是错误的,因为button是Wn类的实例属性而非类属性,且Target类需要获取到父窗口Wn的实例才能正确操作按钮。此外,重写事件处理函数时未调用父类的对应方法,会破坏QLineEdit的默认聚焦行为。

解决方案1:通过父控件直接访问按钮

这种方法简单直接,适合小型场景:

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QLineEdit


class Wn(QWidget):

    def __init__(self):
        super().__init__()

        self.target = Target("Target", self)
        self.target.setFixedSize(400, 60)
        self.target.move(50, 50)
        self.secondary = QLineEdit("Secondary", self)
        self.secondary.setFixedSize(400, 60)
        self.secondary.move(50, 150)
        self.button = QPushButton("Appears @ Target focused. Disappears @ target not focused", self)
        self.button.setFixedSize(400, 60)
        self.button.move(50, 250)
        # 初始状态隐藏按钮
        self.button.setHidden(True)


class Target(QLineEdit):

    def focusInEvent(self, event):
        super().focusInEvent(event)  # 必须调用父类事件处理,保留默认行为
        print("The target is in focus: Button should be shown")
        self.setStyleSheet("background-color: red;")
        # Line A:获取父窗口实例,显示按钮
        self.parent().button.setHidden(False)

    def focusOutEvent(self, event):
        super().focusOutEvent(event)  # 必须调用父类事件处理,保留默认行为
        print("The target is out of focus: Button should be hidden")
        self.setStyleSheet("background-color: white;")
        # Line B:获取父窗口实例,隐藏按钮
        self.parent().button.setHidden(True)


app = QApplication(sys.argv)
wn = Wn()
wn.show()
sys.exit(app.exec())

关键修改点:

  1. 在Wn的初始化方法中设置按钮初始隐藏,符合默认状态。
  2. 重写focusInEvent和focusOutEvent时,必须调用父类对应方法,确保QLineEdit的默认聚焦逻辑正常运行。
  3. 通过self.parent()获取父窗口Wn的实例,直接操作其button属性的可见性。

解决方案2:自定义信号解耦控件依赖

这种方法遵循Qt的信号槽设计模式,解耦Target和Wn的直接依赖,适合大型项目:

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QLineEdit
from PyQt6.QtCore import pyqtSignal


class Wn(QWidget):

    def __init__(self):
        super().__init__()

        self.target = Target("Target", self)
        # 连接Target的焦点变化信号到槽函数
        self.target.focus_changed.connect(self.on_target_focus_changed)
        self.target.setFixedSize(400, 60)
        self.target.move(50, 50)
        self.secondary = QLineEdit("Secondary", self)
        self.secondary.setFixedSize(400, 60)
        self.secondary.move(50, 150)
        self.button = QPushButton("Appears @ Target focused. Disappears @ target not focused", self)
        self.button.setFixedSize(400, 60)
        self.button.move(50, 250)
        self.button.setHidden(True)

    def on_target_focus_changed(self, has_focus):
        # 根据焦点状态设置按钮可见性
        self.button.setHidden(not has_focus)


class Target(QLineEdit):
    # 自定义信号:传递布尔值,表示当前是否获得焦点
    focus_changed = pyqtSignal(bool)

    def focusInEvent(self, event):
        super().focusInEvent(event)
        print("The target is in focus: Button should be shown")
        self.setStyleSheet("background-color: red;")
        # Line A:发送获得焦点的信号
        self.focus_changed.emit(True)

    def focusOutEvent(self, event):
        super().focusOutEvent(event)
        print("The target is out of focus: Button should be hidden")
        self.setStyleSheet("background-color: white;")
        # Line B:发送失去焦点的信号
        self.focus_changed.emit(False)


app = QApplication(sys.argv)
wn = Wn()
wn.show()
sys.exit(app.exec())

关键修改点:

  1. 给Target类添加focus_changed自定义信号,用于传递焦点状态变化。
  2. 在Wn中连接信号到槽函数on_target_focus_changed,由槽函数负责按钮的显示/隐藏逻辑。
  3. Target类无需知道父窗口的具体控件,仅负责发送焦点状态信号,实现了控件间的解耦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 12:15:48