pyglet script works in windows but not in osx

霸气de小男生 提交于 2019-12-24 21:50:53

问题


I am working in a pyglet script which displays an animation, it works as expected in Windows, but when I execute it in osx I only get a blank screen.

I know it works because I've put print statements in on_draw() and other functions and those are shown in the terminal, but the pyglet window does not display anything.

I am forcing the execution of the 32 bit python with the command defaults write com.apple.versioner.python Prefer-32-Bit -bool yes, and I have executed without a problem another pyglet script which also displayed an animation.

I do not understand the problem, because this script, as I said, works in Windows. The code is the following:

import pyglet
from pyglet.gl import *
from pyglet.window import mouse, key
import math 
import time
import ConfigParser
import numpy as np # for randomize the trials
import sys # debuging purposes
import os

## Create pyglet window
# Get screens
screens = pyglet.window.get_platform().get_default_display().get_screens()
allowstencil = pyglet.gl.Config(stencil_size=8)

# Create window (not visible at start)
myWindow = pyglet.window.Window(config=allowstencil,fullscreen=False,screen=screens[0], visible = 0)

## Functions definition


def create_filename():

    ## Create output data file name

    # Get subject and time information
    exp_name = 'pythonMigration'
    time_string = time.strftime("%y.%m.%d_%H.%M.%S", time.localtime())
    subject_name = "Name"

    textfilename = (exp_name + '_' + subject_name + '_' + time_string + '.txt')

    # Save output file in the folder "data"
    out_file_name = os.path.join('data', textfilename) 

    return out_file_name

def ConfigFileToStruct(configfilename):
    # ConfigFileToStruct receives the string of the name of the configuration file to be read.
    # It will return a dict variable with the configuration parameters and values

    # config_struct will be the dict struture where all the configuration parameters will be stored
    config_struct = {}  

    # Initialize configParser
    config = ConfigParser.RawConfigParser()

    # Read file named configfilename
    config.read(configfilename)

    # Read sections of configuration file
    sectionlist = config.sections()

    # Read options of each section
    # optionlist will be an AxB array, where A is not defined and B is the len(sectionlist)
    optionlist = [[] for x in range(len(sectionlist))]


    for i in range(len(sectionlist)):
        # Read variables (options) from configuration file
        optionlist[i] = config.options(sectionlist[i])

        # Fill structure with sections
        config_struct[sectionlist[i]] = {}

        # Fill sections of structure with variables and values
        for j in range(len(optionlist[i])):
            config_struct[sectionlist[i]][optionlist[i][j]] = config.getfloat(sectionlist[i], optionlist[i][j])

    return(config_struct) #end of readconfigFile function

def load_trial_parameters(trialsfile,trial):
    # trialsfile is the struct previously loaded by ConfigFileToStruct()
    # trial is the number of the trial to load parameters from
    global mylambda1, duty_cycle1, orientation1, speed1
    global mylambda2, duty_cycle2, orientation2, speed2
    global timeCurrentTrial

    ## GRATING PARAMETERS

    mylambda1 = trialsfile[str(trial)]["wavelength1"]
    duty_cycle1 = trialsfile[str(trial)]["duty_cycle1"]
    orientation1 = trialsfile[str(trial)]["orientation1"]
    speed_pix = trialsfile[str(trial)]["speed1"]
    speed1 = speed_pix / math.cos(math.radians(orientation1))

    #grating2

    mylambda2 = trialsfile[str(trial)]["wavelength2"]
    duty_cycle2 = trialsfile[str(trial)]["duty_cycle2"]
    orientation2 = trialsfile[str(trial)]["orientation2"]
    speed_pix = trialsfile[str(trial)]["speed2"]
    speed2 = speed_pix / math.cos(math.radians(orientation2))

    # other parameters
    timeCurrentTrial = trialsfile[str(trial)]["time"]

def load_config_parameters(config):
    # config is the struct previously loaded by ConfigFileToStruct()

    # Declare variables, all are global, this function if for clearity purposes    
    global x0_pix, y0_pix
    global ysize_cm, aperture_color, numTheta, deltaTheta, x1, y1, apertRad_pix
    global x2, y2
    global red_color, cyan_color
    global stereo1, stereo2
    global fixp_color, surrp_color
    global time_fixp

    # calculate x, y center coordinates in pixels
    x0_myW = 0 # note that we consider center of screen to be 0,0 in My World Coordinates
    y0_myW = 0
    x0_pix = ((x0_myW/0.5) + 1)/2 * myWindow.width # center of screen; assuming myW width max == 0.5; this equation derived with Nava
    y0_pix = ((y0_myW/0.5) + 1)/2 * myWindow.height # center of screen # assuming myW height max == 0.5


    # calculate radius; we want an aperture with a 13 deg diameter or 6.5 deg radius @ view dist of 57cm
