简体   繁体   中英

pyglet script works in windows but not in osx

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?

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.

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