为什么 QLabel.setFocus() 不将焦点传递给下一个小部件?

问题描述 投票:0回答:1

当我

TAB
围绕带有标签和行编辑的表单时,我看不到
QLabel
获得任何焦点;焦点正确地传递到它旁边的行编辑,即到
QWidget
label.nextInFocusChain()
.

我最初想要的:在

QLineEdit.editingFinished
的插槽中,我想将焦点设置到下一个(按TAB顺序)行编辑。我做
self.sender().nextInFocusChain().setFocus()
;而不是行编辑,它的标签,焦点链中的下一个,获得焦点。

调用

QLabel.setFocus()
时,焦点在标签本身;做另一个
TAB
将焦点设置到它之后的预期行编辑。为什么会这样?为什么焦点没有设置到它之后的小部件?为什么没有像
TAB
键那样设置焦点?

我检查了标签的焦点策略;他们

Qt.NoFocus
(默认)。我也把label的
textInteractionFlags
设置成
Qt.NoTextInteraction
也是白搭

将行编辑设置为标签的焦点代理可以满足我的要求,但我不认为这是正确的解决方案;或者我的理解有差距。

最小的例子

#!/usr/bin/env python3

import sys
from PySide2.QtWidgets import QApplication, QLineEdit, QWidget, \
    QFormLayout, QPushButton, QMainWindow, QLabel
from PySide2.QtCore import Qt


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        txtName = QLineEdit('')
        txtAge = QLineEdit('')
        self.lblAge = QLabel('&Age')
        self.lblAge.setBuddy(txtAge)
        # This or (default) Qt.LinksAccessibleByMouse doesn't help.
        # self.lblAge.setTextInteractionFlags(Qt.NoTextInteraction)
        btnNext = QPushButton('N&ext')
        btnNext.clicked.connect(self.moveFocus)
        formLayout = QFormLayout()
        formLayout.addRow('&Name', txtName)
        formLayout.addRow(self.lblAge, txtAge)
        formLayout.addRow(btnNext)
        window = QWidget()
        window.setLayout(formLayout)
        self.setCentralWidget(window)

    def moveFocus(self):
        self.lblAge.setFocus()


app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()

我在 ArchLinux 和 Xfce4 桌面环境上使用 Qt5 的官方 Python 绑定,即 PySide2。

qt5 focus pyside2 qlabel
1个回答
0
投票

widgets 的焦点策略只告诉 widget 在用户交互后是否接受焦点;事实上,文档说,例如,“小部件接受键盘焦点 by tabbing”或“by clicking”。

为伙伴设置标签时,并不意味着它可以获得焦点,也不意味着它是焦点链的一部分,也不会在它实际接收到它时(以编程方式或非编程方式)将焦点设置在该伙伴上:好友功能的唯一目的是在触发其快捷方式时将焦点设置在好友上。

显式调用

setFocus()
,尽管它的策略是
NoFocus
,但始终会使小部件获得焦点,那是因为调用已以 编程方式 完成,并且它没有从用户交互中获得焦点。另外,小部件必须能够在事件中接收焦点,即使它忽略它,这正是焦点代理的工作方式。

事实上,当用户交互(包括窗口激活)改变焦点时,Qt 根本不会调用

setFocus()
;相反,它将 QFocusEvent 发送到目标小部件,最终将传播到对象树中的父级。

不清楚您为什么要尝试根据标签设置焦点,但如果您真的需要这样做,那么您有以下选择:

  • 设置焦点代理,正如您已经发现的那样;
  • 在应该设置焦点的函数中,检查小部件是否是 QLabel 以及它是否有接受焦点的伙伴,然后使用
    setFocus()
  • 子类QLabel,覆盖
    focusInEvent()
    ,并执行上述操作;

使用子类方法,您甚至可以重写

mousePressEvent
处理程序,这样当用户单击标签时,它会自动将焦点设置在好友上。

同样可以通过将小部件设置为标签的焦点代理,然后将标签的焦点策略设置为

ClickFocus
.

© www.soinside.com 2019 - 2024. All rights reserved.