#     ysize_cm = config["screen_parameters"]["ysize_cm"] #@@ TO-DO this will be set as a config param @@ and will change depending on monitor!!
#     apertDiam_cm = config["radius"]["aperture"]
#     apertRad_myW = (apertDiam_cm/ysize_cm) / 2 # determine radius value in My World with reference to 0,0 center
#     apertRad_pix = (((apertRad_myW/0.5) + 1)/2 * myWindow.height) - y0_pix
    apertureDiv = config["aperture_size"]["proportion"]
    apertRad_pix = myWindow.height / apertureDiv

    ## APERTURE PARAMETERS
        # Calculate circle for aperture
    aperture_color = (config["aperture_color"]["red"], config["aperture_color"]["green"], config["aperture_color"]["blue"])
    numTheta = int(config["radius"]["numtheta"])
    deltaTheta = 2 * math.pi / numTheta # == 0.0698
#     
    ## GRATING PARAMETERS
    #grating1
    x1 = x0_pix - apertRad_pix
    y1 = y0_pix - apertRad_pix
    stereo1 = config["stereo"]["grating1"]

    #grating2
    x2 = x0_pix + apertRad_pix
    y2 = y0_pix + apertRad_pix
    stereo2 = config["stereo"]["grating2"]

    ## COLOR PARAMETERS
    red_color   = (config["red_color"]["red"], config["red_color"]["green"], config["red_color"]["blue"])
    cyan_color  = (config["cyan_color"]["red"], config["cyan_color"]["green"], config["cyan_color"]["blue"])

    # fixation point color
    fixp_color  = (config["fixp_color"]["red"], config["fixp_color"]["green"], config["fixp_color"]["blue"])
    surrp_color = (config["surrp_color"]["red"], config["surrp_color"]["green"], config["surrp_color"]["blue"])

    # fixation point time beginning trials
    time_fixp = config["time"]["time_fixp"]

@myWindow.event
def on_mouse_press(x, y, button, modifiers):
#     On_mouse_press will be executed each time a mouse button is pressed
    global count, datatime, dataclick, datatrial
    global show_stim, show_trial_menu, trial, clockTrial, show_welcome

    global show_trial_menu_release, show_welcome_release

    timeNow = time.clock() - clockTrial


    if show_stim:

        if button == mouse.LEFT:
            datatrial[count] = trials_array[trial_counter]
            dataclick[count] = '-1'
            datatime[count] = timeNow - time_fixp


        if button == mouse.RIGHT:
            datatrial[count] = trials_array[trial_counter]
            dataclick[count] = '1'
            datatime[count] = timeNow - time_fixp

        count += 1

    elif show_trial_menu:
        show_trial_menu_release = 1


    elif show_welcome:
        show_welcome_release = 1

@myWindow.event
def on_mouse_release(x, y, button, modifiers):
#     On_mouse_release will be executed each time a mouse button is release
    global count, dataclick, datatime, datatrial
    global show_stim, show_trial_menu, trial, clockTrial, show_welcome, trial_counter
    global show_trial_menu_release, show_welcome_release

    timeNow = time.clock() - clockTrial


    if show_stim:   
        if button == mouse.LEFT:
            datatrial[count] = trials_array[trial_counter]
            dataclick[count] = '-2'
            datatime[count] = timeNow - time_fixp

        if button == mouse.RIGHT:
            datatrial[count] = trials_array[trial_counter]
            dataclick[count] = '2'
            datatime[count] = timeNow - time_fixp

        count += 1

    elif show_trial_menu & show_trial_menu_release:

        show_trial_menu_release = 0 

        show_stim = 1
        show_trial_menu = 0
        trial = trial + 1
        trial_counter = trial_counter + 1
        clockTrial = time.clock()


    elif show_welcome & show_welcome_release:

        show_welcome_release = 0
        show_welcome = 0
        show_stim = 1

        clockTrial = time.clock()


@myWindow.event
def on_close():
    #on_close is executed when mywindow is closed
    close_nicely()

