pyqt5的键盘事件

原帖出自http://blog.sina.com.cn/yjcx2010

键盘事件被频繁处理。例如,按下F1,显示帮助信息;在文本编辑框中,按下回车键,输入焦点自动跳到另一控件。下面详细介绍键盘事件。

    1.设置输入焦点
    在某一时刻,只有一个控件(或根本没有)可以获得输入焦点。指定输入焦点可使用QWidget的下列方法:
  • setFocus([reason]) - 如果控件在活动窗口中,调用此方法后,该控件成为输入焦点。reason参数可为QtCore.Qt类中的以下枚举变量:
    • MouseFocusReason(0):使用鼠标获得焦点;
    • TabFocusReason(1):按下了键;
    • BacktabFocusReason(2):按下了+组合键;
    • ActiveWindowFocusReason(3):窗口变为活动和非活动;
    • PopupFocusReason(4):打开或关闭弹出窗口;
    • ShortcutFocusReason(5):按下快捷键;
    • MenuBarFocusReason(6):通过菜单操作;
    • OtherFocusReaaon(7):其他方式。
  • clearFocus() - 去除输入焦点;
  • hasFocus() - 如果控件是输入焦点,返回True;否则,返回False;
  • focusWidget() - 返回最后调用setFocus()方法的控件对象;
  • setFocusProxy() - 指定获得输入焦点的控件对象;
  • focusProxy() - 返回获得非当前控件的输入焦点的控件对象;
  • focusNextChild() - 找到下一个可获得输入焦点的控件对象,并设置为输入焦点。相当于按了键。如果有此控件,返回True;否则,返回False;
  • focusPreviousChild() - 找到上一个可获得输入焦点的控件对象,并设置为输入焦点。相当于按了+键。如果有此控件,返回True;否则,返回False;
  • focusNextPrevChild() -  如果isnext参数为True,功能相当于focusNextChild();如果isnext参数为False,功能相当于focusPreviousChild();
  • setTabOrder(,) - 静态函数。用于指定按下键时,输入焦点的移动顺序。component2是当输入焦点在component1是按下键后的输入焦点所在的控件。如果有多个控件,则需要调用多次。例如,指定输入焦点在按下键的变化顺序为widget1->widget2->widget3->widget4,相应的代码为:
    QtWidgets.QWidget.setTabOrder(
    widget1,widget2)
    QtWidgets.QWidget.setTabOrder(widget2,widget3)
    QtWidgets.QWidget.setTabOrder(widget3,widget4)
  • setFocusPolicy () - 指定控件如何获得输入焦点。Method可以QtCore.Qt类以一的枚举对象:
    • nofocus(0):不能获得输入焦点;
    • TabFocus(1):用键获得;
    • ClickFocus(2):用点击鼠标获得;
    • strongFocus(11):用键和点击鼠标获得;
    • wheelFocus(15):用键、点击鼠标和滚轮获得;
  • focusPolicy():返回当前获得输入焦点的方式;
  • grabKeyboard():限定键盘输入。在调用releaseKeyboard()之前,其他控件无法获得输入焦点;
  • releaseKeyboard():释放之前所作的键盘输入限定。 
    QApplication类的静态方法focusWidget()返回拥有键盘输入焦点的应用程序顶级窗口。如果还有,返回None.
    QWidget类的下列方法可用来处理焦点事件:
  • focusInEvent(self, event) - 获得焦点时被调用;
  • focusOutEvent(self,even) - 失去焦点时被调用;
    event参数为QFocusEvent类的实例,有以下方法:
  • gotFocus() - 如果event的类型为QEvent.FocusIn,返回True,否则,返回False;
  • lostFocus() - 如果event的类型为QEvent.FocusOut,返回True,否则,返回False;
  • reason() - 返回设置输入焦点的原因。
下面的代码为:
     创建一个带有按钮和两个单行编辑框的窗口。 对于 单行编辑框,我们处理获得和失去输入焦点的事件。通过按下按钮,我们将输入焦点设置为第二个 单行编辑框。 另外,通过按键可切换输入焦点。
# -*- coding: utf-8 -*-
from PyQt5 import QtWidgets

class MyLineEdit(QtWidgets.QLineEdit):
    def __init__(self, id, parent=None):
        QtWidgets.QLineEdit.__init__(self, parent)
        self.id = id
    def focusInEvent(self, e):
        print("输入焦点在", self.id)
        QtWidgets.QLineEdit.focusInEvent(self, e)
    def focusOutEvent(self, e):
        print(self.id,"失去输入焦点")
        QtWidgets.QLineEdit.focusOutEvent(self, e)

