网站首页 > 技术教程 正文
在一个GUI桌面应用中,用户和程序之间的交互一般通过键盘和鼠标来完成,处理有关键盘和鼠标的事件是一个GUI程序几乎不可或缺的部分,下面介绍在Qt中处理输入焦点和键盘事件的相关知识。
设置控件的输入焦点
在一个窗口中,一般会有多个控件在其中,如果一个控件要获得键盘输入信息,必须将输入焦点设置到该控件上,在窗口中,一个时刻只有一个(或者没有) 控件可以获得输入焦点。可以使用QWidget的下列方法来操作控件的输入焦点。
- setFocus([reason]):- 如果控件在活动窗口中,调用此方法后,该控件成为输入焦点。reason参数可为Qt.FoucsReason中的以下枚举变量。
- MouseFocusReason (0): 使用鼠标获得焦点;
- TabFocusReason (1): 按下了Tab键;
- BacktabFocusReason (2): 按下了组合键+Tab键,组合键包括Shift或Control, 例如Shift+Tab;
- ActiveWindowFocusReason (3): 窗口变为活动和非活动;
- PopupFocusReason (4): 打开或关闭弹出窗口;
- ShortcutFocusReason (5): 按下快捷键;
- MenuBarFocusReason (6): 通过菜单操作;
- OtherFocusReaaon (7): 其他方式。
- clearFocus(): 清除输入焦点;
- hasFocus(): 如果控件是输入焦点,返回True;否则,返回False;
- focusWidget(): 返回最后调用setFocus()方法的控件对象;
- setFocusProxy(): 指定获得输入焦点的控件对象;
- focusProxy(): 返回获得非当前控件的输入焦点的控件对象;
- focusNextChild(): 找到下一个可获得输入焦点的控件对象,并设置为输入焦点。相当于按了Tab键。如果有此控件,返回True;否则,返回False;
- focusPreviousChild(): 找到上一个可获得输入焦点的控件对象,并设置为输入焦点。相当于按了Shift+Tab键。如果有此控件,返回True;否则,返回False;
- focusNextPrevChild(): 如果isnext参数为True,功能相当于focusNextChild();如果isnext参数为False,功能相当于focusPreviousChild();
- setTabOrder(,) - 静态函数。用于指定按下键时,输入焦点的移动顺序。component2是当输入焦点在component1是按下键后的输入焦点所在的控件。如果有多个控件,则需要调用多次。例如,指定输入焦点在按下键的变化顺序为widget1->widget2->widget3->widget4,相应的代码为:
QWidget.setTabOrder(widget1,widget2)
QWidget.setTabOrder(widget2,widget3)
QWidget.setTabOrder(widget3,widget4)
- setFocusPolicy ():指定控件如何设置输入焦点。method可以Qt.FocusPolicy中的以下枚举变量:
- NoFocus: 不能设置输入焦点;
- TabFocus: 用Tab键设置输入焦点;
- ClickFocus: 用点击鼠标来设置输入焦点;
- StrongFocus: 用Tab键和点击鼠标来设置焦点;
- WheelFocus:用Tab键、点击鼠标和滚轮来设置焦点。
- 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(): 返回设置输入焦点的原因。
焦点设置测试
在测试代码中,我们创建一个带有QPushButton按钮和两个QLineEdit单行编辑的窗口。对于单行编辑框,处理获得和失去输入焦点的事件。通过按下按钮,我们将输入焦点设置为第二个单行编辑框。 另外,通过Tab键顺向切换焦点,或者通过S hift+Tab反向切换焦点。完整代码如下:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget,
QLineEdit, QPushButton, QVBoxLayout, QFormLayout)
class MyLineEdit(QLineEdit):
def __init__(self, id, parent=None):
super(MyLineEdit, self).__init__(parent)
self.id = id
#焦点进入事件
def focusInEvent(self, evt):
print('输入焦点在:', self.id)
QLineEdit.focusInEvent(self, evt)
#焦点离开事件
def focusOutEvent(self, evt):
print(self.id, ':失去输入焦点')
QLineEdit.focusOutEvent(self, evt)
class FocusSetDemo(QMainWindow):
def __init__(self, parent = None):
super(FocusSetDemo, self).__init__(parent)
# 设置窗口标题
self.setWindowTitle('实战PyQt5:焦点设置演示')
# 设置窗口大小
self.resize(300, 200)
self.initUi()
def initUi(self):
mainWidget = QWidget()
mainLayout = QVBoxLayout()
mainLayout.setSpacing(10)
btnChangeFocus = QPushButton('将焦点设置到编辑框2')
btnChangeFocus.clicked.connect(self.onButtonChangeFocus)
self.lineEdit1 = MyLineEdit(1)
self.lineEdit2 = MyLineEdit(2)
fLayout = QFormLayout()
fLayout.addRow('编辑框1', self.lineEdit1)
fLayout.addRow('编辑框2', self.lineEdit2)
mainLayout.addWidget(btnChangeFocus)
mainLayout.addLayout(fLayout)
mainWidget.setLayout(mainLayout)
self.setCentralWidget(mainWidget)
def onButtonChangeFocus(self):
self.lineEdit2.setFocus()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = FocusSetDemo()
window.show()
sys.exit(app.exec())
运行结果如下图:
快捷键设置
快捷键(也称热键)是GUI程序交互操作的一种常见功能,在一个GUI应用的系统菜单里,我们常常可以见到菜单项有对应的快捷键操作。快捷键用来快速设置输入焦点,要设置快捷键,可以在相应的字母上加上“&”,程序运行后,会在相应的字母下加下划线以提示用户。按下Alt+带下划线的字母,对应的控件即可获得输入焦点,执行相应动作。
对于编辑框这类没有文本的控件,在设置快捷键时,可以创建一个QLabel对象,并通过调用setBuddy(component)与控件相关联。如果不创建QLabel对象,则可以使用QWidget的下列的方法来设置和管理快捷键:
- grabShortcut (keys [,context]): 登记快捷键,返回一个标识符。参数keys为QtGui.QKeySequence对象。设置控制键+快捷键的Keys设置方式为:
- QKeySequence.mnemonic("&e")
- QKeySequence("Alt+e")
- QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_E)
context参数可以是Qt.ShortcutContext中的枚举变量: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对象。
快捷键设置测试
测试代码演示了直接为按钮设置快捷键,使用QLabel.setBuddy()方法为编辑框1设置快捷键和使用QWidget. grabShortcut为编辑框2设置快捷键,完整演示代码如下:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QEvent
from PyQt5.QtGui import QKeySequence
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QLabel,
QLineEdit, QPushButton, QVBoxLayout, QFormLayout)
class MyLineEdit(QLineEdit):
def __init__(self, parent = None):
super(MyLineEdit, self).__init__(parent)
self.id = None
def event(self, evt):
if evt.type() == QEvent.Shortcut:
if self.id == evt.shortcutId():
self.setFocus(Qt.ShortcutFocusReason)
return True
return QLineEdit.event(self, evt)
class FocusSetDemo(QMainWindow):
def __init__(self, parent = None):
super(FocusSetDemo, self).__init__(parent)
# 设置窗口标题
self.setWindowTitle('实战PyQt5: 快捷键设置演示')
# 设置窗口大小
self.resize(360, 240)
self.initUi()
def initUi(self):
mainWidget = QWidget()
mainLayout = QVBoxLayout()
mainLayout.setSpacing(10)
btnClearFocus = QPushButton('(&R)清除编辑框1的输入焦点')
btnClearFocus.clicked.connect(self.onButtonClearFocus)
label1 = QLabel('编辑框1(&E)')
self.lineEdit1 = MyLineEdit()
self.lineEdit1.setText('test1')
label1.setBuddy(self.lineEdit1)
self.lineEdit2 = MyLineEdit()
self.lineEdit2.setText('test2')
self.lineEdit2.id = self.lineEdit2.grabShortcut(QKeySequence.mnemonic('&D'))
fLayout = QFormLayout()
fLayout.addRow(label1, self.lineEdit1)
fLayout.addRow('编辑框2', self.lineEdit2)
mainLayout.addWidget(btnClearFocus)
mainLayout.addLayout(fLayout)
mainWidget.setLayout(mainLayout)
self.setCentralWidget(mainWidget)
def onButtonClearFocus(self):
self.lineEdit1.clearFocus()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = FocusSetDemo()
window.show()
sys.exit(app.exec())
运行结果如下图所示:
按键事件
按下并释放键盘按键时,以下方法将被调用:
- keyPressEvent(self,event): 按下某一键时,该方法被调用直到键被释放为止;
- keyReleaseEvent(self,event) - 释放之前按下的键时被调用。
上述方法中的event参数为QKeyEvent对象,其常用方法有:
- key(): 返回按下键的值;
- text(): 返回按下键的Unicode字符编码信息,当按键为Shift, Control, Alt等时,则该函数返回的字符为空值。
- modifiers(): 判断按下了哪些修饰键(Shift,Ctrl,Alt,等等)。返回值为Qt. KeyboardModifier 中下列枚举变量的组合:
- NoModifier - 没有修饰键;
- ShiftModifier - Shift修饰键;
- ControlModifier - Ctrl修饰键;
- AltModifier - Alt修饰键;
- MetaModifier - 组合修饰键;
- KeypadModifier - 附加键盘上的任何按键;
- GroupSwitchModifier - 按下键(仅限X11系统)。
- isAutoRepeat(): 如果一直按着某键,返回True;否则,返回False;
- match(QKeySequence.StandardKey key): 如果当前的键组合与key相同,返回True;否则,返回False。
比如,是否按下了复制快捷键的代码:
if e.matches(QKeySequence.Copy):
print("组合键为",QKeySequence.Copy)
处理键盘按键时,需要注意以下几点:
- 控件必须可以设置为输入焦点。有些控件,如QLabel是不能接受输入焦点的;
- 捕获键盘事件要使用grabKeyboard( )方法,释放时,调用rekeaseKeyboard();
- 可能拦截除Tab键和Shift+Tab键以外的任何键。因为默认Tab /Shift+Tab事件(切换焦点)被先捕获了, 要拦截这两个键,只能在event(self,event)中完成;
- 如果要让父控件继续收到键盘事件,要调用事件的ignore()方法;否则,调用accept()。
测试按键事件
测试代码演示里使用keyPressEvent和event来捕获键盘按下事件,并使用paintEvent将其显示在窗口中央。完整代码如下:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QEvent
from PyQt5.QtGui import QPainter, QPen, QFont
from PyQt5.QtWidgets import QApplication, QWidget
class DemoKeyboardEvent(QWidget):
def __init__(self, parent=None):
super(DemoKeyboardEvent, self).__init__(parent)
# 设置窗口标题
self.setWindowTitle('实战PyQt5: 键盘按键事件演示')
# 设置窗口大小
self.resize(400, 320)
self.key=''
#重绘窗口事件
def paintEvent(self, event):
painter = QPainter(self)
painter.setFont(QFont(self.font().family(), 36))
painter.setPen(QPen(Qt.blue))
painter.setRenderHint(QPainter.TextAntialiasing)
#居中绘制文本信息
painter.drawText(self.rect(), Qt.AlignCenter, self.key)
#键盘按键事件
def keyPressEvent(self, event):
self.key = ''
if event.key() == Qt.Key_Home:
self.key = 'Home'
elif event.key() == Qt.Key_End:
self.key = 'End'
elif event.key() == Qt.Key_PageUp:
if event.modifiers() & Qt.ControlModifier:
self.key = "Ctrl+PageUp"
else:
self.key = "PageUp"
elif event.key() == Qt.Key_PageDown:
if event.modifiers() & Qt.ControlModifier:
self.key = "Ctrl+PageDown"
else:
self.key = "PageDown"
elif Qt.Key_0 <= event.key() <= Qt.Key_9:
self.key = event.text()
elif Qt.Key_A <= event.key() <= Qt.Key_Z:
if event.modifiers() & Qt.ShiftModifier:
self.key = "Shift+"
self.key += event.text()
#如果key有字符,不为空,则绘制字符
if self.key:
self.update()
#否则就继续监视这个事件
else:
QWidget.keyPressEvent(self, event)
#Tab键由于涉及焦点切换,不会传递给keyPressEvent,因此,需要在这里重新定义。
def event(self, event):
#如果有按键按下,并且按键是tab键
if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab:
self.key = "Tab"
self.update()
return True
return QWidget.event(self, event)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = DemoKeyboardEvent()
window.show()
sys.exit(app.exec())
测试结果如下图:
本文知识点
- 焦点事件;
- 快捷键设置;
- 键盘按下和释放事件;
- 使用QPainter 绘制指定样式的文字信息。
喜欢本文内容就关注, 收藏,点赞,评论和转发。
猜你喜欢
- 2024-10-10 WordPress备份插件 wordpress整站备份
- 2024-10-10 新年潜水的50种玩法,看看你玩过几种
- 2024-10-10 如何手动备份WordPress数据库 wordpress数据库迁移
- 2024-10-10 狗眼一睁:“我咋住进白宫了??” 狗眼看阴阳3
- 2024-10-10 数据丢失?这5大网站备份插件请收下
- 2024-10-10 WordPress注册邀请码插件:Ashuwp Invitation Code
- 2024-10-10 WordPress 5.2 “Jaco”提供更多开发者福利,对系统要求也更高
- 2024-10-10 谈一谈WEB3.0的CMS web3.0的本质是什么
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- sd分区 (65)
- raid5数据恢复 (81)
- 地址转换 (73)
- 手机存储卡根目录 (55)
- tcp端口 (74)
- project server (59)
- 双击ctrl (55)
- 鼠标 单击变双击 (67)
- debugview (59)
- 字符动画 (65)
- flushdns (57)
- ps复制快捷键 (57)
- 清除系统垃圾代码 (58)
- web服务器的架设 (67)
- 16进制转换 (69)
- xclient (55)
- ps源文件 (67)
- filezilla server (59)
- 句柄无效 (56)
- word页眉页脚设置 (59)
- ansys实例 (56)
- 6 1 3固件 (59)
- sqlserver2000挂起 (59)
- vm虚拟主机 (55)
- config (61)
本文暂时没有评论,来添加一个吧(●'◡'●)