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') 

Я проверил, казалось бы, похожий вопрос Обнаружение определенных нажатий клавиш в графическом интерфейсе, но спрашивал о проверке, если нажимается специальная клавиша. Что не мой случай. В качестве минимального кода мы предоставляем следующее.

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

он связывает ключ и ключ-мод (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)

person Siva Guru    schedule 28.12.2018

Вы должны создать свой личный «буфер», который будет «буферизировать» нажатия клавиш и проверять при каждом нажатии клавиши, соответствуют ли эти нажатия желаемым критериям. Не забудьте очистить буфер, если критерии не соответствуют...

Также обратите внимание, что ваш код не возвращает символы Юникода. Так что будьте готовы потерять часть аудитории...

Чтобы получить символ Юникода, вы должны использовать 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