def close_nicely(): 
    #Write data to text file   
    for i in range(count):
        with open(out_file_name, 'a') as txtfile:
            txtfile.write(str(i) +'\t'+ str(datatime[i]) +'\t'+ str(dataclick[i]) +'\t'+ str(datatrial[i]) + '\n')

    print("closed nicely :)")

    myWindow.clear()
    myWindow.close()

def drawCircle(radius, circle_color, x, y):
    global numTheta, deltaTheta 

    glColor3f( circle_color[0] , circle_color[1], circle_color[2])

    for i in range (0, numTheta):
        cx1 = x + radius * math.sin(deltaTheta * i)
        cy1 = y + radius * math.cos(deltaTheta * i)
        cx2 = x + radius * math.sin(deltaTheta * (i+1))
        cy2 = y + radius * math.cos(deltaTheta * (i+1))

        glBegin( GL_TRIANGLES )
        glVertex2f(x, y )
        glVertex2f(cx1 , cy1 )
        glVertex2f(cx2 , cy2 )
        glEnd()

def drawAperture():
    global aperture_color, numTheta, deltaTheta, x0_pix, y0_pix, apertRad_pix

    # Do we need the stencil commands in here? It does not change if I delete them
    # Enable stencil
    glClearStencil(0x0)
    glEnable(GL_STENCIL_TEST) 

    #define the region where the stencil is 1
    glClear(GL_STENCIL_BUFFER_BIT)
    glStencilFunc(GL_ALWAYS, 0x1, 0x1) #Always pass stencil functions test
    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE) #Replace stencil value with reference value

    drawCircle(apertRad_pix, aperture_color, x0_pix, y0_pix)

def drawGrating(x, y, fill_color, orientation, mylambda, duty_cycle):

    bar_length = 1500

    radio_aux = (2 * apertRad_pix) + mylambda #diameter 
    num_bars = int(1 + math.floor(radio_aux / mylambda))+3

    glStencilFunc (GL_EQUAL, 0x1, 0x1) 
    glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP)

    glLoadIdentity() #replace current matrix with the identity matrix
    glTranslatef(x, y, 0)
    glRotatef(orientation,0,0,1)    
    glTranslatef(-x, -y, 0)

    glColor3f( fill_color[0] , fill_color[1], fill_color[2] )

    glBlendFunc(GL_ZERO, GL_SRC_COLOR)  

    for i in range(num_bars):    

        x1 = mylambda * i + x
        x2 = (duty_cycle * mylambda) + (mylambda * i + x)

        glBegin(GL_QUADS)

        glVertex2f(x1, y - bar_length) 
        glVertex2f(x1, y + bar_length) 
        glVertex2f(x2, y + bar_length) 
        glVertex2f(x2, y - bar_length)

        glEnd()

#     glRotatef(-orientation, 0, 0, 1)#Is it necessary?
    glBlendFunc(GL_ONE, GL_ZERO)
    glLoadIdentity()     

def update_frames(dt):
    global x1, x2, timetrial, clockTrial, trial, show_stim, show_trial_menu

    timeNow = time.clock()

    if (show_stim) & ((timeNow-clockTrial) < (timeCurrentTrial + time_fixp)):
        # Load trial parameters
        load_trial_parameters(trialsfile,trials_array[trial_counter])

        motion_cycle1 = mylambda1/(math.cos(math.radians(orientation1)))
        motion_cycle2 = mylambda2/(math.cos(math.radians(orientation2)))

        initialpos1 = myWindow.width/2 - apertRad_pix - mylambda1/2
        initialpos2 = myWindow.width/2 - apertRad_pix + mylambda2/2

        # update position of grating 1:
        x1 = initialpos1 + math.fmod(speed1*(timeNow-clockTrial), motion_cycle1)

        # update position of grating 2:
        x2 = initialpos2 + math.fmod(speed2*(timeNow-clockTrial), motion_cycle2)

    elif ((show_stim) & (trial_counter < numtrials)):
        show_stim = 0
        show_trial_menu = 1

    elif ((show_stim == 0) & (trial_counter == numtrials-1)):
        close_nicely()
        pass

