2017-06-29 1 views
2

Ich arbeite an einem Programm, das je nach Joystick-Eingabe einen Ball bewegen würde. Die GUI, die ich benutze, ist Tkinter.Binden Sie ein Tkinter-Ereignis, das in einer Klasse außerhalb der Klasse generiert wurde

Vor kurzem habe ich eine Demo eines Verfahrens gefunden, die Tkinter verwendet und war kompatibel mit Pygame (Davor, dachte ich, dass Pygame mit Tkinter unvereinbar war. Ich war psyched, als ich das gefunden konnte.)

I definiert das virtuelle Ereignis "LT" in der Klasse Find_Joystick. ("LT" bezieht sich auf den "LT" Knopf auf einem Gamepad.) Wenn es gedrückt wird, soll es den Ball nach links bewegen. Wenn ich jedoch versuche, das Ereignis an die tatsächliche Bewegungsfunktion zu binden, scheint die Funktion die Eingabe nicht zu empfangen.

Hier ist mein Code (etwas vereinfacht):

from tkinter import * 
import pygame 

class Find_Joystick: 
    def __init__(self, root): 
    self.root = root 

     ## initialize pygame and joystick 
     pygame.init() 
     if(pygame.joystick.get_count() < 1): 
      # no joysticks found 
      print("Please connect a joystick.\n") 
      self.quit() 
     else: 
       # create a new joystick object from 
      # ---the first joystick in the list of joysticks 
      joystick = pygame.joystick.Joystick(0) 
      # tell pygame to record joystick events 
      joystick.init() 

     ## start looking for events 
     self.root.after(0, self.find_events) 

    def find_events(self): 
     ## check everything in the queue of pygame events 
     events = pygame.event.get() 
     joystick = pygame.joystick.Joystick(0) 
     LT = joystick.get_button(6) 
     for event in events: 
      # event type for pressing any of the joystick buttons down 
      if event.type == pygame.JOYBUTTONDOWN: 
      self.root.event_generate('<<JoyFoo>>') 
      if LT == 1: 
       self.root.event_generate('<<LT>>') 

     if event.type == pygame.JOYAXISMOTION: 
      self.root.event_generate('<<JoyMove>>') 
      #Move left 
      if axisX < 0: 
       self.root.event_generate('<<Left>>') 
      #Move right 
      if axisX > 0: 
       self.root.event_generate('<<Right>>') 
      #Move upwards 
      if axisY < -0.008: 
       self.root.event_generate('<<Up>>') 
      #Move downwards 
      if axisY > -0.008: 
       self.root.event_generate('<<Down>>') 

    ## return to check for more events in a moment 
    self.root.after(20, self.find_events) 

def main(): 
## Tkinter initialization 
root = Tk() 
app = Find_Joystick(root) 

frame = Canvas(root, width=500, height = 250) 
frame.pack() 

ball = frame.create_oval([245, 120], [255, 130], outline = 'red', fill = 'red') 



def callback(event): 
    frame.focus_set() 


def moveLeftFunc(event): 
    frame.move(ball, -3, 0) 
    print('Move left') 

frame.bind('<Button-1>', callback) 
frame.bind('<<LT>>', moveLeftFunc) 

root.mainloop() 

if __name__ == "__main__": 
    main() 

Hier ist die demo Ich wurde früher mit Bezug (die Klasse der Hauptteil ich verwende).

Antwort

0

Die Lösung könnte in der Ereignisbindung sein. Sie binden die Ereignisse an den Rahmen Leinwand, und dann werden die Ereignisse durch die Root-Widget erzeugt (self.root.event_generate('<<LT>>'))

in der anderen Art und Weise arbeiten könnte, wird das Ereignis aus dem Widget an die Mutter propagiert, aber nicht von der Wurzel zu den Kinder Widgets.

können Sie versuchen, mit:

root.bind('<Button-1>', callback) 
root.bind('<<LT>>', moveLeftFunc) 

(Sie auch die Linie self.root.event_generate('<<JoyFoo>>') entfernen sollen)

EDIT:

Hier ist ein reproduzierbarer Fall ohne den Joystick Zeug:

(Die Schaltfläche untergeordnete Schaltfläche propagiert das Ereignis, um das Fenster zu schließen, aber das Ereignis, das durch das Ereignis ausgelöst wird root Timer schlägt nicht auf die Rahmenbindung, um zu schließen)

from tkinter import * 
import sys 

def quit(*arg): 
    sys.exit() 

class ChildFrame(Frame): 
    def __init__(self, root): 
    Frame.__init__(self, root) 
    self.grid() 
    button = Button(self, text="Propagate Quit", command=self.child_event) 
    button.pack() 

    def child_event(self): 
    self.event_generate('<<Propagated>>') # triggers the root binding 

root = Tk() 
frame = ChildFrame(root) 

def root_event(*arg): 
    global root 
    root.event_generate('<<NotPropagated>>') # doesn't trigger child binding 
    #root.event_generate('<<Propagated>>') # triggers the root binding 

root.bind('<<Propagated>>', quit)  
frame.bind('<<NotPropagated>>', quit) 

root.after(2000, root_event) # timer to create event from root to child 
root.mainloop() 
Verwandte Themen