简体   繁体   中英

Python Tkinter Thread - mainloop in thread

I'm trying to program a game. If I press the "new game" button, the game starts. But because the game uses "while 1", the Tkinter never refreshes after the game starts. I tried to it using threading but it writes:

Unhandled exception in thread started by <function refresh at 0xb7465c6c>
Traceback (most recent call last):
File "Alchymist_lab.py", line 22, in refresh
okno.mainloop()
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1035, in mainloop
self.tk.mainloop(n)
RuntimeError: Calling Tcl from different appartment

Here is the code:

    #importace modulů
import thread
from Tkinter import *
import base64
from pygame import *
import os

okno=Tk() #incializace okna pro tlačítka
okno.title("alchymist lab") #titul okna



def refresh():
    okno.mainloop()

def first_time():
    gamesave = [base64.b64encode("10000"), base64.b64encode("0"), base64.b64encode("0")]  #zakódovávání počátečních hodnot (peníze, bankovky, skóre) 
    file = open(os.path.dirname(os.path.abspath(__file__))+"/gamesave.txt", "w") #otevíraní + vytváření souboru s gamesavem
    file.write(str(gamesave)) #zapisování zakódovaných hodnot
    file.close #zavírání souboru 
    hra(10000,0,0) #otevírání hry s následujícími hodnotami: peníze 10000 , bankovky 0, skóre 0

def hra(p,b,s):
    start_panel=okno.winfo_screenwidth()-2*okno.winfo_screenheight()/5 #výpočet začátku panelu tak "aby to dobře vypadalo"
    base_width=start_panel+219-1 # výpočet šířky od které se dopočítává
    base_start_panel=800 #výpočet základního začátku panelu od kterého se pak dopočítává
    real_width=okno.winfo_screenwidth() #opravdpvá šířka obrazovky
    add_width=real_width-base_width #výpočet čísla ketré bude připočteno k šířce panelu 

    effect_bottle=os.path.dirname(os.path.abspath(__file__)) + "/efektova_lahev.png" #hledání obrázku efektové lahve
    effect_bottle_obr=image.load(effect_bottle) #nahrávání obrázku efektové lahve
    water_bottle=os.path.dirname(os.path.abspath(__file__))+ "/vodni_lahev.png" # hledání obrázku vodní lahve 
    water_bottle_obr=image.load(water_bottle) #nahrávání obrázku vodní lahve
    explosive_bottle=os.path.dirname(os.path.abspath(__file__))+ "/vybusna_lahev.png" #hledání obrázku výbušné lahve
    explosive_bottle_obr=image.load(explosive_bottle) #nahrávání obrázku výbušné lahve
    explosive_bottle_blue=os.path.dirname(os.path.abspath(__file__))+"/vybusna_lahev_blue.png" # hledání obrázku výbušné lahve s modrým pozadím
    explosive_bottle_blue_obr=image.load(explosive_bottle_blue) #nahrávání obrázku

    width = okno.winfo_screenwidth()  # šířka obrazovky
    height= okno.winfo_screenheight() # výška obrazovky



    while 1:   #hlavní smyčka
        clicked="no" #přednastavení proměné o kliknutí
        screen = display.set_mode((width, height)) #incializace obrazovky
        game = screen.subsurface (0,0,start_panel,okno.winfo_screenheight())
        panel = screen.subsurface (start_panel,0,219+add_width-4,okno.winfo_screenheight()) #incializace panelu
        game.fill([0,0,255]) #vybarvení obrazovky
        panel.fill([0,255,0]) #vybarvení panelu
        mouse_position=mouse.get_pos() #pozice myši
        panel.blit(effect_bottle_obr,(0,0)) #vykreslení obrázku efektové lahve na panel
        panel.blit(water_bottle_obr,(0,160)) #vykreslení obrázku vodní lahve na panel
        panel.blit(explosive_bottle_obr,(0,320))#vykreslení obrázku výbušné lahve na panel
        screen.blit(explosive_bottle_blue_obr,(120,50))#vykreslení obrázku výbušné lahve na obrazovku hry
        if mouse.get_pressed()[0]==1: #pokud je levé tlačítko myši zmáčknuto:
            clicked = "yes" # nastav proměnou kliknuto na ano

        if clicked=="yes": # pokud je proměná kliknuto na ano:
            while 1: # smyčka jako ta hlavní vylepšená o myš pronásledovanou obrázken výbušné lahve na obrazovce hry
                screen = display.set_mode((width, height))
                game = screen.subsurface (0,0,start_panel,okno.winfo_screenheight())
                panel = screen.subsurface (start_panel,0,219+add_width-4,okno.winfo_screenheight())
                game.fill([0,0,255])
                panel.fill([0,255,0])
                mouse_position=mouse.get_pos()
                panel.blit(effect_bottle_obr,(0,0))
                panel.blit(water_bottle_obr,(0,160))
                panel.blit(explosive_bottle_obr,(0,320))
                game.blit(explosive_bottle_blue_obr,(mouse_position))
                display.flip()

                if mouse.get_pressed()[0]==1: # pokud je znova zmáčknuto levé tlačítko myši:
                    break # zastav smyčku

        display.flip() # obnovení obrazovky pro znovunačtení dat, tím se pohybují obrázky pohybují

def continue_game():
    print "nacist do 3 proměných peníze , super peníze , skóre"

start=Button(okno, text="new game", command=first_time) #tlačítko pro novou hru
start.pack() #zarovnání tlačítka

continue_game=Button(okno, text=" continue ", command=continue_game) #tlačítko pro pokračování ve hře
continue_game.pack() #zarovnání tlačítka

end=Button(okno, text="     end     ", command=exit) #tlačítko pro  konec hry
end.pack() #zarovnání tlačítka
thread.start_new_thread(refresh,())
okno.mainloop() #konečné zobrazení

`

Disregard the comments, I write them in Czech because I'm Czech.

I use a loop like this in a similar program

root = Tk()

while True:
    canvas.delete(ALL)
    game_loop()
    draw(canvas)
    canvas.update()
    canvas.after(100)

root.mainloop()

This sorted out the issue with Tkinter not refreshing because an update is called each time. The canvas.after(100) acts to pause the refreshing - you can use this to control frame rate

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