#python #libreoffice
#python #libreoffice
Вопрос:
Пожалуйста, обратите внимание, что это вопрос с самостоятельным ответом для справки. Я не нашел его документированным для python, несмотря на тщательный поиск.
Вместо того, чтобы создавать прослушиватель для определенного элемента в диалоговом окне, я хочу «прослушать» ввод с клавиатуры для текстового документа. Цель состоит в том, чтобы выполнить действие, если видны определенные клавиши или комбинации.
Создав следующий код с использованием Uno com.sun.star.awt XKeyListener
, я ожидал увидеть хотя бы какое-то указание на то, что он функционирует.
import unohelper
from com.sun.star.awt import XKeyListener
def fs_listen(*args):
doc = XSCRIPTCONTEXT.getDocument()
desktop = XSCRIPTCONTEXT.getDesktop()
model = desktop.getCurrentComponent()
contr = model.getCurrentController()
url_current = doc.getLocation()
oEventListener = KeyListen(doc)
contr.addEventListener(oEventListener)
class KeyListen(unohelper.Base, XKeyListener):
def __init__(self, parent):
self.parent = parent
print("listener added")
def keyPressed( self, event ):
""" is invoked when a key has been pressed."""
print("event",event)
def keyReleased( self, event ):
""" is invoked when a key has been released."""
print("release",event)
Код активируется и запускается, но не выдает никаких выходных данных для ввода с клавиатуры после «добавления слушателя».
Где я ошибаюсь?
Ответ №1:
Вопреки интуиции, кажется, что добавление KeyListener к CurrentController не делает того, что можно было бы подумать. Казалось бы, документ должен получать ввод, который, как вы думаете, он будет делать в любом случае.
Функция, которая будет выдавать ответ на ввод с клавиатуры, является XKeyHandler
.
Однако он добавляется не как EventListener, а как KeyHandler.
У этой функции есть своя особенность, заключающаяся в том, что для ее отмены вам нужно удалить обработчик с точно таким же экземпляром oEventListener
, который использовался для его запуска. Не проблема с oobasic, где экземпляр может быть сохранен как «глобальный», и я предполагаю, что, поскольку он является неотъемлемым, он каким-то образом поддерживается или сохраняется.
Проблема для python заключается в том, что он не может быть сохранен таким образом, если только кто-то, читающий это, не знает способа. Он не будет «мариноваться», и я оказался в затруднительном положении относительно того, как его сохранить. Возможно, я пропустил что-то очевидное.
Решение, которое я в конечном итоге использовал, состояло в том, чтобы сделать функцию самоподавляющейся на основе ввода с клавиатуры.
Предостережение: это было протестировано только в Linux
Следующее можно протестировать, запустив LibreOffice из командной строки lowriter
, а затем запустив как любой другой макрос, завершив с помощью Shift Alt Ctrl k
#!/usr/bin/python
import unohelper
from com.sun.star.awt import XKeyHandler
from com.sun.star.awt import Key
from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK
from com.sun.star.awt.MessageBoxType import INFOBOX
fs_fkeys={} # dictionary of keys to identify each key
for key in dir(Key):
fs_fkeys[getattr(Key, key)] = key
#Idiosyncrasies
# Shift_L, Ctrl_L, Alt_L are not reported as separate keys but are reported as modifiers
# 1,2 and 4 respectively. Shift_R and Ctrl_R are identical to their Left twins
# Alt_R (AltGr) is not reported and not a modifier.
# Super_R (Right Windows) is not reported but is a modifier, even though it doesn't modify any keys.
# It reports as modifier 8
# Super_L (Left Windows) is not reported and not a modifier.
# Caps_Lock and Num_Lock report as unidentified keys but not as modifiers.
# track key input with option of consuming the input (return True)
def fs_Tracker(*args):
doc = XSCRIPTCONTEXT.getDocument()
desktop = XSCRIPTCONTEXT.getDesktop()
global contr, oEventHandler
contr = desktop.getCurrentComponent().getCurrentController()
oEventHandler = KeyHandler(doc)
contr.addKeyHandler(oEventHandler)
mess = "Key tracker activenTo deactivate close document or Shift Alt Ctrl K"
heading = "Key Tracker"
MessageBox(None, mess, heading, INFOBOX, BUTTONS_OK)
class KeyHandler( unohelper.Base, XKeyHandler ):
def __init__(self, parent):
self.parent = parent
return None
def Terminate ( self, event ):
mess = "Key tracker deactivated!"
heading = "Key Tracker"
MessageBox(None, mess, heading, INFOBOX, BUTTONS_OK)
contr.removeKeyHandler(oEventHandler)
def keyPressed( self, event ):
k = event.KeyCode
c = event.KeyChar.value
mods = event.Modifiers
# mods are additive
# 0 - None
# 1 - Shift
# 2 - Ctrl
# 4 - Alt
# 8 - Super_R
if c == "K" and mods == 7: #Shift Ctrl Alt k
self.Terminate(None)
return True # Returning True consumes the key
# Thus assigning this macro to the same keyboard shortcut means that
# the macro is toggled On/Off by Shift Alt Ctrl k
if k in fs_fkeys:
name = fs_fkeys[k]
else:
name = "Undefined"
print(name, k, c, mods)
return False
def keyReleased( self, event ):
return False
def MessageBox(ParentWindow, MsgText, MsgTitle, MsgType, MsgButtons):
ctx = XSCRIPTCONTEXT.getComponentContext()
sm = ctx.ServiceManager
si = sm.createInstanceWithContext("com.sun.star.awt.Toolkit", ctx)
mBox = si.createMessageBox(ParentWindow, MsgType, MsgButtons, MsgTitle, MsgText)
mBox.execute()
#List components that are accessible
g_exportedScripts = fs_Tracker,