[Tkinter] How can I use Tkinter with pygame - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: GUI (https://python-forum.io/forum-10.html) +--- Thread: [Tkinter] How can I use Tkinter with pygame (/thread-17965.html) |
How can I use Tkinter with pygame - microphone_head - May-01-2019 Hi everyone, Can anyone help me so the code works with pygame and Tkinter (seemingly) simultaneously? I'm also interested in formatting the text and using the appropriate methods, anything to assist would be greatly appreciated . 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 , and have got as far as launching the Tkinterwindow (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 RE: How can I use Tkinter with pygame - microphone_head - May-01-2019 Looks like I was way off . 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 : #!/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. RE: How to run two windows (Tkinter with pygame) - microphone_head - May-01-2019 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 . I need the code to visit the window temporarily (and not close it) before doing more of my other stuff in pygame . 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 RE: How can I use Tkinter with pygame - microphone_head - May-02-2019 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 . Thank you all for your patience . 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 . I found the hardest thing getting this protype built was finding a complete reference guide of TKinter . RE: How can I use Tkinter with pygame - kritesh - May-13-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() |