【问题标题】:How to get key events when using enaml?使用 enaml 时如何获取关键事件?
【发布时间】:2013-12-04 16:38:52
【问题描述】:

我一直在使用 enaml(0.6.8,目前 Canopy 可用)并成功创建了一些非常有用的实用程序应用程序。但是,我想拦截键盘事件以启用一些快速键盘快捷键,而不是在 UI 中重复单击按钮。

我该如何处理?我知道这将是特定于工具包(qt4)的,但无法真正弄清楚从哪里开始。我在 qt 中阅读了一些关于 event filters 的内容,这似乎是我想要的,但我不明白将 QApplication 等与 enaml 相关联的机制

【问题讨论】:

    标签: python qt canopy enaml


    【解决方案1】:

    目前不支持拦截原始键事件,除非您想通过foo.proxy.widget 直接使用工具包小部件(在 0.7+ 系列上;不再支持 0.6 系列)。但是,您可以使用支持由自定义操作名称(例如“Cut\tCtrl+C”和“Paste\tCtrl+V”)触发的加速键的 Actions 定义 MenuBar。

    【讨论】:

    • 感谢克里斯,感谢您的帮助。我想我现在可以使用 MenuBar。看起来我只需要定义不与系统标准重叠的加速键(即 Ctrl+X 等),以防焦点位于与文本相关的控件中(好吧,在 Mac OS 上也不是 Ctrl+Q) .我一直在关注 Enaml 和 Atom 的进展,并希望很快看到 Canopy 包管理器支持更高版本,否则我将硬着头皮自己安装它们。事实证明,Enaml 对我来说非常强大,而且是一个了不起的贡献。
    【解决方案2】:

    我创造了一种相当粗糙的方法来做到这一点。使用以下内容创建一个名为 key_event.py 的文件:

    # -*- coding: utf-8 -*-
    '''
    Created on Jul 20, 2015
    @author: jrm
    '''
    from atom.api import (Callable,Event, Value, Unicode, Bool, Instance,Typed, ForwardTyped, observe)
    from enaml.core.declarative import d_
    from enaml.widgets.control import Control, ProxyControl
    from enaml.qt.qt_control import QtControl
    from enaml.qt import QtCore
    
    class ProxyKeyEvent(ProxyControl):
        declaration = ForwardTyped(lambda: KeyEvent)
    
        def set_enabled(self, enabled):
            raise NotImplementedError
    
    class KeyEvent(Control):
        proxy = Typed(ProxyKeyEvent)
    
        key_code = d_(Value())
        key = d_(Unicode())
        enabled = d_(Bool(True))
        repeats = d_(Bool(True))
    
        pressed = d_(Event(),writable=False)
        released = d_(Event(),writable=False)
    
        @observe('enabled')
        def _update_proxy(self, change):
            """ An observer which sends state change to the proxy.
            """
            super(KeyEvent, self)._update_proxy(change)
    
    class QtKeyEvent(QtControl, ProxyKeyEvent):
        _keyPressEvent = Callable() # Refs to original functions
        _keyReleaseEvent = Callable() # Refs to original functions
        widget = Instance(QtCore.QObject)
    
        def create_widget(self):
            self.widget = self.parent_widget()
        def init_widget(self):
            super(QtKeyEvent, self).init_widget()
            d = self.declaration
            widget = self.parent_widget()
            self._keyPressEvent = widget.keyPressEvent
            self._keyReleaseEvent = widget.keyPressEvent
            self.set_enabled(d.enabled)
    
        def set_enabled(self, enabled):
            widget = self.parent_widget()
            if enabled:
                widget.keyPressEvent = lambda event:self.on_key_press(event)
                widget.keyReleaseEvent = lambda event:self.on_key_release(event)
            else:
                # Restore original
                widget.keyPressEvent = self._keyPressEvent
                widget.keyReleaseEvent = self._keyReleaseEvent
    
        def on_key_press(self,event):
            try:
                if (self.declaration.key_code and event.key()==self.declaration.key_code) or \
                    (self.declaration.key and self.declaration.key in event.text()):
                    if not self.declaration.repeats and event.isAutoRepeat():
                        return
                    self.declaration.pressed(event)
            finally:
                self._keyPressEvent(event)
    
        def on_key_release(self,event):
            try:
                if (self.declaration.key_code and event.key()==self.declaration.key_code) or \
                    (self.declaration.key and self.declaration.key in event.text()):
                    if not self.declaration.repeats and event.isAutoRepeat():
                        return
                    self.declaration.released(event)
            finally:
                self._keyReleaseEvent(event)
    
    def key_event_factory():
        return QtKeyEvent
    # Inject the factory 
    from enaml.qt.qt_factories import QT_FACTORIES
    QT_FACTORIES['KeyEvent'] = key_event_factory
    

    在您的 enaml 文件中导入 KeyEvent 并像这样使用:

    WidgetToWatchKeys:
      KeyEvent:
        key_code = QtCore.Qt.Key.Key_Up
        pressed :: model.move_up()
    
      KeyEvent:
        key_code = QtCore.Qt.Key.Key_Left
        pressed :: model.move_left()
    
      KeyEvent:
        key = 'x'
        pressed :: model.fire()
      #: etc...
    

    可能不是最好的方法,但它可以满足我的需求。

    【讨论】:

    • 仅供参考,供其他人玩这个并从.py 文件启动他们的应用程序,您必须在导入视图之前放置最后两行(from enaml... import QT_FACTORIES.....)(使用with enaml.imports():...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-29
    • 2011-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-09
    相关资源
    最近更新 更多