Python Tkinter Thread - 线程中的主循环



我正在尝试编写一个游戏。如果我按下"新游戏"按钮,游戏就会开始。但由于游戏使用"while 1",因此 Tkinter 在游戏开始后永远不会刷新。我尝试使用线程来使用它,但它写道:

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

这是代码:

    #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í

'

忽略评论,我用捷克语写,因为我是捷克人。

我在类似的程序中使用了这样的循环

root = Tk()
while True:
    canvas.delete(ALL)
    game_loop()
    draw(canvas)
    canvas.update()
    canvas.after(100)
root.mainloop()

这解决了 Tkinter 无法刷新的问题,因为每次都会调用更新。canvas.after(100) 用于暂停刷新 - 您可以使用它来控制帧速率

最新更新