2013-05-23 19 views
7

Mam program renderowania w 3D, który obraca świat wokół obserwatora na podstawie pozycji myszy na ekranie. Ilość w radianach, że na świecie jest obrócony, jest określona przez tę linięW jaki sposób ustawić pozycję myszy w oknie TKK

glob.worldx=-(w.winfo_pointerxy()[0]-xy[0])/250 

gdzie xy [0] jest współrzędną x środku ekranu

Oznacza to, że ilość że pole obserwatorów widok może być obracany jest ograniczony przez odległość, którą może odejść mysz. Gdybym mógł, aby mysz wróciła na środek ekranu, mógłbym rozwiązać ten problem. Jakieś pomysły?

+0

Zamiast przesuwając kursor, może uczynić stanowisko sterowania kursorem się prędkość * * z której świat obraca - im dalej od centrum, tym szybszy obrót. – unutbu

+0

To świetna propozycja unetbu, a ja używałem tego schematu, ale nie jest to tak przyjazne dla użytkownika, jak tego chciałem, więc chcę coś podobnego do tego, jak kontrolowana jest gra w strzelanki pierwszej osoby. – sam

Odpowiedz

7

Dobrą wiadomością jest to, że istnieje sposób, aby to zrobić.

Pośrednia wiadomość jest taka, że ​​nie jest dobrze udokumentowana.

Zła wiadomość jest taka, że ​​działa tylko na niektórych platformach.

Drugą wiadomością pośrednią jest to, że można wyjść poza TK na co najmniej niektórych platformach.


Sposób to zrobić w Tcl/Tk jest poprzez generowanie zdarzenia <Motion> z -warp 1. Dokumentacja na ten temat jest skąpa i rozproszona na kilku różnych stronach (początek bind), ale szczegóły są opisane here. Zasadniczo, jest to po prostu:

event generate . <Motion> -warp 1 -x 50 -y 50 

Jak to zrobić z Tkinter?

No event_generate nie jest udokumentowane w dowolnym miejscu, a nie jest to wydarzenie <Motion> lub parametr warp ... ale to dość proste, aby dowiedzieć się, czy wiesz jak mapy Tk Tkinter:

window.event_generate('<Motion>', warp=True, x=50, y=50) 

i to rzeczywiście generuje zdarzenie, jak można zobaczyć, wiążąc <Motion>. Oto prosty program testowy:

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

go uruchomić, kliknij okno, aby upewnić się, że ma skupić, przesuń kursor wokół, a zobaczysz go wydrukować coś takiego:

motion 65, 69 
motion 65, 70 
motion 65, 71 

następnie uderzył w klawisz, a my go wydrukować to:

motion 50, 50 

który jest wielki ... oprócz tego, że nie może w rzeczywistości być w stanie poruszać kursorem, w tym przypadku wszystko to robi to sztuczka Tk do myślenia kursor przeniósł.


Od przeglądając różne fora, to wygląda:

  • Mac: nie działa.
  • Okna: zwykle działa.
    • Musisz mieć Tk 8.4.something lub nowszy. Nie mogłem znaleźć tego błędu, ale możesz liczyć na 8.4 z oficjalną binarną instalacją Windows w Pythonie 2.7 lub 3.x +.
    • Nie wolno również uruchamiać aplikacji pełnoekranowej (której na ogół nie ma, w przypadku Tk).
    • W systemie Vista i nowszych przypadkach w niektórych przypadkach nie będzie działać. Może to mieć coś wspólnego z nieposiadaniem sesji pulpitu lub nie jest sesją konsoli lokalnej lub może być związane z potrzebą administratora lub innymi uprawnieniami.
    • Jeśli to nie zadziała, łatwo przejść bezpośrednio do interfejsu Win32 API.
  • X11 (najczęściej Linux, * BSD, itd.): Zazwyczaj
    • Twój menedżer okien nie musi mieć niepełnosprawne innych klientów wypaczaniu wskaźnik. Na szczęście nie wydaje się to powszechne.
    • Jeśli masz ten problem, nie da się tego obejść.
  • Inne platformy (iOS, Android itp.): Nie mam pojęcia.

Dla komputerów Mac, chcesz wygenerować i wysłać wydarzenie NSMouseMoved. Prosty sposób na to jest z pyobjc (który jest zbudowany, jeśli używasz Apple Pythona, w przeciwnym razie trzeba go instalować):

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) 

Dla Windows, chcesz wywołać SetCursorPos API, lub generować i wyślij MOUSEEVENT. Ten pierwszy nie będzie działać z np. Grami DirectX; ten ostatni może nie działać ze zdalnymi pulpitami. W tym przypadku prawdopodobnie chcesz ten pierwszy. Tak czy inaczej, najprostszym sposobem, aby to zrobić, to zainstalować pywin32, a potem po prostu:

win32api.SetCursorPos((50, 50)) 
+0

To działa dla ja na Windows 7. – Tim

+0

@Tim: Świetnie! Zrobiłem trochę więcej badań; pozwól mi aktualizować rzeczy. – abarnert

+0

Działa jak magiczny abernart! Czy jest sposób, w jaki mogę to zrobić bez naciskania przycisku? najbliżej mam, umieszczając funkcję root.event_generate w ruchu myszy, ale to aktualizuje się dość powoli. – sam

Powiązane problemy