Python gtk3 窗口监听输入事件

Posted

技术标签:

【中文标题】Python gtk3 窗口监听输入事件【英文标题】:Python gtk3 window listen to input events 【发布时间】:2017-05-25 07:38:47 【问题描述】:

python gtk3 Window 有什么方法可以捕获其中的键盘和/或鼠标的每个输入?

基本上我正在创建一个应用程序,它会在空闲时启动屏幕保护程序之类的东西,为此我需要知道我的窗口(应用程序)内发生键盘或鼠标事件的时间。

我试图将key-press-event 连接到我的窗口,但是当我点击它的子项时,就像一个按钮一样,窗口没有收到事件。

感谢您的任何解决方案。

更新 正如公认的答案所示,我将event-after 信号连接到主窗口,并确定我是否需要接收到的信号。

【问题讨论】:

我刚刚尝试了一个简单的示例(在 Vala 中),并且窗口一直在接收信号。我有一个带有垂直框容器的窗口,带有一个条目和一个按钮。信号总是在窗口上发出。必须在 python 上尝试,但行为将是相同的。你可以发布代码(如果小的话)? 很抱歉,应用程序很大,有 30 多个文件(类)。我确实尝试了一些代码测试,是的,窗口确实收到了信号。就我而言,我不知道如何解释,它有时会收到信号,有时却没有,点击同一个按钮。 可能不是这样,但有时只是一些回调的返回停止了信号的传播。 【参考方案1】:

也许首先记得有信号和事件。也许有些过于简单,事件是“原始的”:例如,它们来自键盘或鼠标。最顶部的小部件(考虑到窗口位于底部)接收这些事件并决定它是否对事件感兴趣。

如果小部件对事件感兴趣,比如按钮对按钮按下事件和按钮释放事件感兴趣,那么小部件就会创建信号,例如,在这种情况下,“点击”、“双击'信号。在事件处理程序内部,返回值(True 或 False)决定了事件是否会“向下”传播到下一个小部件(在顶部小部件的“下方”)。

因此,我怀疑您无法在底层窗口上直接监控所有事件,然后才能达到目标。

也许您的解决方案是连接到窗口的“事件之后”。这被独立于其他处理程序的返回值调用。下面是一个小程序,您可以在其中测试以下内容:

GtkGrid 出现时带有一个标签、一个按钮和一个 SpinButton。右下角单元格为空:

单击标签,事件会向下传递到窗口,因为标签不会捕获任何事件

点击按钮,事件(如'pressed')被handler捕获,并产生'clicked'等信号。

我连接到“事件后”,并报告在任意位置按下按钮。

.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
#  test_events.py
#
#  Copyright 2017 John Coppens <john*at*jcoppens*dot*com>
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#
#


from gi.repository import Gtk

class EventsTest(Gtk.Grid):
    def __init__(self):
        super(EventsTest, self).__init__()

        btn = Gtk.Button("Top right")
        btn.connect("clicked", lambda x: print("Button clicked"))

        self.attach(Gtk.Label("Top left"), 0, 0, 1, 1)
        self.attach(btn, 1, 0, 1, 1)
        self.attach(Gtk.SpinButton(), 0, 1, 1, 1)


class MainWindow(Gtk.Window):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.connect("destroy", lambda x: Gtk.main_quit())
        self.connect("button-press-event", self.on_button_pressed)
        self.connect("event-after", self.on_event_after)

        evtest = EventsTest()

        self.add(evtest)
        self.show_all()

    def on_button_pressed(self, btn, event):
        print("Main window button pressed")
        return True

    def on_event_after(self, wdg, event):
        print("Event after")

    def run(self):
        Gtk.main()


def main(args):
    mainwdw = MainWindow()
    mainwdw.run()

    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

【讨论】:

是的,这会将我需要通知eventuser activity 的信号发送到主窗口。谢谢。 我认为还有注册回调而不是继承Gtk.Window的方法。也就是说,您将实例化一个像window = Gtk.Window() 这样的窗口来执行类似window.connect('button-press-event', ....) 的操作,而不是将您的代码封装在一个子类Gtk.Window 中。可能很快就会遇到利弊。 是的,当然。这是多年来的一个长期争论。实例化(有时称为组合)而不是子类化——已经有很多关于这个的讨论,包括堆栈溢出和其他地方。【参考方案2】:

key-press-event 仅适用于键盘。一个按钮创建一个button-press-event。请参阅docs。

永远记住*-press-event 在操作完成之前运行。我建议您使用*-release-event,如果您不小心点击了按钮,您可以在释放之前滑出按钮。这在您的情况下并不重要,但仍然......

【讨论】:

以上是关于Python gtk3 窗口监听输入事件的主要内容,如果未能解决你的问题,请参考以下文章

Perl/Gtk3,给窗口添加背景图片

pyHook无法监听键盘事件?

TPM 程序设计基础 3-2 :GTK3 窗口与控件

GTK3 - 如何将窗口发送到后台

jquery resize 如何监听div或其它元素的resize事件

使用 Gtk3 和 Cairo 绘制到 GdkWindow 根窗口