在 Python Gtk3+ 中模拟鼠标单击小部件
Simulate mouse-clicking a widget in Python Gtk3+
A Python 3 和 Gtk 3.22.5 应用程序响应全局键绑定,感谢 Keybinder 库。目前它调用一个简单的回调:
def keybinder_callback(self, keystr, user_data):
print("Handling", keystr, user_data)
应用程序的其他地方是 Gtk.Window
,其中包含 Gtk.MenuBar
。 keybinder_callback
需要激活菜单栏,就像用户在其上单击鼠标一样。
(这是一个非常基本的扩展坞类型应用程序,而不是具有典型应用程序的应用程序 window)
我试过向菜单项发送信号:
self.menubar.get_children()[0].emit("activate-item")
没有任何喜悦。我也试过伪造按钮按下
from Xlib.ext.xtest import fake_input
fake_input(display,X.ButtonPress,1)
这也没有效果,但无论如何感觉都是错误的方法。我觉得发信号比较合适
能否以编程方式激活小部件,就像用户在其上单击鼠标一样?
(不必是模拟的鼠标单击 - 它只需要以与鼠标单击相同的方式激活和聚焦小部件)
我写了一个example that has a keybinder_callback
这样的:
def keybinder_callback(self, keystr, user_data):
print("Handling", keystr, user_data)
print("Event time:", Keybinder.get_current_event_time())
activate_the_menu()
我需要向该函数添加一些命令以 activate_the_menu
。
我尝试了很多东西,包括捕获真实事件(通过使用 xev
进行监控)并通过将它们注入 Gdk.main_do_event
来模拟它们(ENTER_NOTIFY
和 FOCUS_CHANGE
) ].
我试过调用 menu.popup
、menu.popup_at_widget
、menubar.select_item
和其他许多东西。都无济于事。
运行 没主意了,我什至把我的旧 Xlib 书都掸掉了...
顺便说一句,虽然这不是一个合适的解决方案,但它适用于 shell:
$ xdotool mousemove 1605 10 click 1 mousemove restore
但不可靠 keybinder_callback
:
run("xdotool mousemove %d 10 click 1 mousemove restore" %
(self.get_position().root_x+5) , shell=True)
在尝试了很多东西之后,我发现这行得通。
import Xlib
from Xlib import X
from Xlib.display import Display
from Xlib.ext.xtest import fake_input
import time
def keybinder_callback(self, keystr, user_data):
time.sleep(0.2)
x = self.get_position().root_x+5
display = Display()
mpos = display.screen().root.query_pointer()._data
display.screen().root.warp_pointer(x,5)
display.sync()
fake_input(display,X.ButtonPress,1, X.CurrentTime, X.NONE, x, 5)
display.sync()
fake_input(display,X.ButtonRelease,1)
display.screen().root.warp_pointer(mpos['root_x'],
mpos['root_y'])
display.sync()
我发现延迟时间对于避免这个错误是必要的:
Gdk-CRITICAL **: Window 0x1e7c660 has not been made visible in GdkSeatGrabPrepareFunc
A Python 3 和 Gtk 3.22.5 应用程序响应全局键绑定,感谢 Keybinder 库。目前它调用一个简单的回调:
def keybinder_callback(self, keystr, user_data):
print("Handling", keystr, user_data)
应用程序的其他地方是 Gtk.Window
,其中包含 Gtk.MenuBar
。 keybinder_callback
需要激活菜单栏,就像用户在其上单击鼠标一样。
(这是一个非常基本的扩展坞类型应用程序,而不是具有典型应用程序的应用程序 window)
我试过向菜单项发送信号:
self.menubar.get_children()[0].emit("activate-item")
没有任何喜悦。我也试过伪造按钮按下
from Xlib.ext.xtest import fake_input
fake_input(display,X.ButtonPress,1)
这也没有效果,但无论如何感觉都是错误的方法。我觉得发信号比较合适
能否以编程方式激活小部件,就像用户在其上单击鼠标一样?
(不必是模拟的鼠标单击 - 它只需要以与鼠标单击相同的方式激活和聚焦小部件)
我写了一个example that has a keybinder_callback
这样的:
def keybinder_callback(self, keystr, user_data):
print("Handling", keystr, user_data)
print("Event time:", Keybinder.get_current_event_time())
activate_the_menu()
我需要向该函数添加一些命令以 activate_the_menu
。
我尝试了很多东西,包括捕获真实事件(通过使用 xev
进行监控)并通过将它们注入 Gdk.main_do_event
来模拟它们(ENTER_NOTIFY
和 FOCUS_CHANGE
) ].
我试过调用 menu.popup
、menu.popup_at_widget
、menubar.select_item
和其他许多东西。都无济于事。
运行 没主意了,我什至把我的旧 Xlib 书都掸掉了...
顺便说一句,虽然这不是一个合适的解决方案,但它适用于 shell:
$ xdotool mousemove 1605 10 click 1 mousemove restore
但不可靠 keybinder_callback
:
run("xdotool mousemove %d 10 click 1 mousemove restore" %
(self.get_position().root_x+5) , shell=True)
在尝试了很多东西之后,我发现这行得通。
import Xlib
from Xlib import X
from Xlib.display import Display
from Xlib.ext.xtest import fake_input
import time
def keybinder_callback(self, keystr, user_data):
time.sleep(0.2)
x = self.get_position().root_x+5
display = Display()
mpos = display.screen().root.query_pointer()._data
display.screen().root.warp_pointer(x,5)
display.sync()
fake_input(display,X.ButtonPress,1, X.CurrentTime, X.NONE, x, 5)
display.sync()
fake_input(display,X.ButtonRelease,1)
display.screen().root.warp_pointer(mpos['root_x'],
mpos['root_y'])
display.sync()
我发现延迟时间对于避免这个错误是必要的:
Gdk-CRITICAL **: Window 0x1e7c660 has not been made visible in GdkSeatGrabPrepareFunc