问题
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