class MyWindow(QtWidgets.QWidget):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)
        self.resize(300, 100)
        self.button = QtWidgets.QPushButton("设置输入焦点在编辑框 2")
        self.line1 = MyLineEdit(1)
        self.line2 = MyLineEdit(2)
        self.vbox = QtWidgets.QVBoxLayout()
        self.vbox.addWidget(self.button)
        self.vbox.addWidget(self.line1)
        self.vbox.addWidget(self.line2)
        self.setLayout(self.vbox)
        self.button.clicked.connect(self.on_clicked)
        # 指定顺序
        QtWidgets.QWidget.setTabOrder(self.line1, self.line2)
        QtWidgets.QWidget.setTabOrder(self.line2, self.button)
    def on_clicked(self):
        self.line2.setFocus()

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.show()
    sys.exit(app.exec_())

    2.设置快捷键
    快捷键(也要称热键)一些特别键的组合,用来快速设置输入焦点。按下输入焦点所在按钮的快捷键,按钮将被按下。
    要设置快捷键,需要在相应字母前加上“&”,程序运行后,在相应字母下加上下划线以提示用户。 按下+带下划线的字母,对应的控件获得输入焦点。对于编辑框这类没有文本的控件,在设置快捷键时,要先创建一个QLabel对象,并通过调用 setBuddy(component)与控件相关联。如果不想创建QLabel对象,可使用QWidget的下列方法:
  • grabShortcut (Keys [,Context]) - 登记快捷键,返回一个标识符。参数Keys为QKeySequence对象。设置+快捷键的Keys设置方式为:
    • QtQui.QKeySequence.mmemonic("&e")
    • QtGui.QKeySequence("Alt+e")
    • QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_E)
          Context参数可设置为Qt中的枚举变量:WidgetShortcut、WidgetWithChildrenShortcut、WindowsShortcut(默认值 )和ApplicationShortcut。
  • releaseshortcut (ID) - 删除标识符为ID的组合键;
  • setShortcutEnabled(ID[,Flag]) -  Flag为True时,标识符为ID的组合键有效;否则,无效。
    按下快捷键时,产生QEvent.Shortcut事件,可在函数event(self,event)中处理。event参数是QShortcutEvent对象,有以下方法:
  • shortcutId():返回快捷键的标识符。
  • isAmbiguous():如果事件同时发送给几个控件,返回True;否则,返回Fasle.
  • key():返回代表所按下快捷键的QkeySequence对象。
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets

class MyLineEdit(QtWidgets.QLineEdit):
    def __init__(self, parent=None):
        QtWidgets.QLineEdit.__init__(self, parent)
        self.id = None
    def event(self, e):
        if e.type() == QtCore.QEvent.Shortcut:
            if self.id == e.shortcutId():
                self.setFocus(QtCore.Qt.ShortcutFocusReason)
                return True
        return QtWidgets.QLineEdit.event(self, e)

class MyWindow(QtWidgets.QWidget):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)
        self.resize(300, 100)
        self.label = QtWidgets.QLabel("(&E)设置输入焦点在编辑框1")
        self.lineEdit1 = QtWidgets.QLineEdit()
        self.label.setBuddy(self.lineEdit1)
        self.lineEdit2 = MyLineEdit()
        self.lineEdit2.id = self.lineEdit2.grabShortcut(
                            QtGui.QKeySequence.mnemonic("&D"))
        self.button = QtWidgets.QPushButton("(&R)删除编辑框1的输入焦点")
        self.vbox = QtWidgets.QVBoxLayout()
        self.vbox.addWidget(self.label)
        self.vbox.addWidget(self.lineEdit1)
        self.vbox.addWidget(self.lineEdit2)
        self.vbox.addWidget(self.button)
        self.setLayout(self.vbox)
        self.button.clicked.connect(self.on_clicked)
    def on_clicked(self):
        self.lineEdit1.clearFocus()

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.show()
    sys.exit(app.exec_())

    除了上面介绍的方式,还可以通过QtWidgets模块中的QShortcut类来实现:
self.lineEdit2 = QtWidgets.QLineEdit()
self.shc = QtWidgets.QShortcut(QtGui.QKeySequence.mnemonic("&D"), self)
self.shc.setContext(QtCore.Qt.WindowShortcut)
self.shc.activated.connect(self.lineEdit2.setFocus)
    或者使用 QtWidgets模块中的QAction类来实现:
self.lineEdit2 = QtWidgets.QLineEdit()
self.act = QtWidgets.QAction(self)
self.act.setShortcut(QtGui.QKeySequence.mnemonic("&е"))
self.act.triggered.connect(self.lineEdit2.setFocus)
self.addAction(self.act)

    3.按下并释放键
    按下并释放键时,以下方法将被调用:
  • keyPressEvent(self,event) - 按下某一键时,该方法被调用直到键被释放为止;
  • keyReleaseEvent(self,event) - 释放之前按下的键时被调用。event参数为QKeyEvent对象,包括事件的相关信息,有以下方法可调用。(详见QKeyEvent文档http://doc.qt.io/qt-5/qkeyevent.html)
  • key():返回按下键的值;
  • text():返回按下键的Unicode字符编码信息,当按键为Shift, Control, Alt等时,则该函数返回的字符为空值;
  • modifiers():判断按下了哪些修饰键(Shift,Ctrl , Alt,等等)。返回值为QtCore.Qt 类以下枚举变量的组合:
    • NoModifier - 没有修饰键;
    • ShiftModifier - 修饰键;
    • ControlModifier - 修饰键;
    • AltModifier - 修饰键;
    • MetaModifier - 修饰键;
    • KeypadModifier - 附加键盘上的任何按键
    • GroupSwitchModifier - 按下键(仅限X11系统)。
  • isAutoRepeat(): 如果一直按着某键,返回True;否则,返回False;
  • match(QKeySequence.StandardKey key): 如果当前的键组合与key相同,返回True;否则,返回False. 比如,是否按下了复制快捷键的代码:
    if e.matches(QtGui.QKeySequence.Copy):
        print("组合键为 +")
    处理键盘按键时,要注意以下几点:
  • 控件必须可以设置为输入焦点。有些控件,如QLabel是不能接受输入焦点的。
  • 捕获键盘事件要使用grabKeyboard( )方法,释放时,调用rekeaseKeyboard().
  • 可能拦截除和+以外的任何键。要拦截这两个键,只能在event(self,event)中完成。
  • 如果要让父控件继续收到键盘事件,要调用事件的ignore()方法;否则,调用accept()

你可能感兴趣的:(Python)