如何使用 python 宏监视 Libreoffice 文档中的键盘输入?

Posted

技术标签:

【中文标题】如何使用 python 宏监视 Libreoffice 文档中的键盘输入?【英文标题】:How to monitor keyboard input in a Libreoffice document using a python macro? 【发布时间】:2020-11-21 19:46:09 【问题描述】:

请注意,这是一个自我回答的问题,仅供参考。 尽管进行了坚定的搜索,但我还没有发现它记录在 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 上测试过

以下可以通过命令行lowriter启动LibreOffice然后运行 与任何其他宏一样,使用 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 active\nTo 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,   

【讨论】:

以上是关于如何使用 python 宏监视 Libreoffice 文档中的键盘输入?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 python 宏获取 libreoffice 文档中段落的样式名称?

Pycharm中如何使用宏快速编写代码

如何在 LibreOffice 中运行 python 宏?

如何执行启动另一个 python 脚本的 python 宏?

LibreOffice - 如何通过 python 宏创建文件对话框?

[delphi编程]如何实现监视指定文件夹的文件操作