简体   繁体   中英

Pyglet running but not responding to esc commands

I am relatively new to Python and Pyglet, I am trying to create an app that dynamically displays photos accordingly to the ID of a command sent via serial. Here is my code:

import pyglet
from pyglet import clock
import serial
import json
import os

base_dir = 'data'
data = []
currentDatum = ''

def initialiseData():
    global data
    #load the json
    with open('dataset.json') as f:
        data = json.load(f)
    #for every file in the json load the image
    for d in data:
        d['media'] = pyglet.image.load(os.path.join(base_dir, d['name']))

    print("Scan a tag")

def readSerial(dt):
    global currentDatum
    tag = ser.readline()
    tag = tag.strip()
    for d in data:
        if d['id'] == tag:
            currentDatum = d
            print(currentDatum)



ser = serial.Serial('/dev/cu.usbmodem1421', 9600)

initialiseData()

window = pyglet.window.Window(1000, 800, resizable = True)


@window.event
def on_draw():
    window.clear()
    currentDatum['media'].anchor_x = currentDatum['media'].width/2 - window.width/2
    currentDatum['media'].anchor_y = currentDatum['media'].height/2 - window.height/2
    currentDatum['media'].blit(0, 0)


clock.schedule(readSerial)
pyglet.app.run()

The application works fine, in the sense that it loads the data from the son and when I send the serial ID it gets read instantly, but every mouse interaction freezes the app: I cannot close the window, cannot resize it, it just gets stuck. Any advice?

I have no idea what the program actually does, or how to use it. And since I can't replicate your environment (you've got a usbmodem for instance), I'll try my best approach at a generic solution that should work and plan ahead for future development on your project:

import pyglet
from pyglet.gl import *

key = pyglet.window.key

class main(pyglet.window.Window):
    def __init__ (self, width=800, height=600, fps=False, *args, **kwargs):
        super(main, self).__init__(width, height, *args, **kwargs)
        self.x, self.y = 0, 0

        self.batch = pyglet.graphics.Batch()
        self.data = []
        self.currentDatum = ''
        self.ser = serial.Serial('/dev/cu.usbmodem1421', 9600)

        self.initialiseData()

        pyglet.clock.schedule(self.readSerial)

        self.alive = 1

    def on_draw(self):
        self.render()

    def on_close(self):
        self.alive = 0

    def on_mouse_motion(self, x, y, dx, dy):
        pass

    def on_mouse_release(self, x, y, button, modifiers):
        pass

    def on_mouse_press(self, x, y, button, modifiers):
        pass

    def on_mouse_drag(self, x, y, dx, dy, button, modifiers):
        pass

    def on_key_release(self, symbol, modifiers):
        pass

    def on_key_press(self, symbol, modifiers):
        if symbol == key.ESCAPE: # [ESC]
            self.alive = 0

    def render(self):
        self.clear()

        # For future reference, use batches:
        self.batch.draw()
        # But this is how it's implemented atm:
        self.currentDatum['media'].anchor_x = self.currentDatum['media'].width/2 - self.width/2
        self.currentDatum['media'].anchor_y = self.currentDatum['media'].height/2 - self.height/2
        self.currentDatum['media'].blit(0, 0)

        self.flip()

    def initialiseData(self):
        #load the json
        with open('dataset.json') as f:
            self.data = json.load(f)
        #for every file in the json load the image
        for d in self.data:
            d['media'] = pyglet.image.load(os.path.join(base_dir, d['name']))

        print("Scan a tag")

    def readSerial(self, dt):
        tag = self.ser.readline()
        tag = tag.strip()
        for d in self.data:
            if d['id'] == tag:
                self.currentDatum = d
                print(self.currentDatum)

    def run(self):
        while self.alive == 1:
            self.render()

            # -----------> This is key <----------
            # This is what replaces pyglet.app.run()
            # but is required for the GUI to not freeze
            #
            event = self.dispatch_events()

if __name__ == '__main__':
    x = main()
    x.run()

It's bound to be a few run time errors in this code, syntax that I've might have messed up. But I've ported as much of your code as possible into a object oriented way of thinking. Aka a class that inherits the Window class in order for you to modify elements within and the window itself.

There's also some placeholder-functions that you can use to handle mouse and keyboard events. These are inherited/overlapping the pyglet.window.Window class. So any function supported by Window can be put into this class.

There's also a custom pyglet.app.run() that handles the event polling, making sure you don't get stuck on keyboard, mouse or window (resize, move etc) events.

Hope this works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM