The following code is supposed to create a window consisting of a "calibrate" button and a canvas. When the "calibrate" button is clicked, the red dot is supposed to be re-drawn on a random location on the canvas.
Instead, I see the OnPaint event is called once, in the beginning, and not afterwards. Any idea what's going on?
import wx
import datetime
import threading
import random
class frmMain ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 839,553 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.pos = (300,100)
self.initGUI()
def initGUI(self):
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
topSizer = wx.BoxSizer( wx.HORIZONTAL )
buttonsSizer = wx.BoxSizer( wx.VERTICAL )
self.btnCalibrate = wx.Button( self, wx.ID_ANY, u"Calibrate", wx.DefaultPosition, wx.DefaultSize, 0 )
buttonsSizer.Add( self.btnCalibrate, 0, wx.ALL, 5 )
topSizer.Add( buttonsSizer, 0, wx.LEFT, 5 )
sizeCanvas = wx.BoxSizer( wx.VERTICAL )
sizeCanvas.SetMinSize( wx.Size( 600,600 ) )
self.panel=wx.Panel(self, size=(600,600))
self.panel.SetBackgroundColour('white')
self.firstpoint=wx.Point(300,300)
self.secondpoint=wx.Point(400,400)
self.panel.Bind(wx.EVT_PAINT, self.onPaint)
sizeCanvas.Add(self.panel, 0, wx.ALIGN_LEFT, 5)
topSizer.Add( sizeCanvas, 1, wx.ALIGN_RIGHT, 5 )
self.SetSizer( topSizer )
self.Layout()
self.Centre( wx.BOTH )
# Connect Events
self.btnCalibrate.Bind( wx.EVT_BUTTON, self.StartCalibrate )
self.Show(True)
def onPaint(self,event):
print "lalal"
dc = wx.WindowDC(self.panel)
color = wx.Colour(255,0,0)
b = wx.Brush(color)
dc.SetBrush(b)
dc.DrawCircle(self.pos[0], self.pos[1], 10)
def __del__( self ):
pass
def StartCalibrate( self, event ):
size = self.GetSize()
self.pos = (random.randrange(0, size[0] - 1, 1), random.randrange(0, size[1] - 1, 1))
print "fixation at %d, %d" % (self.pos[0], self.pos[1])
self.panel.Update()
event.Skip()
if __name__ == "__main__":
app = wx.App()
frmMain(None)
app.MainLoop()
Use Refresh instead of Update. Update causes any pending paint events to be processed immediately, but if there are no pending paint events then nothing will be done. On the other hand, Refresh causes a paint event to be sent to the widget.
Related
I have a simple application about GUI with wxpython , I'd like to display real time value from database. Currently what I can do is to display the value from database , but I can not figure out how to make it REAL TIME , I mean when the data changed in database then I hope the data on this interface will synchronize with database. Hope it's clear. Anyone who can help on this ? Any suggestion will be appreciated.
Here I attached my code: Python 3.5 , Win 10
# -*- coding: utf-8 -*-
import wx
import wx.adv
import wx.grid
import sys
import pyodbc
import time
bgcolor = (220,220,220)
class Mywin(wx.Frame):
def __init__(self, parent, title):
super(Mywin, self).__init__(parent, title = title, size = (600,320))
self.InitUI()
def InitUI(self):
nb = wx.Notebook(self)
nb.AddPage(MyPanel3(nb), "Table")
self.Centre()
self.Show(True)
def retrieve_data_fromdb():
# SQL Server configuration
server = 'localhost'
db = '***'
user = 'sa'
pwd = '******'
src_db = pyodbc.connect(r'DRIVER={SQL Server Native Client 11.0};SERVER=' + server + ';DATABASE=' + db + ';UID=' + user + ';PWD=' + pwd)
cur = src_db.cursor()
select = 'select * from real_time_test'
cur.execute(select)
rows = cur.fetchone()
wind_spd = rows[0]
site_pwr = rows[1]
acv_pr_setpnt = rows[2]
park_pbl_cap = rows[3]
tol_cur = rows[4]
tol_non_prod = rows[5]
data = []
data.append(wind_spd)
data.append(site_pwr)
data.append(acv_pr_setpnt)
data.append(park_pbl_cap)
data.append(tol_cur)
data.append(tol_non_prod)
return data
cur.commit()
cur.close()
src_db.close()
class MyPanel3(wx.Panel):
def __init__(self, parent):
super(MyPanel3, self).__init__(parent)
self.SetBackgroundColour(bgcolor)
self.Bind(wx.EVT_PAINT, self.OnPaint)
title_NDC = wx.StaticText(self, -1, " Real time signals ", (30, 22))
title_NDC.SetForegroundColour((0, 0, 255))
wx.StaticText(self, -1, "1. Wind Speed", (35, 75))
wx.StaticText(self, -1, "2. Site Power", (35, 95))
wx.StaticText(self, -1, "Instant", (300, 45))
wx.StaticText(self, -1, "m/s", (340, 75))
wx.StaticText(self, -1, "kW", (340, 95))
a = retrieve_data_fromdb()
wind_spd_val = wx.StaticText(self, -1, a[0], (300, 75))
wind_spd_val.SetForegroundColour((0, 0, 255))
def OnPaint(self, event):
pdc = wx.PaintDC(self)
gc = wx.GCDC(pdc)
gc.Clear()
brush_rec = wx.Brush(bgcolor)
gc.SetBrush(brush_rec)
gc.SetPen(wx.Pen("black", 2))
x1 = 20
y1 = 30
w1 = 500
h1 = 180
radius = 3
gc.DrawRoundedRectangle(x1, y1, w1, h1, radius)
ex = wx.App()
Mywin(None,'My example')
ex.MainLoop()
An easy, if inefficient, way to achieve this is using a simple Timer.
Simply read the database once every x amount of time and update the screen.
Forgive the messy code but you'll get the idea.
Use the input box to update the value.
You'll have to fiddle with the database code, as I've used sqlite3, which is already on my box.
import wx
import sqlite3
class Frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
#Dummy database
self.data = [['1111','Lots'],['2222','Fast'],['3333','Low']]
self.db = sqlite3.connect("test1.db")
self.cursor = self.db.cursor()
self.cursor.execute('CREATE TABLE IF NOT EXISTS TEST(Id Text, Value Text)')
self.cursor.execute("select * from TEST");
test = self.cursor.fetchone()
if not test:
for i in self.data:
result = self.db.execute("insert into Test (Id, Value) values (?,?)",(i[0],i[1]))
self.db.commit()
wx.StaticText(self, -1, "1. Wind Speed", (35, 75))
wx.StaticText(self, -1, "2. Site Power", (35, 95))
wx.StaticText(self, -1, "Instant", (300, 45))
wx.StaticText(self, -1, "m/s", (340, 75))
wx.StaticText(self, -1, "kW", (340, 95))
self.wind = wx.TextCtrl(self, -1, pos=(35,200),style=wx.TE_RIGHT|wx.TE_PROCESS_ENTER)
a = self.retrieve_data_fromdb()
self.wind_spd_val = wx.StaticText(self, -1, a[1], (300, 75))
#Bind the callbacks for the timer and the update function
self.wind.Bind(wx.EVT_TEXT_ENTER, self.OnUpdate)
self.dbtimer = wx.Timer(self)
self.Bind(wx.EVT_TIMER,self.OnTimer, self.dbtimer)
self.dbtimer.Start(1000)
def retrieve_data_fromdb(self):
self.cursor.execute("SELECT * FROM Test where Id = ?",['2222'])
a = self.cursor.fetchone()
return a
def OnUpdate(self,event):
self.cursor.execute("update Test set Value=? where Id=?" , (self.wind.GetValue(),'2222'))
self.db.commit()
def OnTimer(self,event):
a = self.retrieve_data_fromdb()
self.wind_spd_val.SetLabel(a[1])
print("Updated with "+str(a[1]))
if __name__ == '__main__':
app = wx.App()
frame = Frame()
frame.Show()
app.MainLoop()
The problem is that there are two Choice drop-down boxes in the UI, the content of the second box is initially empty, and when the user selects an option in the first box, the corresponding option appears in the second box。
For example, if the first box is month, the second box is day, and the user selects January, then the second box has 1... . 31, the user chooses February, the second frame is 1... 28。
My code is as follows.
`
import wx
class myFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__ ( self, None, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
bSizer9 = wx.BoxSizer( wx.VERTICAL )
self.m_staticText14 = wx.StaticText( self, wx.ID_ANY, u"select Month", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText14.Wrap( -1 )
bSizer9.Add( self.m_staticText14, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )
# select month
m_choice1Choices = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]
self.m_choice1 = wx.Choice( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_choice1Choices, 0 )
self.m_choice1.SetSelection( 0 )
bSizer9.Add( self.m_choice1, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )
self.m_staticText15 = wx.StaticText( self, wx.ID_ANY, u"select Day", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText15.Wrap( -1 )
bSizer9.Add( self.m_staticText15, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )
# select day
m_choice2Choices = [str(i) for i in range(1,31)]
self.m_choice2 = wx.Choice( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_choice2Choices, 0 )
self.m_choice2.SetSelection( 0 )
bSizer9.Add( self.m_choice2, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )
self.SetSizer( bSizer9 )
self.Layout()
self.Centre( wx.BOTH )
app = wx.App()
myFrame().Show()
app.MainLoop()
`
The problem does not really reside in the wx.Choice instead it's how do I offer different day options for different months.
The Choice issue is simply addressed by changes to the items in its list and that can be done by a Bind to the Month choice.
Simply put, if the Month is changed, alter the list of days as appropriate to the month. (The ditty, "30 days hath September, April, June and November. All the rest have 31, excepting February alone")
Below, somewhat untested but you get the idea, I Bind the month choice to a callback which resets the list of days for the chosen month.
As a side note, check your range command, the stop value is where it stops, so range(1,31) will give you 1...30
import wx
import datetime
from calendar import monthrange
year = datetime.datetime.now().year
month_days = []
for i in range(1,13):
month_days.append(monthrange(year,i)[1])
class myFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__ ( self, None, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
bSizer9 = wx.BoxSizer( wx.VERTICAL )
self.m_staticText14 = wx.StaticText( self, wx.ID_ANY, u"select Month", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText14.Wrap( -1 )
bSizer9.Add( self.m_staticText14, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )
# select month
m_choice1Choices = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]
self.m_choice1 = wx.Choice( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_choice1Choices, 0 )
self.m_choice1.SetSelection( 0 )
bSizer9.Add( self.m_choice1, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )
self.m_staticText15 = wx.StaticText( self, wx.ID_ANY, u"select Day", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText15.Wrap( -1 )
bSizer9.Add( self.m_staticText15, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )
# select day
#m_choice2Choices = [str(i) for i in range(1,31)]
mth_idx = self.m_choice1.GetSelection()
self.m_choice2Choices = [str(i) for i in range(1,month_days[mth_idx]+1)]
self.m_choice2 = wx.Choice( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, self.m_choice2Choices, 0 )
self.m_choice2.SetSelection( 0 )
bSizer9.Add( self.m_choice2, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )
self.m_choice1.Bind(wx.EVT_CHOICE, self.DaysInMonth)
self.SetSizer( bSizer9 )
self.Layout()
self.Centre( wx.BOTH )
def DaysInMonth(self, event):
mth_idx = self.m_choice1.GetSelection()
self.m_choice2Choices = [str(i) for i in range(1,month_days[mth_idx]+1)]
self.m_choice2.SetItems(self.m_choice2Choices)
app = wx.App()
myFrame().Show()
app.MainLoop()
I'm trying to make a program in Python 3.3.0 to train with Tkinter, but when I try to put images on buttons which are created in a loop, I obtain a few buttons that don't work (I can't click on them and they don't have images), and the last one is working and with the image on it. Here there's the code:
elenco = [immagine1, immagine2, immagine3, immagine 4]
class secondWindow:
def __init__(self):
self.secondWindow = Tk()
self.secondWindow.geometry ('500x650+400+30')
class mainWindow:
def __init__(self):
self.mainWindow = Tk()
self.mainWindow.geometry ('1100x650+100+10')
self.mainWindow.title('MainWindow')
def Buttons(self, stringa):
i = 0
for _ in elenco:
if stringa in _.lower():
j = int(i/10)
self.IM = PIL.Image.open (_ + ".jpg")
self.II = PIL.ImageTk.PhotoImage (self.IM)
self.button = Button(text = _, compound = 'top', image = self.II, command = secondWindow).grid(row = j, column = i-j*10)
i += 1
def mainEnter (self):
testoEntry = StringVar()
self.mainEntry = Entry(self.mainWindow, textvariable = testoEntry).place (x = 900, y = 20)
def search ():
testoEntry2 = testoEntry.get()
if testoEntry2 == "":
pass
else:
testoEntry2 = testoEntry2.lower()
mainWindow.Buttons(self, testoEntry2)
self.button4Entry = Button (self.mainWindow, text = 'search', command = search).place (x = 1050, y = 17)
MW = mainWindow()
MW.mainEnter()
mainloop()
If I try to create buttons in a loop without images, they work:
def Buttons(self, stringa):
i = 0
for _ in elenco:
if stringa in _.lower():
j = int(i/10)
self.button = Button(text = _, command = secondWindow).grid(row = j, column = i-j*10)
i += 1
And if I try to create a button with an image but not in a loop, it works too:
im = PIL.Image.open("immagine1.jpg")
ge = PIL.ImageTk.PhotoImage (im)
butt = Button(text = 'immagine', compound = 'top', image = ge, command = secondWindow).grid(row = 0, column = 0)
Let's say you have images named "image-i.png", i=0,..,9.
When I execute the following code (with python 3.5) I obtain ten working buttons with image and text:
from tkinter import Tk, Button, PhotoImage
root = Tk()
images = []
buttons = []
for i in range(10):
im = PhotoImage(master=root, file="image-%i.png" % i)
b = Button(root, text="Button %i" % i, image=im, compound="left",
command=lambda x=i: print(x))
b.grid(row=i)
images.append(im)
buttons.append(b)
root.mainloop()
I have a chat window for the client portion of a chat application that uses Tkinter for the GUI:
import socket
import select
import time
from threading import Thread
from multiprocessing import Process
import sys
from tkinter import *
HOST = "localhost"
PORT = 5678
client_socket = socket.socket()
client_socket.settimeout(2)
try:
client_socket.connect((HOST, PORT))
except:
print("Connection failed.")
sys.exit()
print("Connected to [" + str(HOST) + "," + str(PORT) + "] successfully")
class ChatWindow:
def __init__(self):
form = Tk()
form.minsize(200, 200)
form.resizable(0, 0)
form.title("Chat")
box = Entry(form)
form.bind("<Return>", lambda x: self.sendmessage(self.textbox.get()))
area = Text(form, width=20, height=10)
area.config(state=DISABLED)
area.grid(row=0, column=1, padx=5, pady=5, sticky=W)
box.grid(row=1, column=1, padx=5, pady=5, sticky=W)
self.textbox = box
self.textarea = area
p1 = Process(target=updating)
p1.start()
p2 = Process(target=tryrecvmessage)
p2.start()
def addchat(self, msg, clear=False):
self.textarea.config(state=NORMAL)
self.textarea.insert(END, msg + "\n")
if clear:
# Option to clear text in box on adding
self.textbox.delete(0, END)
self.textarea.see(END)
self.textarea.config(state=DISABLED)
def sendmessage(self, msg):
data = str.encode(msg)
client_socket.send(data)
self.addchat("<You> " + msg, True)
def updating(self):
while True:
form.update()
form.update_idletasks()
time.sleep(0.01)
def tryrecvmessage(self):
while True:
read_sockets, write_sockets, error_sockets = select.select([client_socket], [], [])
for sock in read_sockets:
data = sock.recv(4096)
if data:
self.addchat(data)
else:
self.addchat("Disconnected...")
sys.exit()
if __name__ == "__main__":
window = ChatWindow()
I want the updating() function and the tryrecvmessage() function to run simultaneously, so that the GUI continues to update while the client still receives messages from the server. I've tried using the threading module as well, but I need to have the threads created below where the other functions are defined, but the other functions need to be defined below __init__(). What do I do?
You can attach the functions to the Tk event loop using the after method, as I explained in this question. Essentially the syntax for after goes like this:
after(ms, command = [function object])
What it does is attach the function object passed in as the command argument to the Tk event loop, repeating it each time ms milliseconds has passed.
One caveat here: you would want to remove the while True from the functions as after would be constantly repeating them anyway.
I made this game in python 2.7 and it worked in .py format but when I compiled it with py2exe it suddenly broke. It gave me this error:
"Microsoft Visuak C++ Runtime Library
Runtime Error!
Program C:\Python27\Helmetdodger\Stuffz\main.exe
This application has requested the Runtime to terminate it in an unusual way.
Please contact the program's support team."
The code:
import pygame
import random, sys, os
from pygame.locals import *
WINDOWWIDTH = 1200
WINDOWHEIGHT = 900
TEXTCOLOR = (255, 255, 255)
BACKGROUNDCOLOR = (0, 0, 0)
FPS = 40
BADDIEMINSIZE = 10
BADDIEMAXSIZE = 40
BADDIEMINSPEED = 1
BADDIEMAXSPEED = 8
ADDNEWBADDIERATE = 6
PLAYERMOVERATE = 5
def terminate():
pygame.quit()
os.exit(1)
def waitForPlayerToPressKey():
while True:
for event in pygame.event.get():
if event.type == QUIT:
terminate()
if event.type == KEYDOWN:
if event.key == K_ESCAPE: # pressing escape quits
terminate()
return
def playerHasHitBaddie(playerRect, baddies):
for b in baddies:
if playerRect.colliderect(b['rect']):
return True
return False
def drawText(text, font, surface, x, y):
textobj = font.render(text, 1, TEXTCOLOR)
textrect = textobj.get_rect()
textrect.topleft = (x, y)
surface.blit(textobj, textrect)
# set up pygame, the window, and the mouse cursor
pygame.init()
mainClock = pygame.time.Clock()
windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
pygame.display.set_caption('Helmetdodger')
pygame.mouse.set_visible(False)
# set up fonts
font = pygame.font.SysFont(None, 48)
# set up sounds
gameOverSound = pygame.mixer.Sound('gameover.wav')
pygame.mixer.music.load('background.mid')
# set up images
playerImage1 = pygame.image.load('player1.png')
powerImage = pygame.image.load('power.png')
playerRect = playerImage1.get_rect()
baddieImage1 = pygame.image.load('baddie.png')
baddieImage2 = pygame.image.load('baddie1.png')
baddieImage3 = pygame.image.load('baddie2.png')
baddieImage4 = pygame.image.load('baddie3.png')
baddieImage5 = pygame.image.load('baddie4.png')
baddieImage6 = pygame.image.load('baddie5.png')
baddieImage7 = pygame.image.load('baddie6.png')
baddieImage8 = pygame.image.load('baddie7.png')
baddieImage9 = pygame.image.load('baddie8.png')
baddieImage10 = pygame.image.load('baddie9.png')
baddieImage11 = pygame.image.load('baddie10.png')
baddieImage12 = pygame.image.load('baddie11.png')
baddieImage13 = pygame.image.load('baddie12.png')
baddieImage14 = pygame.image.load('baddie13.png')
baddieImage15 = pygame.image.load('baddie14.png')
baddieImage16 = pygame.image.load('baddie15.png')
baddieImage17 = pygame.image.load('baddie16.png')
baddieImage18 = pygame.image.load('baddie17.png')
baddieImage19 = pygame.image.load('baddie18.png')
baddieImage20 = pygame.image.load('baddie19.png')
baddieImage21 = pygame.image.load('baddie20.png')
baddieImage22 = pygame.image.load('baddie21.png')
baddieImage23 = pygame.image.load('baddie22.png')
baddieImage24 = pygame.image.load('baddie23.png')
baddieImage25 = pygame.image.load('baddie24.png')
baddieImage26 = pygame.image.load('baddie25.png')
baddieImage27 = pygame.image.load('baddie26.png')
baddieImage28 = pygame.image.load('baddie27.png')
baddieImage29 = pygame.image.load('baddie28.png')
baddieImage30 = pygame.image.load('baddie29.png')
baddieImages = [baddieImage1, baddieImage2, baddieImage3, baddieImage4, baddieImage5, baddieImage6, baddieImage7, baddieImage8, baddieImage9, baddieImage10, baddieImage11, baddieImage12, baddieImage13, baddieImage14, baddieImage15, baddieImage16, baddieImage17, baddieImage18, baddieImage19, baddieImage20, baddieImage21, baddieImage22, baddieImage23, baddieImage24, baddieImage25, baddieImage26, baddieImage27, baddieImage28, baddieImage29, baddieImage20]
# show the "Start" screen
drawText('Helmetdodger', font, windowSurface, (WINDOWWIDTH / 3), (WINDOWHEIGHT / 3))
drawText('Press a key to start.', font, windowSurface, (WINDOWWIDTH / 3) - 30, (WINDOWHEIGHT / 3) + 50)
pygame.display.update()
waitForPlayerToPressKey()
#Get highscore
topScore = 0
try:
file = open('hs.txt', "r")
topScore = file.read()
topScore = int(topScore)
file.close()
except:
topScore = 0
while True:
# set up the start of the game
baddies = []
score = 0
playerRect.topleft = (WINDOWWIDTH / 2, WINDOWHEIGHT - 50)
moveLeft = moveRight = moveUp = moveDown = False
reverseCheat = slowCheat = False
baddieAddCounter = 0
pygame.mixer.music.play(-1, 0.0)
powerCount = 0
while True: # the game loop runs while the game part is playing
score += 1 # increase score
for event in pygame.event.get():
if event.type == QUIT:
terminate()
if event.type == KEYDOWN:
if event.key == ord('z'):
reverseCheat = True
if event.key == ord('x'):
slowCheat = True
if event.key == K_LEFT or event.key == ord('a'):
moveRight = False
moveLeft = True
if event.key == K_RIGHT or event.key == ord('d'):
moveLeft = False
moveRight = True
if event.key == K_UP or event.key == ord('w'):
moveDown = False
moveUp = True
if event.key == K_DOWN or event.key == ord('s'):
moveUp = False
moveDown = True
if event.type == KEYUP:
if event.key == ord('z'):
reverseCheat = False
score = 0
if event.key == ord('x'):
slowCheat = False
score = 0
if event.key == K_ESCAPE:
terminate()
if event.key == K_LEFT or event.key == ord('a'):
moveLeft = False
if event.key == K_RIGHT or event.key == ord('d'):
moveRight = False
if event.key == K_UP or event.key == ord('w'):
moveUp = False
if event.key == K_DOWN or event.key == ord('s'):
moveDown = False
if event.type == MOUSEMOTION:
# If the mouse moves, move the player where the cursor is.
playerRect.move_ip(event.pos[0] - playerRect.centerx, event.pos[1] - playerRect.centery)
# Add new baddies at the top of the screen, if needed.
if not reverseCheat and not slowCheat:
baddieAddCounter += 1
if baddieAddCounter == ADDNEWBADDIERATE:
baddieCount = random.randrange(len(baddieImages))
baddieAddCounter = 0
baddieSize = random.randint(BADDIEMINSIZE, BADDIEMAXSIZE)
newBaddie = {'rect': pygame.Rect(random.randint(0, WINDOWWIDTH-baddieSize), 0 - baddieSize, baddieSize, baddieSize),
'speed': random.randint(BADDIEMINSPEED, BADDIEMAXSPEED),
'surface':pygame.transform.scale(baddieImages[baddieCount], (baddieSize, baddieSize)),
}
baddies.append(newBaddie)
# Move the player around.
if moveLeft and playerRect.left > 0:
playerRect.move_ip(-1 * PLAYERMOVERATE, 0)
if moveRight and playerRect.right < WINDOWWIDTH:
playerRect.move_ip(PLAYERMOVERATE, 0)
if moveUp and playerRect.top > 0:
playerRect.move_ip(0, -1 * PLAYERMOVERATE)
if moveDown and playerRect.bottom < WINDOWHEIGHT:
playerRect.move_ip(0, PLAYERMOVERATE)
# Move the mouse cursor to match the player.
pygame.mouse.set_pos(playerRect.centerx, playerRect.centery)
# Move the baddies down.
for b in baddies:
if not reverseCheat and not slowCheat:
b['rect'].move_ip(0, b['speed'])
elif reverseCheat:
b['rect'].move_ip(0, -5)
elif slowCheat:
b['rect'].move_ip(0, 1)
# Delete baddies that have fallen past the bottom.
for b in baddies[:]:
if b['rect'].top > WINDOWHEIGHT:
baddies.remove(b)
# Draw the game world on the window.
windowSurface.fill(BACKGROUNDCOLOR)
# Draw the score and top score.
drawText('Score: %s' % (score), font, windowSurface, 10, 0)
drawText('Top Score: %s' % (topScore), font, windowSurface, 10, 40)
# Draw the player's rectangle
windowSurface.blit(playerImage1, playerRect)
# Draw each baddie
for b in baddies:
windowSurface.blit(b['surface'], b['rect'])
pygame.display.update()
# Check if any of the baddies have hit the player.
if playerHasHitBaddie(playerRect, baddies):
if score > topScore:
topScore = score # set new top score
file = open("hs.txt", "w")
score = str(score)
file.write(score)
file.close()
break
mainClock.tick(FPS)
# Stop the game and show the "Game Over" screen.
pygame.mixer.music.stop()
gameOverSound.play()
drawText('GAME OVER', font, windowSurface, (WINDOWWIDTH / 3), (WINDOWHEIGHT / 3))
drawText('Press a key to play again.', font, windowSurface, (WINDOWWIDTH / 3) - 80, (WINDOWHEIGHT / 3) + 50)
pygame.display.update()
waitForPlayerToPressKey()
gameOverSound.stop()
My buildscript was incorrect, I found a better buildscript online to use instead
try:
from distutils.core import setup
import py2exe, pygame
from modulefinder import Module
import glob, fnmatch
import sys, os, shutil
import operator
except ImportError, message:
raise SystemExit, "Unable to load module. %s" % message
#hack which fixes the pygame mixer and pygame font
origIsSystemDLL = py2exe.build_exe.isSystemDLL # save the orginal before we edit it
def isSystemDLL(pathname):
# checks if the freetype and ogg dll files are being included
if os.path.basename(pathname).lower() in ("libfreetype-6.dll", "libogg-0.dll","sdl_ttf.dll"): # "sdl_ttf.dll" added by arit.
return 0
return origIsSystemDLL(pathname) # return the orginal function
py2exe.build_exe.isSystemDLL = isSystemDLL # override the default function with this one
class pygame2exe(py2exe.build_exe.py2exe): #This hack make sure that pygame default font is copied: no need to modify code for specifying default font
def copy_extensions(self, extensions):
#Get pygame default font
pygamedir = os.path.split(pygame.base.__file__)[0]
pygame_default_font = os.path.join(pygamedir, pygame.font.get_default_font())
#Add font to list of extension to be copied
extensions.append(Module("pygame.font", pygame_default_font))
py2exe.build_exe.py2exe.copy_extensions(self, extensions)
class BuildExe:
def __init__(self):
#Name of starting + .py
self.script = "raw.py"
#Name of program
self.project_name = "main"
#Project url
self.project_url = "about:none"
#Version of program
self.project_version = "0.0"
#License of the program
self.license = "MyApps License"
#Auhor of program
self.author_name = "Me"
self.author_email = "example#example.com"
self.copyright = "Copyright (c) 2009 Me."
#Description
self.project_description = "MyApps Description"
#Icon file (None will use pygame default icon)
self.icon_file = None
#Extra files/dirs copied to game
self.extra_datas = []
#Extra/excludes python modules
self.extra_modules = []
self.exclude_modules = []
#DLL Excludes
self.exclude_dll = ['']
#python scripts (strings) to be included, seperated by a comma
self.extra_scripts = []
#Zip file name (None will bundle files in exe instead of zip file)
self.zipfile_name = None
#Dist directory
self.dist_dir ='C:\Python27\dist'
## Code from DistUtils tutorial at http://wiki.python.org/moin/Distutils/Tutorial
## Originally borrowed from wxPython's setup and config files
def opj(self, *args):
path = os.path.join(*args)
return os.path.normpath(path)
def find_data_files(self, srcdir, *wildcards, **kw):
# get a list of all files under the srcdir matching wildcards,
# returned in a format to be used for install_data
def walk_helper(arg, dirname, files):
if '.svn' in dirname:
return
names = []
lst, wildcards = arg
for wc in wildcards:
wc_name = self.opj(dirname, wc)
for f in files:
filename = self.opj(dirname, f)
if fnmatch.fnmatch(filename, wc_name) and not os.path.isdir(filename):
names.append(filename)
if names:
lst.append( (dirname, names ) )
file_list = []
recursive = kw.get('recursive', True)
if recursive:
os.path.walk(srcdir, walk_helper, (file_list, wildcards))
else:
walk_helper((file_list, wildcards),
srcdir,
[os.path.basename(f) for f in glob.glob(self.opj(srcdir, '*'))])
return file_list
def run(self):
if os.path.isdir(self.dist_dir): #Erase previous destination dir
shutil.rmtree(self.dist_dir)
#Use the default pygame icon, if none given
if self.icon_file == None:
path = os.path.split(pygame.__file__)[0]
self.icon_file = os.path.join(path, 'pygame.ico')
#List all data files to add
extra_datas = []
for data in self.extra_datas:
if os.path.isdir(data):
extra_datas.extend(self.find_data_files(data, '*'))
else:
extra_datas.append(('.', [data]))
setup(
cmdclass = {'py2exe': pygame2exe},
version = self.project_version,
description = self.project_description,
name = self.project_name,
url = self.project_url,
author = self.author_name,
author_email = self.author_email,
license = self.license,
# targets to build
windows = [{
'script': self.script,
'icon_resources': [(0, self.icon_file)],
'copyright': self.copyright
}],
options = {'py2exe': {'optimize': 2, 'bundle_files': 2, 'compressed': True, \
'excludes': self.exclude_modules, 'packages': self.extra_modules, \
'dll_excludes': self.exclude_dll,
'includes': self.extra_scripts} },
zipfile = self.zipfile_name,
data_files = extra_datas,
dist_dir = self.dist_dir
)
if os.path.isdir('build'): #Clean up build dir
shutil.rmtree('build')
if __name__ == '__main__':
if operator.lt(len(sys.argv), 2):
sys.argv.append('py2exe')
BuildExe().run() #Run generation
raw_input("Press any key to continue") #Pause to let user see that things ends