python,Qt,QLineEdit响应tab键、上下左右方向键

基本介绍

QLineEdit本身支的信号函数一共有六个,但其中只有returnPressed的响应,并没有对其他按键的响应。参见:QLineEdit 信号函数总结,https://blog.csdn.net/u013687602/article/details/19968185

·void cursorPositionChanged( intold, intnew )
当鼠标移动时发出此信号,old为先前的位置,new为新位置。

·void editingFinished()
当按返回或者回车键时,或者行编辑失去焦点时,发出此信号。
注意:当QLineEdit设置了validator() orinputMask()函数,验证器or输入掩码,并按了返回或回车键,信号只有在 输入内容符合输入掩码 或验证器返回 QValidator::Acceptable时 发出。

· void returnPressed()
当 返回或回车键按下时发出此信号,
注意:当QLineEdit设置了validator() orinputMask()函数,验证器or输入掩码,并按了返回或回车键,信号只有在 输入内容符合输入掩码 或验证器返回 QValidator::Acceptable时 发出。

· void selectionChanged()
当选文本改变时,发出此信号。

· void textChanged( const QString &text )
当QLineEdit中的文本改变时,发出此信号,text是新的文本。当通过程序改变文本时,也会触发此信号,例如,setText()

· void textEdited( const QString &text )
当QLineEdit中的文本改变时,发出此信号,text是新的文本。当通过程序改变文本时,不会触发此信号。

这6个信号在python中的使用参考“PyQt5 QLineEdit控件信号使用”一文,https://blog.csdn.net/u013934107/article/details/94599494

le.textEdited.connect(lambda val:print("文本框编辑的时候",val))#文本框编辑事件
le.textChanged.connect(lambda val:print("文本框内容发生改变",val))#文本框改变事件
le.returnPressed.connect(lambda:print("回车键被按下"))
le.returnPressed.connect(lambda:le2.setFocus())
le.editingFinished.connect(lambda:print("结束编辑"))
le.cursorPositionChanged.connect(lambda  old_Pos,new_Pos:print(old_Pos,new_Pos))#焦点发生改变
le.selectionChanged.connect(lambda:print("选中文本发生改变",le.selectedText()))#选中文本发生改变事件

通过installEventFilter响应按键

由上一小节可知,QLineEdit控件本身并不支持单独响应tab键、上下左右方向键。通过搜索,我们看到可以通过installEventFilter的方式来实现这一功能。

https://stackoverflow.com/questions/2078842/qlineedit-how-to-handle-up-and-down-arrows

该文虽然和本文中我们遇到的问题很一致,从问答中我们可以进一步确认QLineEdit对于tab键及方向键,确实没有提供类似于returnPressed这样的信号函数。尽管回答中提供了通过installEventFilter实现功能的思路,但是对于具体的实现描述不多。因此我们继续以installEventFilter为关键字进行搜索。

https://stackoverflow.com/questions/25275974/make-qlineedit-detect-tab-key-press-event

该文介绍了C++中,介绍了通过installEventFilter方式和继承QLineEdit 的方式来实现tab按键检测的方式。同时演示了自定义eventFilter()函数的写法。

https://stackoverflow.com/questions/50768366/installeventfilter-in-pyqt5

该文介绍了在python中,通过调用QLineEdit对象实例的installEventFilter方法来监听按键。特别地,该文演示了python中自定义eventFilter()函数的写法。该文中,给installEventFilter函数传递的self对象同时是Ui_cortes2的实例,但这并不是必须的。下文会有说。

https://programtalk.com/python-examples/PyQt5.QtWidgets.QApplication.instance.installEventFilter/

https://programtalk.com/vs2/python/13927/frescobaldi/frescobaldi_app/gadgets/customtooltip.py/

通过阅读这段代码,我们可以知道,给installEventFilter函数传递的类对象只需要是QObject的实例对象即可。同时该代码还提示我们,除了QEvent.KeyPress外,installEventFilter还可以监听FocusIn、Leave等事件。

代码实现

由于我们在python环境下使用Qt,是通过designer来设计界面的,并通过命令将ui命令转为py文件(pyuic5 -o main_ui.py fp_dev_tool.ui)。所以我们没有走继承QLineEdit的这种方式,而是采用installEventFilter的方式来实现我们的需求。下面是我们对QLineEdit的一个封装。

from PyQt5.QtCore import QEvent, QObject

class CustomQLineEditWrapper(QObject):        
    def __init__(self, editor):
        # installEventFilter 依赖QObject,因此必须先调用父类构造函数
        super().__init__()
        self.editor = editor
        self.editor.installEventFilter(self)
        self.keyMap = {}

    def setKeyPressCallback(self, key, callback):
        self.keyMap[key] = callback

    # 返回True表示将此消息消耗掉,返回False则不会
    def eventFilter(self, obj, ev):
        if obj is not self.editor:
            return False
        if ev.type() != QEvent.KeyPress:
            return False
        if ev.key() in self.keyMap:
            self.keyMap[ev.key()]()
            return True
        return False
#pyuic5 -o main_ui.py fp_dev_tool.ui

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget
from PyQt5.QtWidgets import QMessageBox

import sys
import main_ui
from custom_qlineedit_wrapper import *
class FfDevToolWindow(main_ui.Ui_MainWindow):
    def setupUi(self, window):
        super().setupUi(window)
        self.cmdLineEdit.setFocus()
        self.cmdLineEdit.returnPressed.connect(self.returnPressed)

        self.lineEditor = CustomQLineEditWrapper(self.cmdLineEdit)
        self.lineEditor.setKeyPressCallback(Qt.Key_Escape, lambda:self.cmdLineEdit.setText(""))
        self.lineEditor.setKeyPressCallback(Qt.Key_Up, self.upPressed)
        self.lineEditor.setKeyPressCallback(Qt.Key_Down, self.downPressed)

    def upPressed(self):
        QMessageBox.information(QWidget(), "标题", "key up", QMessageBox.Yes | QMessageBox.No)

    def downPressed(self):
        QMessageBox.information(QWidget(), "标题", "key down", QMessageBox.Yes | QMessageBox.No)

    def returnPressed(self):
        self.cmdLineEdit.setText("")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    ui = FfDevToolWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

其他资料

Qt::Key键盘按键详细说明,https://blog.csdn.net/judgejames/article/details/93191524

Qt::Key_Escape0x01000000Esc键
Qt::Key_Tab0x01000001Tab键
Qt::Key_Backtab0x01000002Tab补全键
Qt::Key_Return0x01000004Return键
Qt::Key_Enter0x01000005回车键
Qt::Key_Left0x01000012
Qt::Key_Up0x01000013
Qt::Key_Right0x01000014
Qt::Key_Down0x01000015

 

其中,Key_Enter是小键盘的确认键,Key_Return是大键盘的回车键。参见:https://blog.csdn.net/qq_37887537/article/details/79089288

 


版权声明:本文为l03071344原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。