PyGTK3:从键盘上捕获字符串

时间:2018-12-28 00:35:56

标签: python-3.x gtk3 pygtk gdk

我有一些使用GTK3用python3编写的代码。程序等待键盘的一些输入。例如,如果我按“ q”,程序将打印一个特定的符号,等等。 这段代码看起来像

 keyname = Gdk.keyval_name(event.keyval)
 if keyname == 'q':
        self.textbuffer.insert_at_cursor('you've pressed q')

当程序捕获特定字符串时,我想执行一个回调函数。当我同时按下“ q”和“ w”(我按下“ w”而不离开键“ q”)时,程序将执行特定功能。 除了一个名为Gdk.utf8_to_string_target(event.string)的方法,我没有在GTK3中找到任何东西,但我没有正确使用它。要按下两个字符(例如ctrl和'h'),可以使用类似的

ctrl = (event.state & Gdk.ModifierType.CONTROL_MASK)
if ctrl and event.keyval == Gdk.KEY_h:
        self.textbuffer.insert_at_cursor('\n') 

我检查了一个看似相似的问题Detect specific keypresses in GUI,但询问是否要按特殊键。这不是我的情况。 作为最小的代码,我们提供了以下内容。

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import  Gtk, Gdk

class MyWindow(Gtk.Window):
    def __init__(self):

        Gtk.Window.__init__(self, title="awesome gui")
        self.set_resizable(True)
        self.set_default_size(700,550)
        self.grid = Gtk.Grid()
        self.add(self.grid)                        
        self.create_textview()
        self.create_buttons()

    def create_textview(self):

        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_hexpand(True)
        scrolledwindow.set_vexpand(True)
        self.grid.attach(scrolledwindow, 0, 1, 50, 1)
        self.textview = Gtk.TextView()
        scrolledwindow.add(self.textview)
        self.textbuffer = self.textview.get_buffer()
        self.textview.set_editable(False)
        self.textview.set_cursor_visible(False)

    def create_buttons(self):
        self.button1 = Gtk.Button(label="Clear text")   
        self.button1.connect("clicked", self.on_button1_clicked)
        self.grid.attach(self.button1, 0,  0, 1, 1)      
        self.button2 = Gtk.Button(label="Start capturing")
        self.button2.connect("key-release-event", self.on_key_release) 
        self.grid.attach_next_to(self.button2,self.button1,\
        Gtk.PositionType.RIGHT, 1, 1)  

    def on_button1_clicked(self, widget):
        self.textbuffer.set_text('')

    def on_key_release(self, widget, event, data=None):
        keyval = event.keyval       
        keyname = Gdk.keyval_name(keyval)
        ctrl = (event.state & Gdk.ModifierType.CONTROL_MASK)

        if keyval == Gdk.KEY_space: 
            self.textbuffer.insert_at_cursor(' ') #space

        if keyname == 'q':
            self.textbuffer.insert_at_cursor('you pressed q')

       # etc..

        if ctrl and keyval == Gdk.KEY_h:
            self.textbuffer.insert_at_cursor('\n') #change line when ctrl + h is pressed

win = MyWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

我的问题是,如果我可以拥有类似的东西

#you press q and after w or w and after q or the same time you press q and w
if keyname == 'qw': 
    self.textbuffer.insert_at_cursor('you pressed qw')

有什么想法吗?请,如果有可能,请提供一些代码来证明您的观点!

3 个答案:

答案 0 :(得分:1)

有一个函数(在gtk中),它与您的需求类似。

https://developer.gnome.org/gtk3/stable/gtk3-Keyboard-Accelerators.html#gtk-accel-group-connect

它连接一个键和一个键模(https://github.com/bstpierre/gtk-examples/blob/master/c/accel.c

如果您确实要捕获字符串,则可以尝试重新创建gtk_accel_group中提供的功能

可以在git中找到源代码(这是c源代码https://github.com/GNOME/gtk/blob/master/gtk/gtkaccelgroup.c

答案 1 :(得分:1)

您必须创建您的个人“缓冲区”,该缓冲区将“缓冲”按键并在每个步进按键中检查这些按键是否符合所需条件。如果条件不符合,请记住清空缓冲区...

还请注意,您的代码不会返回unicode字符。因此,准备放松一些听众...

要获取Unicode字符,必须使用chr(Gdk.keyval_to_unicode(event.keyval))

答案 2 :(得分:0)

Accelerator可能是更好的解决方案,但跟踪按键的按下和释放可能更接近您的需求。

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import  Gtk, Gdk

class MyWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title="awesome gui")
        self.set_resizable(True)
        self.set_default_size(700,550)
        self.grid = Gtk.Grid()
        self.add(self.grid)                        
        self.create_textview()
        self.create_buttons()
        self.buffer = []

    def create_textview(self):
        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_hexpand(True)
        scrolledwindow.set_vexpand(True)
        self.grid.attach(scrolledwindow, 0, 1, 50, 1)
        self.textview = Gtk.TextView()
        scrolledwindow.add(self.textview)
        self.textbuffer = self.textview.get_buffer()
        self.textview.set_editable(False)
        self.textview.set_cursor_visible(False)

    def create_buttons(self):
        self.button1 = Gtk.Button(label="Clear text")   
        self.button1.connect("clicked", self.on_button1_clicked)
        self.grid.attach(self.button1, 0,  0, 1, 1)      
        self.button2 = Gtk.Button(label="Start capturing")
        self.button2.connect("key-release-event", self.on_key_release)
        self.button2.connect("key-press-event", self.on_key_down)
        self.grid.attach_next_to(self.button2,self.button1,\
        Gtk.PositionType.RIGHT, 1, 1)  

    def on_button1_clicked(self, widget):
        self.textbuffer.set_text('')

    def on_key_release(self, widget, event, data=None):
        keyval = event.keyval       
        keyname = Gdk.keyval_name(keyval)
        ctrl = (event.state & Gdk.ModifierType.CONTROL_MASK)
        if keyname in self.buffer:
            self.buffer.remove(keyname)
            if self.buffer:
                self.textbuffer.insert_at_cursor('you released '+'+'.join(self.buffer)+'\n')

    def on_key_down(self, widget, event, data=None):
        keyval = event.keyval       
        keyname = Gdk.keyval_name(keyval)
        if keyname in 'wqs' and keyname not in self.buffer:
            self.buffer.append(keyname)
            if self.buffer:
                self.textbuffer.insert_at_cursor('you pressed '+'+'.join(self.buffer)+'\n')

win = MyWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()