@myWindow.event
def on_draw():
    print "on draw"
    if show_stim:
        # For each frame of the stimulus:

        # clear the window
        myWindow.clear()

        load_trial_parameters(trialsfile, trials_array[trial_counter])

        # Enable blending
        glEnable(GL_BLEND)
        pyglet.gl.glClearColor( 0.6, 0.6, 0.6, 0 )

        # Enable stencil
        glClearStencil(0x0)
        glEnable(GL_STENCIL_TEST) 

        # define the region where the stencil is 1
        glClear(GL_STENCIL_BUFFER_BIT)
        glStencilFunc(GL_ALWAYS, 0x1, 0x1) #Always pass stencil functions test
        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE) #Replace stencil value with reference value

        # draw Aperture
        drawCircle(apertRad_pix, aperture_color, x0_pix, y0_pix) 

        # draw Fixation point and fixation surround
        drawCircle(apertRad_pix/15, fixp_color,  x0_pix, y0_pix)
        drawCircle(apertRad_pix/80, surrp_color, x0_pix, y0_pix)

        if (time.clock()-clockTrial)>time_fixp:
            # draw gratings

            Red  = red_color
            Cyan = cyan_color

            drawGrating(x1 + stereo1, y1, Cyan, orientation1, mylambda1, duty_cycle1)
            drawGrating(x1 - stereo1, y1, Red,  orientation1, mylambda1, duty_cycle1)

            drawGrating(x2 + stereo2, y2, Red,  orientation2, mylambda2, duty_cycle2)
            drawGrating(x2 - stereo2, y2, Cyan, orientation2, mylambda2, duty_cycle2)

            glBlendFunc(GL_ONE, GL_ZERO)


    elif show_trial_menu:
        # For each frame of the in-between trials window

        myWindow.clear()

        #define the region where the stencil is 1
        glClear(GL_STENCIL_BUFFER_BIT)
        glStencilFunc(GL_ALWAYS, 0x1, 0x1) #Always pass stencil functions test
        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE) #Replace stencil value with reference value

        labelInterval.draw()

    elif show_welcome:
        # For each frame of the welcome window

        myWindow.clear()

        glEnable(GL_BLEND)
        pyglet.gl.glClearColor( 0.6, 0.6, 0.6, 0 )

        labelWelcome.draw()


################################################################################################
## Main
################################################################################################

if __name__ == "__main__":

    ## Check command-line arguments
    if len(sys.argv)>1:
        confignamefile = sys.argv[1]
        trialsnamefile = sys.argv[2]
        print("input received")
    else:
        print("no input received")
        confignamefile = "cfgfile.txt"
        trialsnamefile = "trialsfile.txt"

    # Load configuration parameters
    config = ConfigFileToStruct(confignamefile)
    if not config:
        print("CONFIG FILE EMPTY")
    else:
        print("CONFIG FILE LOADED")

    # Load trials file parameters
    trialsfile = ConfigFileToStruct(trialsnamefile)
    if not trialsfile:
        print("TRIALS FILE EMPTY")
        sys.exit()
    else:
        print("TRIALS FILE LOADED")
        numtrials = len(trialsfile)


    ## Initialize states of on_draw()
    show_welcome = 1
    show_stim = 0
    show_start_menu = 0
    show_trial_menu = 0

    show_trial_menu_release = 0 

    ## Load parameters
    randomize_trials = 1

    if randomize_trials:
        trials_array = np.random.permutation(numtrials) # goes from 0 to numtrials in random order
    else:
        trials_array = range(numtrials) # no random

    trial = 0
    trial_counter = 0

    load_config_parameters(config)
    load_trial_parameters(trialsfile,trials_array[trial_counter])

    ## Create output data file name
    out_file_name = create_filename()

    # Necessary variables for the data file
    count = 0
    dataclick   = [0]*15000
    datatime    = [0]*15000
    datatrial   = [0]*15000

    ## Message that will be shown between trials
    labelInterval = pyglet.text.Label("Click the mouse to start the next trial", font_name = 'Arial', 
                                  font_size = 20, x = myWindow.width/2, y = myWindow.height/2,
                                  anchor_x = "center", anchor_y = "center")

    ## Message that will be shown at startup
    textWelcome = "\t\t\t\tWelcome\n RIGHT click: Grating to the right is in front\n LEFT click: Grating to the left is in front\n\n LEFT click to start"
    labelWelcome = pyglet.text.Label(textWelcome, 
                                font_name = 'Arial', font_size = 20, x = myWindow.width/2, y = myWindow.height/2, 
                                multiline = True, width=600, anchor_x = "center", anchor_y = "center")


    ## Run stimulus

    # Set stimulus window to visible and mouse not visible
    myWindow.set_visible(1)
    myWindow.set_mouse_visible(0) 

    # initialize clock
    clockTrial = time.clock() # this clock will be reset for each trial    

    framerate = 1/60.0

    pyglet.clock.schedule_interval(update_frames,framerate)

    pyglet.app.run()

