【问题标题】:How can I use Glib.timeout_add() function to wait a keypress event如何使用 Glib.timeout_add() 函数来等待按键事件
【发布时间】:2018-02-06 15:51:22
【问题描述】:

我正在尝试创建一个测试应用程序。应用程序应在目录中列出图像,在屏幕上显示第一个图像,获取键盘响应并显示第二个图像,获取响应,并对每个图像执行此操作。

我创建了一个 glade 文件,并使用它在 RavensAPM 类中创建接口。林间空地文件中有一个Gtk.Window,其中包含一个Gtk.Box,而后者又包含一个Gtk.Image。我使用run_ravens_apm() 函数列出图像并将图像一张一张地提供给RavensAPM 类。在RavensAPM 类中,我更新图像并使用show_all() 呈现所有内容。

此时我希望应用程序等待来自键 [1-8] 和键盘键 [1-8] 的按键事件。

我检查了GLib.timeout_add() 函数的用法,但我无法从中获得所需的行为。目前,run_ravens_apm() 中的for 循环同时调用RavensAPM 并创建与图像数量一样多的窗口,而无需等待键盘信号/事件。

我尝试将GLib.timeout_add() 放在类的__call__() 方法中,并将类的实例用作函数,但它也不起作用。

我做错了什么?

class RavensAPM:
    def __init__(self, test_image):
        self.builder = Gtk.Builder()
        self.builder.add_from_file('glade/window_ravens_apm.glade')
        self.window = self.builder.get_object('window_ravens_apm')
        self.window.fullscreen()
        self.window.connect('key-release-event', self.on_event_after)

        window_height = 1080

        self.pixbuf_file = \
            GdkPixbuf.Pixbuf.new_from_file_at_scale(test_image,
                                                    -1,
                                                    window_height,
                                                    True)
        self.image = self.builder.get_object('ravens_apm_image')
        self.image.set_from_pixbuf(self.pixbuf_file)
        self.window.show_all()

    def on_event_after(self, widget, event):
        keys = [i for i in range(49, 57)] + [i for i in range(65457, 65465)]
        key_value = event.keyval
        if keys in key_value:
            self.window.destroy()
            return False

    def __call__(self):
        self.on_event_after()
        return True


def run_ravens_apm():
    # List the contents of img/ravens_apm
    # Use a loop to run RavensAPM for the length of images
    interval_ms = 200
    img_directory = 'img/ravens_apm'
    img_files = os.listdir(img_directory)
    img_files.sort()
    img_files = img_files[:2]
    nr_images = len(img_files)

    for i in range(nr_images):
        img_file = os.path.join(img_directory, img_files[i])
        ravens = RavensAPM(img_file)
        GLib.timeout_add(interval_ms, ravens)
        print('GLib.timeout_add must wait for Gdk.EventKey event')
        print(datetime.datetime.now())

glade 文件的内容如下。

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
  <requires lib="gtk+" version="3.12"/>
  <object class="GtkWindow" id="window_ravens_apm">
    <property name="can_focus">False</property>
    <signal name="key-press-event" handler="on_windows_ravens_apm_key_press_event" swapped="no"/>
    <child>
      <object class="GtkViewport" id="viewport1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkBox" id="box1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="orientation">vertical</property>
            <child>
              <object class="GtkImage" id="ravens_apm_image">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="stock">gtk-missing-image</property>
                <signal name="key-press-event" handler="on_ravens_apm_keypress" swapped="no"/>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
          </object>
        </child>
      </object>
    </child>
  </object>
</interface>

【问题讨论】:

  • 最重要的是,我要说的是您来自 Gtk 和 Python 以外的编程语言。请查看python-gtk-3-tutorial.readthedocs.io/en/latest/builder.html 以开始使用。
  • 这不是timeout_add 所做的。阅读 GLib 的主事件循环,您的按键事件处理程序基本上应该在您收到按键时交换图像。
  • 谢谢@nemequ。读完你的评论后,我意识到我必须做些什么。通过使用一个简单的回调方法,我创建了我想要的脚本。

标签: python-3.x gtk3 glib


【解决方案1】:

如果您需要更长的答案,我会在此处发布我的解决方案。很简单。现在我知道我一开始就不应该使用Glib.timeout_add() 函数。

#!/usr/bin/python3
import gi
import os
import random
from gi.repository import Gtk
from gi.repository import GdkPixbuf
# from gi.repository import Gdk
# from gi.repository import GLib
gi.require_version('Gtk', '3.0')


FAKING_FIRTS = None
WINDOW_HEIGHT = 1080


class RavensAPM:
    def __init__(self, img_list, window_height):
        self.img_list = img_list
        self.window_height = window_height

        self.builder = Gtk.Builder()
        self.builder.add_from_file('glade/window_ravens_apm.glade')

        self.window = self.builder.get_object('window_ravens_apm')
        self.window.connect('key-release-event', self.on_key_released)
        self.window.fullscreen()

        self.ravens_image = self.builder.get_object('ravens_apm_image')
        self.pixbuf_file = \
            GdkPixbuf.Pixbuf.new_from_file_at_scale(self.img_list[-1],
                                                    -1,
                                                    self.window_height,
                                                    True)
        self.ravens_image.set_from_pixbuf(self.pixbuf_file)

        self.window.show_all()

    def on_key_released(self, widget, event):
        key_value = event.keyval
        keys_list = list(range(49, 57)) + list(range(65429, 65436))
        if key_value in keys_list:
            # TODO
            # Do stg to save the keyvalue somewhere
            self.img_list.pop()
            self.pixbuf_file = \
                GdkPixbuf.Pixbuf.new_from_file_at_scale(self.img_list[-1],
                                                        -1,
                                                        self.window_height,
                                                        True)
            self.ravens_image = self.builder.get_object('ravens_apm_image')
            self.ravens_image.set_from_pixbuf(self.pixbuf_file)


def run_ravens_apm():
    img_directory = 'img/ravens_apm'
    img_files = os.listdir(img_directory)
    img_files.sort(reverse=True)
    img_files = [os.path.join(img_directory, i) for i in img_files]
    RavensAPM(img_files, WINDOW_HEIGHT)

这是我使用的 Glade 文件。

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
  <requires lib="gtk+" version="3.12"/>
  <object class="GtkWindow" id="window_ravens_apm">
    <property name="can_focus">False</property>
    <child>
      <object class="GtkViewport" id="viewport1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkBox" id="box1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="orientation">vertical</property>
            <child>
              <object class="GtkImage" id="ravens_apm_image">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="stock">gtk-missing-image</property>
                <signal name="key-press-event" handler="on_ravens_apm_keypress" swapped="no"/>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
          </object>
        </child>
      </object>
    </child>
  </object>
</interface>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-19
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    • 2013-03-02
    • 1970-01-01
    相关资源
    最近更新 更多