Posts: 63
Threads: 22
Joined: Aug 2017
Hi everyone,
Can anyone help me so the code works with pygame and Tkinter (seemingly) simultaneously? ![Confused Confused](https://python-forum.io/images/smilies/confused.png) I'm also interested in formatting the text and using the appropriate methods, anything to assist would be greatly appreciated ![Angel Angel](https://python-forum.io/images/smilies/angel.png) .
I'm working on introducing Tkinter into my pygame project to make it easier to test and debug. I normally send the information to the Python shell window but thought it would be much cooler to have the information neatly displayed in a seperate window, ideally having the pygame window doing its thing, while keeping an eye on (some of) the variables in the Tkinter window.
I've done the pygame stuff already ![Smile Smile](https://python-forum.io/images/smilies/smile.png) , and have got as far as launching the Tkinterwindow ![Think Think](https://python-forum.io/images/smilies/eusa_think.gif) (incorrectly I imagine).
import tkinter
import pygame
pygame.init()
pwbr_power = 0
pwbr_duration = 0
pwbr_scrn_refresh = 0
pwbr_elps_time = 0
pwbr_ttl_sec = 0
def fn_pbtkwin_update():
"""
Updates the status information in the tkinter window.
"""
global pwbr_power, pwbr_duration, pwbr_scrn_refresh, pwbr_elps_time
global pwbr_ttl_sec
pwbr_power += 1
pwbr_duration += 0.15
pwbr_elps_time += pwbr_duration
pwbr_scrn_refresh = 0.333
pwbr_ttl_sec += pwbr_elps_time
if pwbr_elps_time > pwbr_scrn_refresh:
pwbr_elps_time = 0
pwbr_duration = 0
caption_pwr = "Power: " + str(pwbr_power)
caption_dur = "Duration: " + str(pwbr_duration)
caption_rfrsh = "Screen Refresh: " + str(pwbr_scrn_refresh)
caption_etime = "Elapsed time: " + str(pwbr_elps_time)
caption_ttl = "Total sec's: " + str(pwbr_ttl_sec)
tkinter.Label(tkwin, text=caption_pwr, fg="black").grid(row=0, column=0)
tkinter.Label(tkwin, text=caption_dur, fg="black").grid(row=1, column=0)
tkinter.Label(tkwin, text=pwbr_scrn_refresh, fg="black").grid(row=2, column=0)
tkinter.Label(tkwin, text=caption_etime, fg="black").grid(row=3, column=0)
tkinter.Label(tkwin, text=caption_ttl, fg="black").grid(row=4, column=0)
tkwin.after(1000, fn_pbtkwin_update)
# fn_pbtkwin_update() ----------------------------------------------------------
tkwin = tkinter.Tk()
tkwin.title("Power Bar")
tkinter.Label(tkwin, text = "Power: 0", fg = "black").grid(row=0, column=0)
tkinter.Label(tkwin, text = "Duration: 0", fg = "black").grid(row=1, column=0)
tkinter.Label(tkwin, text = "Screen Refresh: 0", fg = "black").grid(row=2, column=0)
tkinter.Label(tkwin, text = "Elapsed time: 0", fg = "black").grid(row=3, column=0)
tkinter.Label(tkwin, text = "Total sec's: 0", fg = "black").grid(row=4, column=0)
tkinter.Label(tkwin, text = "Fully charged: False", fg = "black").grid(row=0, column=3)
tkinter.Label(tkwin, text = "Reactor overloading: False", fg = "black").grid(row=1, column=3)
tkinter.Label(tkwin, text = "Power bar status: Normal", fg = "black").grid(row=2, column=3)
tkinter.Label(tkwin, text = "Press [Spacebar] to simulate firing phaser cannons.", fg = "black").grid(row=6, column=1)
tkinter.Label(tkwin, text = "Press [r] to initiate a reactor overload.", fg = "black").grid(row=7, column=1)
tkinter.Label(tkwin, text = "Press [Esc] to quit.", fg = "black").grid(row=7, column=1)
tkwin.after(1000, fn_pbtkwin_update)
pygame.time.wait(1000)
pygame.display.set_mode((640, 480))
quit_loop = False
while quit_loop is not True:
for event in pygame.event.get():
if event.type == pygame.QUIT: # If user clicked close
quit_loop = True # Flag that we are done so we exit this loop
elif event.type == pygame.MOUSEBUTTONUP:
pass
elif event.type == pygame.constants.KEYDOWN:
if event.key == pygame.constants.K_ESCAPE:
quit_loop = True
break
elif event.key == pygame.constants.K_LEFT:
kbd["left"] = True
elif event.key == pygame.constants.K_RIGHT:
kbd["right"] = True
elif event.key == pygame.constants.K_UP:
kbd["up"] = True
elif event.key == pygame.constants.K_DOWN:
kbd["down"] = True
elif event.key == pygame.constants.K_SPACE: # Fire.
kbd["fire"] = True
elif event.key == pygame.constants.K_LCTRL: # Thrust.
kbd["thrust"] = True
elif event.key == pygame.constants.K_r:
kbd["overload"] = True
elif event.type == pygame.constants.KEYUP:
if event.key == pygame.constants.K_LEFT:
kbd["left"] = False
elif event.key == pygame.constants.K_RIGHT:
kbd["right"] = False
elif event.key == pygame.constants.K_UP:
kbd["up"] = False
elif event.key == pygame.constants.K_DOWN:
kbd["down"] = False
elif event.key == pygame.constants.K_SPACE: # Fire.
kbd["fire"] = False
elif event.key == pygame.constants.K_LCTRL: # Thrust.
kbd["thrust"] = False
elif event.key == pygame.constants.K_r:
kbd["overload"] = False
# end if
# end if
# end for loop
# { Paint some graphics on the screen.
# ...
# }.
pygame.display.flip()
tkwin.mainloop()
# end while loop
Posts: 63
Threads: 22
Joined: Aug 2017
Looks like I was way off ![Doh Doh](https://python-forum.io/images/smilies/eusa_doh.gif) . I did read something about backward compatibility but I didn't realise by just how much.
I think I should have started off with something like this ![Think Think](https://python-forum.io/images/smilies/eusa_think.gif) :
#!/usr/bin/env python
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.grid()
self.createwidgets()
def createwidgets(self):
self.quitButton = tk.Button(self, text='Quit', command=self.quit)
self.quitButton.grid()
app = Application()
app.master.title('Sample application')
app.mainloop() Now all I need to do add the extra controls as before, and learn how to update the label's text attribute, to get to where I was before.
Posts: 63
Threads: 22
Joined: Aug 2017
May-01-2019, 06:13 PM
(This post was last modified: May-01-2019, 06:13 PM by microphone_head.)
Making progress but still not there yet.
The examples i've see so far only use the method "mainloop" which looks like a wait until tkinter window has finished ![Undecided Undecided](https://python-forum.io/images/smilies/undecided.png) . I need the code to visit the window temporarily (and not close it) before doing more of my other stuff in pygame ![Sad Sad](https://python-forum.io/images/smilies/sad.png) .
import tkinter as tk
import pygame
pygame.init()
pwbr_power = 0
pwbr_duration = 0
pwbr_scrn_refresh = 0
pwbr_elps_time = 0
pwbr_ttl_sec = 0
class Application(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.grid()
self.createwidgets()
# __init__() ---------------------------------------------------------------
def createwidgets(self):
"""
Creates the numerous widgets that make up the form.
"""
global pwbr_power, pwbr_duration, pwbr_scrn_refresh, pwbr_elps_time
global pwbr_ttl_sec
pwbr_power += 1
pwbr_duration += 0.15
pwbr_elps_time += pwbr_duration
pwbr_scrn_refresh = 0.333
pwbr_ttl_sec += pwbr_elps_time
if pwbr_elps_time > pwbr_scrn_refresh:
pwbr_elps_time = 0
pwbr_duration = 0
caption_pwr = "Power: " + str(pwbr_power)
caption_dur = "Duration: " + str(pwbr_duration)
caption_rfrsh = "Screen Refresh: " + str(pwbr_scrn_refresh)
caption_etime = "Elapsed time: " + str(pwbr_elps_time)
caption_ttl = "Total sec's: " + str(pwbr_ttl_sec)
self.lblpower = tk.Label(self, text=caption_pwr, fg="black")
self.lblduration = tk.Label(self, text=caption_dur, fg="black")
self.lblrefreshrate = tk.Label(self, text=caption_rfrsh, fg="black")
self.lbletime = tk.Label(self, text=caption_etime, fg="black")
self.lbltotalsec = tk.Label(self, text=caption_ttl, fg="black")
self.quitButton = tk.Button(self, text='Quit', command=self.quit)
self.lblpower.grid()
self.lblduration.grid()
self.lblrefreshrate.grid()
self.lbletime.grid()
self.lbltotalsec.grid()
self.quitButton.grid()
self.update()
self.after(1000, self.update_info)
# createwidgets() ----------------------------------------------------------
def update_info(self):
"""
Updates the status information in the tkinter window.
"""
global pwbr_power, pwbr_duration, pwbr_scrn_refresh, pwbr_elps_time
global pwbr_ttl_sec
pwbr_power += 1
pwbr_duration += 0.15
pwbr_elps_time += pwbr_duration
pwbr_scrn_refresh = 0.333
pwbr_ttl_sec += pwbr_elps_time
if pwbr_elps_time > pwbr_scrn_refresh:
pwbr_elps_time = 0
pwbr_duration = 0
caption_pwr = "Power: " + str(pwbr_power)
caption_dur = "Duration: " + str(pwbr_duration)
caption_rfrsh = "Screen Refresh: " + str(pwbr_scrn_refresh)
caption_etime = "Elapsed time: " + str(pwbr_elps_time)
caption_ttl = "Total sec's: " + str(pwbr_ttl_sec)
self.lblpower.config(text=caption_pwr)
self.lblduration.config(text=caption_dur)
self.lblrefreshrate.config(text=caption_rfrsh)
self.lbletime.config(text=caption_etime)
self.lbltotalsec.config(text=caption_ttl)
self.after(1000, self.update_info)
# update_info() ----------------------------------------------------------
# Application() ----------------------------------------------------------------
pygame.display.set_mode((640, 480))
app = Application()
app.master.title("Power Bar")
app.mainloop()
quit_loop = False
while quit_loop is not True:
for event in pygame.event.get():
if event.type == pygame.QUIT: # If user clicked close
quit_loop = True # Flag that we are done so we exit this loop
elif event.type == pygame.MOUSEBUTTONUP:
pass
elif event.type == pygame.constants.KEYDOWN:
if event.key == pygame.constants.K_ESCAPE:
quit_loop = True
break
elif event.key == pygame.constants.K_LEFT:
kbd["left"] = True
elif event.key == pygame.constants.K_RIGHT:
kbd["right"] = True
elif event.key == pygame.constants.K_UP:
kbd["up"] = True
elif event.key == pygame.constants.K_DOWN:
kbd["down"] = True
elif event.key == pygame.constants.K_SPACE: # Fire.
kbd["fire"] = True
elif event.key == pygame.constants.K_LCTRL: # Thrust.
kbd["thrust"] = True
elif event.key == pygame.constants.K_r:
kbd["overload"] = True
elif event.type == pygame.constants.KEYUP:
if event.key == pygame.constants.K_LEFT:
kbd["left"] = False
elif event.key == pygame.constants.K_RIGHT:
kbd["right"] = False
elif event.key == pygame.constants.K_UP:
kbd["up"] = False
elif event.key == pygame.constants.K_DOWN:
kbd["down"] = False
elif event.key == pygame.constants.K_SPACE: # Fire.
kbd["fire"] = False
elif event.key == pygame.constants.K_LCTRL: # Thrust.
kbd["thrust"] = False
elif event.key == pygame.constants.K_r:
kbd["overload"] = False
# end if
# end if
# end for loop
# { Paint some graphics on the screen.
# ...
# }.
pygame.display.flip()
# end while loop
Posts: 63
Threads: 22
Joined: Aug 2017
I think I've acquired enough here in this prototype. I'm going to go ahead and plug this bad boy into my game and start testing ![Dance Dance](https://python-forum.io/images/smilies/eusa_dance.gif) .
Thank you all for your patience ![Smile Smile](https://python-forum.io/images/smilies/smile.png) .
import tkinter as tk
import pygame
pygame.init()
pwbr_power = 0
pwbr_duration = 0
pwbr_scrn_refresh = 0
pwbr_elps_time = 0
pwbr_ttl_sec = 0
pwbr_fcharged = False
pwbr_overload = False # Reactor overload status.
pwbr_status = None
class Application(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.grid()
self.createwidgets()
# __init__() ---------------------------------------------------------------
def _cmd_quit(self):
"""
Terminates the Tkwindow.
"""
global quit_loop
self.master.destroy()
quit_loop = True
# _cmd_quit() --------------------------------------------------------------
def createwidgets(self):
"""
Creates the numerous widgets that make up the form.
"""
global pwbr_power, pwbr_duration, pwbr_scrn_refresh, pwbr_elps_time
global pwbr_ttl_sec
global pwbr_fcharged, pwbr_overload, pwbr_status
col_width = None
pwbr_power += 1
pwbr_duration += 0.15
pwbr_elps_time += pwbr_duration
pwbr_scrn_refresh = 0.333
pwbr_ttl_sec += pwbr_elps_time
pwbr_fcharged = False
pwbr_overload = False # Reactor overload status.
pwbr_status = "Normal"
if pwbr_elps_time > pwbr_scrn_refresh:
pwbr_elps_time = 0
pwbr_duration = 0
caption_pwr = "Power: " + str(pwbr_power)
caption_dur = "Duration: " + str(pwbr_duration)
caption_rfrsh = "Screen Refresh: " + str(pwbr_scrn_refresh)
caption_etime = "Elapsed time: " + str(pwbr_elps_time)
caption_ttl = "Total sec's: " + str(pwbr_ttl_sec)
caption_fcharged = "Fully charged: " + str(pwbr_fcharged)
caption_overload = "Reactor overloading: " + str(pwbr_overload)
caption_status = "Power bar status: " + str(pwbr_status)
caption_hint1 = "Press [Spacebar] to simulate firing phaser cannons."
caption_hint2 = "Press [r] to initiate a reactor overload."
caption_hint3 = "Press [Esc] to quit"
self.lblpower = tk.Label(self, text=caption_pwr, fg="black")
self.lblduration = tk.Label(self, text=caption_dur, fg="black")
self.lblrefreshrate = tk.Label(self, text=caption_rfrsh, fg="black")
self.lbletime = tk.Label(self, text=caption_etime, fg="black")
self.lbltotalsec = tk.Label(self, text=caption_ttl, fg="black")
self.lblfcharged = tk.Label(self, text=caption_fcharged, fg="black")
self.lbloverload = tk.Label(self, text=caption_overload, fg="black")
self.lblstatus = tk.Label(self, text=caption_status, fg="black")
self.lblhint1 = tk.Label(self, text=caption_hint1, fg="black")
self.lblhint2 = tk.Label(self, text=caption_hint2, fg="black")
self.lblhint3 = tk.Label(self, text=caption_hint3, fg="black")
self.quitButton = tk.Button(self, text='Quit', command=self._cmd_quit)
self.lblpower.grid(row=0, column=0, sticky="w") #tk.W)
self.lblduration.grid(row=1, column=0)
self.lblrefreshrate.grid(row=2, column=0)
self.lbletime.grid(row=3, column=0)
self.lbltotalsec.grid(row=4, column=0)
self.lblfcharged.grid(row=0, column=3)
self.lbloverload.grid(row=1, column=3)
self.lblstatus.grid(row=2, column=3)
self.lblhint1.grid(row=6, column=2)
self.lblhint2.grid(row=7, column=2)
self.lblhint3.grid(row=8, column=2)
# { Set the width for all the labels in column #1.
col_width = 20
self.lblpower["width"] = col_width
self.lblduration["width"] = col_width
self.lblrefreshrate["width"] = col_width
self.lbletime["width"] = col_width
self.lbltotalsec["width"] = col_width
# }.
# { Set the width for all the labels in column #3.
col_width = 23
self.lblfcharged["width"] = col_width
self.lbloverload["width"] = col_width
self.lblstatus["width"] = col_width
# }.
# { Set the text alignment for all the labels in column #1 & #2.
self.lblpower["anchor"] = "w"
self.lblduration["anchor"] = "w"
self.lblrefreshrate["anchor"] = "w"
self.lbletime["anchor"] = "w"
self.lbltotalsec["anchor"] = "w"
self.lblfcharged["anchor"] = "w"
self.lbloverload["anchor"] = "w"
self.lblstatus["anchor"] = "w"
# }.
# { Send the doc string information of the label object to the
# Python shell.
print(help(self.lblpower))
# }.
self.quitButton.grid(row=6, column=3)
# { Paint the image of the root / main TKinter window on the screen.
self.update()
# }.
# { Set a timeout of a second to callback the routine
# update_info, so the labels are updated with the current (up to
# date) data values.
self.after(1000, self.update_info)
# }.
# createwidgets() ----------------------------------------------------------
def update_info(self):
"""
Updates the status information in the tkinter window.
"""
global pwbr_power, pwbr_duration, pwbr_scrn_refresh, pwbr_elps_time
global pwbr_ttl_sec
pwbr_power += 1
pwbr_duration += 0.15
pwbr_elps_time += pwbr_duration
pwbr_scrn_refresh = 0.333
pwbr_ttl_sec += pwbr_elps_time
if pwbr_elps_time > pwbr_scrn_refresh:
pwbr_elps_time = 0
pwbr_duration = 0
caption_pwr = "Power: " + str(pwbr_power)
caption_dur = "Duration: " + str(pwbr_duration)
caption_rfrsh = "Screen Refresh: " + str(pwbr_scrn_refresh)
caption_etime = "Elapsed time: " + str(pwbr_elps_time)
caption_ttl = "Total sec's: " + str(pwbr_ttl_sec)
self.lblpower.config(text=caption_pwr)
self.lblduration["text"] = caption_dur
self.lblrefreshrate.config(text=caption_rfrsh)
self.lbletime.config(text=caption_etime)
self.lbltotalsec.config(text=caption_ttl)
self.after(1000, self.update_info)
# update_info() ----------------------------------------------------------
# Application() ----------------------------------------------------------------
pygame.display.set_mode((640, 480))
app = Application()
app.master.title("Power Bar")
#app.mainloop()
quit_loop = False
while quit_loop is not True:
for event in pygame.event.get():
if event.type == pygame.QUIT: # If user clicked close
quit_loop = True # Flag that we are done so we exit this loop
elif event.type == pygame.MOUSEBUTTONUP:
pass
elif event.type == pygame.constants.KEYDOWN:
if event.key == pygame.constants.K_ESCAPE:
quit_loop = True
break
elif event.key == pygame.constants.K_LEFT:
kbd["left"] = True
elif event.key == pygame.constants.K_RIGHT:
kbd["right"] = True
elif event.key == pygame.constants.K_UP:
kbd["up"] = True
elif event.key == pygame.constants.K_DOWN:
kbd["down"] = True
elif event.key == pygame.constants.K_SPACE: # Fire.
kbd["fire"] = True
elif event.key == pygame.constants.K_LCTRL: # Thrust.
kbd["thrust"] = True
elif event.key == pygame.constants.K_r:
kbd["overload"] = True
elif event.type == pygame.constants.KEYUP:
if event.key == pygame.constants.K_LEFT:
kbd["left"] = False
elif event.key == pygame.constants.K_RIGHT:
kbd["right"] = False
elif event.key == pygame.constants.K_UP:
kbd["up"] = False
elif event.key == pygame.constants.K_DOWN:
kbd["down"] = False
elif event.key == pygame.constants.K_SPACE: # Fire.
kbd["fire"] = False
elif event.key == pygame.constants.K_LCTRL: # Thrust.
kbd["thrust"] = False
elif event.key == pygame.constants.K_r:
kbd["overload"] = False
# end if
# end if
# end for loop
# { Paint some graphics on the screen.
# ...
# }.
pygame.display.flip()
app.master.update()
# end while loop
pygame.quit() PS. That was a lot harder than I thought it was going to be ![Cry Cry](https://python-forum.io/images/smilies/cry.png) . I found the hardest thing getting this protype built was finding a complete reference guide of TKinter ![Dodgy Dodgy](https://python-forum.io/images/smilies/dodgy.png) .
Posts: 3
Threads: 0
Joined: May 2019
The first one is made with pygame, which runs smooth and is straight forward efficient. The second version made with tkinter is slow and laggy. I even had to batch edit pixels which does not help much. Both of them function exactly the same but the tkinter version is just not as fast.
# Used to store debug file
#import os
#BASE_DIR = os.path.realpath(os.path.dirname(__file__))
# Some config width height settings
canvas_width = 640
canvas_height = 480
# Create a window
window = Tk()
# Set the window title
window.wm_title("Sine Wave")
# Put a canvas on the window
canvas = Canvas(window, width=canvas_width, height=canvas_height, bg="#000000")
canvas.pack()
# Create a image, this acts as the canvas
img = PhotoImage(width=canvas_width, height=canvas_height)
# Put the image on the canvas
canvas.create_image((canvas_width/2, canvas_height/2), image=img, state="normal")
def sine_wave_anim():
# Update sine wave
frequency = 4
amplitude = 50 # in px
speed = 1
# We create a blank area for what where we are going to draw
color_table = [["#000000" for x in range(0, canvas_width)] for y in range(0, amplitude*2)]
# And draw on that area
for x in range(0, canvas_width):
y = int(amplitude + amplitude*math.sin(frequency*((float(x)/canvas_width)*(2*math.pi) + (speed*time.time()))))
color_table[y][x] = "#ffff00"
# Don't individually put pixels as tkinter sucks at this
#img.put("#ffff00", (x, y))
# Then batch put it on the canvas
# tkinter is extremely inefficient doing it one by one
img.put(''.join("{" + (" ".join(str(color) for color in row)) + "} " for row in color_table), (0, int(canvas_height/2 - amplitude)))
# Debug the color_table
#with open(os.path.join(BASE_DIR, 'output.txt'), "w+") as text_file:
# text_file.write(''.join("{" + (" ".join(str(color) for color in row)) + "} " for row in color_table))
# Continue the animation as fast as possible. A value of 0 (milliseconds), blocks everything.
window.after(1, sine_wave_anim)
# Start off the anim
sine_wave_anim()
mainloop()
|