Could anybody help me to find out what am I doing wrong in this code?


回答1:


This is a (working) example code where flip is utilized:

import pyglet
from pyglet.gl import *
from math import radians, cos, sin, degrees, atan2
from time import time
from os.path import abspath

glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glEnable(GL_LINE_SMOOTH)
glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE)
pyglet.options['audio'] = ('alsa', 'openal', 'silent')
key = pyglet.window.key

class BasicObject(pyglet.sprite.Sprite):
    def __init__(*args, **dictWars):
        if type(args) == tuple and len(args) == 2 and len(dictWars) == 0 and type(args[1]) == dict:
            args, dictWars = args

        self = args[0]
        self.name = args[1]
        self.render = True
        self.anchor = 'center'

        self.last_update = time()

        self.texture = pyglet.image.load(abspath(dictWars['texture']))
        super(BasicObject, self).__init__(self.texture)

        self.x, self.y = 0, 0
        self.rotation = 0

        if 'x' in dictWars:
            self.x = dictWars['x']
        if 'y' in dictWars:
            self.y = dictWars['y']

    def swap_image(self, image, filePath=True):
        if filePath:
            self.texture = pyglet.image.load(abspath(image))
        else:
            self.texture = image
        self.image = self.texture

    def draw_line(self, xy, dxy, color=(0.2, 0.2, 0.2, 1)):
        glColor4f(color[0], color[1], color[2], color[3])
        glBegin(GL_LINES)
        glVertex2f(xy[0], xy[1])
        glVertex2f(dxy[0], dxy[1])
        glEnd()

    def rotate(self, deg):
        self.image.anchor_x = self.image.width / 2
        self.image.anchor_y = self.image.height / 2
        self.rotation = self.rotation+deg
        if self.anchor != 'center':
            self.image.anchor_x = 0
            self.image.anchor_y = 0

    def click(self):
        print('Clicked:',self.name)

    def work(self, *args):
        if time() - self.last_update > 0.1:
            self.rotate(10)

    def click_check(self, x, y):
        if x > self.x and x < (self.x + self.width):
            if y > self.y and y < (self.y + self.height):
                return self

    def _draw(self):
        self.work()
        # self.draw_line((x,y), (dx, dy))
        self.draw()

class GUI(pyglet.window.Window):
    def __init__(self):
        super(GUI, self).__init__(640,340, caption='My app')
        self.alive = True
        self.keys_down = {}

        self.myImage = BasicObject('TestImage', texture='/path/to/texture.png')

    def render(self, *args):
        pyglet.gl.glClearColor(1, 1, 1, 1)
        self.clear()
        # .. This is where you draw your objects, for instance
        self.myImage._draw()
        self.flip()

    def on_draw(self):
        self.render()

    def on_close(self):
        self.alive = False

    def on_key_press(self, symbol, modkey):
        self.keys_down[symbol] = time()

    def on_key_release(self, symbol, modkey):
        if symbol in self.keys_down:
            del(self.keys_down[symbol])

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

    def on_mouse_press(self, x, y, button, modifiers):
        print(button,'pressed',(x,y))


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

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

    def run(self):
        while self.alive:
            event = self.dispatch_events()

            for symbol in self.keys_down:
                if symbol == key.ESCAPE:
                    self.alive = None
                    break
                elif symbol == key.LEFT:
                    pass #Arrowkey Left
                elif symbol == key.RIGHT:
                    pass #Arrowkey Right
                elif symbol == key.UP:
                    pass #Arrowkey Up
                elif symbol == key.DOWN:
                    pass #Arrowkey Down
                elif symbol == 65515:
                    pass # Win key
                else:
                    print(symbol)
            self.render()


if __name__ == '__main__':
    x = GUI()
    pyglet.clock.set_fps_limit(120)
    x.run()

This is also the code i use in all my projects, something that's been evolving to fit my needs but also something that's proved to be working in most scenarios.



来源:https://stackoverflow.com/questions/24324985/pyglet-script-works-in-windows-but-not-in-osx

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!