PyGTK3: улавяне на низ от клавиатурата

Имах някакъв код, написан на python3, използвайки GTK3. Програмата изчака някои входове от клавиатурата. Например, ако натисна 'q', програмата отпечата определен символ и т.н. Този код изглежда така

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

Искам да изпълня функция за обратно извикване, когато програмата улови конкретен низ, напр. когато натисна, да речем, 'q' и 'w' паралелно (натиснах 'w', без да напускам клавиша 'q'), тогава програмата изпълнява специфична функция. Не намерих нищо в GTK3, освен метод, наречен Gdk.utf8_to_string_target(event.string), но не успях да го използвам правилно. За натискане на два знака като ctrl и 'h' е лесно с помощта на нещо подобно

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

Проверих привидно подобен въпрос Откриване на конкретни натискания на клавиши в 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')

Някакви идеи? Моля, ако е възможно, дайте някакъв код, за да докажете мнението си!


person 111    schedule 28.12.2018    source източник


Отговори (3)


има функция (в gtk), която е нещо подобно на вашите нужди..

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

той свързва ключ и key-mod (https://github.com/bstpierre/gtk-examples/blob/master/c/accel.c)

ако наистина искате да заснемете низ, можете да опитате да пресъздадете функцията, дадена в gtk_accel_group

източникът може да бъде намерен в git (това е c-source кодът https://github.com/GNOME/gtk/blob/master/gtk/gtkaccelgroup.c)

person Siva Guru    schedule 28.12.2018

Трябва да създадете свой личен "буфер", който ще "буферира" натисканията на клавиши и ще проверява при всяко натискане на клавиш дали тези натискания на клавиши отговарят на желаните критерии. Не забравяйте да изпразните буфера, ако критериите не отговарят...

Също така имайте предвид, че вашият код не връща Unicode знаците. Така че бъдете готови да загубите малко публика...

За да получите символа на Unicode, трябва да използвате chr(Gdk.keyval_to_unicode(event.keyval)).

person ilias iliadis    schedule 21.10.2019

Ускорителят може да е по-добро решение но следенето на натиснати и отпуснати клавиши може да е по-близо до това, от което се нуждаете.

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()
person pan-mroku    schedule 02.01.2019