确定在按下按钮之前具有最后焦点的 QWidget
Determine QWidget that had last focus before button press
我想在我的 Qt 应用程序中实现以下功能:
- 用户打开一个或多个 'input' 小部件(
InputWidget
class 的实例),每个小部件包含一个 QLineEdit
小部件
- 用户打开 'helper' 对话框
- 用户在 'helper' 对话框中选择一个值
- 用户在 'helper' 对话框中按下 'Insert'
QPushButton
- 从 'helper' 对话框中选择的值被插入到 'input' 对话框的
QLineEdit
中,该对话框在按下 'Insert' 按钮之前具有最后一个焦点
所以,基本上,我想要的是,如果用户在以下屏幕截图中单击 'Insert',则字符串 'Apple' 应该出现在焦点输入对话框中。下面的代码示例做了一些工作,只是将字符串(通常,见下文)插入到第二个中。
下面是创建此设置的代码示例:
from PyQt5.QtWidgets import (QApplication, QWidget, QHBoxLayout,
QLineEdit, QLabel, QPushButton, QComboBox)
import sys
# this is the missing bit
def determineWhichWidgetHadLastFocus():
for widget in QApplication.instance().topLevelWidgets():
if isinstance(widget, InputWidget):
# do something wonderful to determine whether this widget
# is the one that had last focus
wonderful = True
if wonderful:
return widget
return None
class BaseWidget(QWidget):
""" Base widget type """
def __init__(self, name):
super(BaseWidget, self).__init__()
self.setWindowTitle(name)
self.setupUi()
self.show()
def setupUi(self):
pass
class InputWidget(BaseWidget):
""" InputWidget contains a QLabel and a QLineEdit widget """
def setupUi(self):
self.label = QLabel("Input string:")
self.edit = QLineEdit()
layout = QHBoxLayout(self)
layout.addWidget(self.label)
layout.addWidget(self.edit)
class HelperWidget(BaseWidget):
""" HelperWidget contains a QLineEdit and a QPushButton widget. Pressing
the button inserts the content of the edit widget into the edit widget of
the last activated InputWidget """
def setupUi(self):
self.combo = QComboBox()
self.combo.addItems(["Apple", "Pear", "Banana"])
self.button = QPushButton("Insert")
self.button.clicked.connect(self.insertString)
layout = QHBoxLayout(self)
layout.addWidget(self.combo)
layout.addWidget(self.button)
def insertString(self):
widget = determineWhichWidgetHadLastFocus()
if widget:
widget.edit.insert(self.combo.currentText())
def main():
app = QApplication(sys.argv)
diag1 = InputWidget("Input dialog")
diag2 = InputWidget("Another input")
helper = HelperWidget("Helper")
app.exec_()
if __name__ == "__main__":
main()
缺少的部分是 determineWhichWidgetHadLastFocus()
函数。
这个函数应该做一些很棒的事情,让它可以确定哪个 'input' 是最后一个保持焦点的。目前,它从 QApplication
开始遍历顶级小部件列表,但顶级小部件的顺序并不反映激活顺序(它通常但并不总是显示为创建顺序)。
我想到的一个想法是安装一个事件过滤器来跟踪 FocusIn
事件。在我的示例中,这对于 InputWidget
class 来说很容易,但对于我的具有许多 QLineEdit
、QTextEdit
和下降 class到处都是。我宁愿不走那条路。
还有其他想法吗?
事实证明,事件过滤器的想法毕竟是可行的方法。我所做的是首先创建一个事件过滤器 class,如果发送对象是 QLineEdit
对象,它会发出一个信号:
from PyQt5.QtCore import QObject, QEvent, pyqtSignal
class inputFocusFilter(QObject):
focusIn = pyqtSignal(object)
def eventFilter(self, widget, event):
if event.type() == QEvent.FocusIn and isinstance(widget, QLineEdit):
# emit a `focusIn` signal, with the widget as its argument:
self.focusIn.emit(widget)
return super(inputFocusFilter, self).eventFilter(widget, event)
此过滤器是为自定义 QApplication
class 安装的,因此创建的任何事件都可以通过过滤器。信号 focusIn
连接到一个 setter 函数,该函数记住最后一个获得焦点的输入小部件:
class MyApplication(QApplication):
def __init__(self, *arg, **kwarg):
super(MyApplication, self).__init__(*arg, **kwarg)
self._input_focus_widget = None
self.event_filter = inputFocusFilter()
self.event_filter.focusIn.connect(self.setInputFocusWidget)
self.installEventFilter(self.event_filter)
def setInputFocusWidget(self, widget):
self._input_focus_widget = widget
def inputFocusWidget(self):
return self._input_focus_widget
MyApplication
代替了main()
第一行的QApplication
。现在,HelperWidget.insertString()
中对 determineWhichWidgetHadLastFocus()
的调用可以替换为 QApplication.instance().inputFocusWidget()
,并且一切正常。
我想在我的 Qt 应用程序中实现以下功能:
- 用户打开一个或多个 'input' 小部件(
InputWidget
class 的实例),每个小部件包含一个QLineEdit
小部件 - 用户打开 'helper' 对话框
- 用户在 'helper' 对话框中选择一个值
- 用户在 'helper' 对话框中按下 'Insert'
QPushButton
- 从 'helper' 对话框中选择的值被插入到 'input' 对话框的
QLineEdit
中,该对话框在按下 'Insert' 按钮之前具有最后一个焦点
所以,基本上,我想要的是,如果用户在以下屏幕截图中单击 'Insert',则字符串 'Apple' 应该出现在焦点输入对话框中。下面的代码示例做了一些工作,只是将字符串(通常,见下文)插入到第二个中。
下面是创建此设置的代码示例:
from PyQt5.QtWidgets import (QApplication, QWidget, QHBoxLayout,
QLineEdit, QLabel, QPushButton, QComboBox)
import sys
# this is the missing bit
def determineWhichWidgetHadLastFocus():
for widget in QApplication.instance().topLevelWidgets():
if isinstance(widget, InputWidget):
# do something wonderful to determine whether this widget
# is the one that had last focus
wonderful = True
if wonderful:
return widget
return None
class BaseWidget(QWidget):
""" Base widget type """
def __init__(self, name):
super(BaseWidget, self).__init__()
self.setWindowTitle(name)
self.setupUi()
self.show()
def setupUi(self):
pass
class InputWidget(BaseWidget):
""" InputWidget contains a QLabel and a QLineEdit widget """
def setupUi(self):
self.label = QLabel("Input string:")
self.edit = QLineEdit()
layout = QHBoxLayout(self)
layout.addWidget(self.label)
layout.addWidget(self.edit)
class HelperWidget(BaseWidget):
""" HelperWidget contains a QLineEdit and a QPushButton widget. Pressing
the button inserts the content of the edit widget into the edit widget of
the last activated InputWidget """
def setupUi(self):
self.combo = QComboBox()
self.combo.addItems(["Apple", "Pear", "Banana"])
self.button = QPushButton("Insert")
self.button.clicked.connect(self.insertString)
layout = QHBoxLayout(self)
layout.addWidget(self.combo)
layout.addWidget(self.button)
def insertString(self):
widget = determineWhichWidgetHadLastFocus()
if widget:
widget.edit.insert(self.combo.currentText())
def main():
app = QApplication(sys.argv)
diag1 = InputWidget("Input dialog")
diag2 = InputWidget("Another input")
helper = HelperWidget("Helper")
app.exec_()
if __name__ == "__main__":
main()
缺少的部分是 determineWhichWidgetHadLastFocus()
函数。
这个函数应该做一些很棒的事情,让它可以确定哪个 'input' 是最后一个保持焦点的。目前,它从 QApplication
开始遍历顶级小部件列表,但顶级小部件的顺序并不反映激活顺序(它通常但并不总是显示为创建顺序)。
我想到的一个想法是安装一个事件过滤器来跟踪 FocusIn
事件。在我的示例中,这对于 InputWidget
class 来说很容易,但对于我的具有许多 QLineEdit
、QTextEdit
和下降 class到处都是。我宁愿不走那条路。
还有其他想法吗?
事实证明,事件过滤器的想法毕竟是可行的方法。我所做的是首先创建一个事件过滤器 class,如果发送对象是 QLineEdit
对象,它会发出一个信号:
from PyQt5.QtCore import QObject, QEvent, pyqtSignal
class inputFocusFilter(QObject):
focusIn = pyqtSignal(object)
def eventFilter(self, widget, event):
if event.type() == QEvent.FocusIn and isinstance(widget, QLineEdit):
# emit a `focusIn` signal, with the widget as its argument:
self.focusIn.emit(widget)
return super(inputFocusFilter, self).eventFilter(widget, event)
此过滤器是为自定义 QApplication
class 安装的,因此创建的任何事件都可以通过过滤器。信号 focusIn
连接到一个 setter 函数,该函数记住最后一个获得焦点的输入小部件:
class MyApplication(QApplication):
def __init__(self, *arg, **kwarg):
super(MyApplication, self).__init__(*arg, **kwarg)
self._input_focus_widget = None
self.event_filter = inputFocusFilter()
self.event_filter.focusIn.connect(self.setInputFocusWidget)
self.installEventFilter(self.event_filter)
def setInputFocusWidget(self, widget):
self._input_focus_widget = widget
def inputFocusWidget(self):
return self._input_focus_widget
MyApplication
代替了main()
第一行的QApplication
。现在,HelperWidget.insertString()
中对 determineWhichWidgetHadLastFocus()
的调用可以替换为 QApplication.instance().inputFocusWidget()
,并且一切正常。