Хорошая новость заключается в том, что есть способ сделать это.
Промежуточная новость заключается в том, что это плохо задокументировано.
Плохая новость заключается в том, что он работает только на некоторых платформах.
Другая промежуточная новость заключается в том, что вы можете выйти за пределы Tk по крайней мере на некоторых платформах.
В Tcl/Tk это можно сделать, создав событие <Motion>
с помощью -warp 1
. Документация по этому вопросу немногочисленна и разбросана по нескольким разным страницам (начните с bind
), но подробности описаны здесь. В основном, это просто:
event generate . <Motion> -warp 1 -x 50 -y 50
Итак, как вы делаете это из Tkinter?
Что ж, event_generate
нигде не задокументировано, равно как и событие <Motion>
, или параметр warp
… но это довольно просто понять, если вы знаете, как Tk сопоставляется с Tkinter:
window.event_generate('<Motion>', warp=True, x=50, y=50)
И это действительно генерирует событие, как вы можете видеть, связывая <Motion>
. Вот простая тестовая программа:
from tkinter import *
root = Tk()
def key(event):
root.event_generate('<Motion>', warp=True, x=50, y=50)
def motion(event):
print('motion {}, {}'.format(event.x, event.y))
root.bind('<Key>', key)
root.bind('<Motion>', motion)
root.mainloop()
Запустите его, щелкните по окну, чтобы убедиться, что оно имеет фокус, переместите курсор, и вы увидите что-то вроде этого:
motion 65, 69
motion 65, 70
motion 65, 71
Затем нажмите клавишу, и он распечатает это:
motion 50, 50
Это здорово… за исключением того, что на самом деле он может не иметь возможности перемещать ваш курсор, и в этом случае все, что он делает, это обманывает Tk, заставляя его думать, что курсор переместился.
Полазив по разным форумам, получилось так:
- Mac: Does not work.
- Windows: Usually works.
- You must have Tk 8.4.something or later. I couldn't find the bug for this, but you can count on 8.4 with any official Windows binary install of Python 2.7 or 3.x+.
- Вы также не должны запускать полноэкранное приложение (чего обычно не бывает с Tk).
- В Vista и более поздних версиях в некоторых случаях это не сработает. Это может иметь какое-то отношение к тому, что вы не владеете сеансом рабочего стола или не являетесь сеансом локальной консоли, или это может быть связано с необходимостью прав администратора или других привилегий.
- Если не работает, то легко сразу перейти к Win32 API.
- X11 (most linux, *BSD, etc.): Usually
- Your window manager must not have disabled other clients from warping the pointer. Fortunately, that doesn't seem to be a common thing to do.
- Если у вас есть эта проблема, нет никакого способа обойти это.
- Другие платформы (iOS, Android и т. д.): не знаю.
Для Mac вы хотите сгенерировать и отправить NSMouseMoved
. Проще всего это сделать с помощью pyobjc
(который встроен, если вы используете Apple Python; в противном случае вам придется его установить):
app = Foundation.NSApplication.sharedApplication()
event = Foundation.NSEvent.mouseEventWithType_location_modifierFlags_timestamp_windowNumber_context_eventNumber_clickCount_pressure_(
Foundation.NSMouseMoved, (50, 50), 0, 0,
app.mainWindow().windowNumber(), None, 0, 0, 0.0)
app.sendEvent_(event)
Для Windows вы хотите вызвать SetCursorPos
API или создайте и отправьте MOUSEEVENT. Первый не будет работать, например, с играми DirectX; последний может не работать с удаленными рабочими столами. В этом случае вы, вероятно, захотите первого. В любом случае, самый простой способ сделать это — установить pywin32
, а затем просто:
win32api.SetCursorPos((50, 50))
person
abarnert
schedule
23.05.2013