首页 > 解决方案 > 调用函数时不会创建 Python Tkinter Tic-Tac-Toe 窗口

问题描述

我正在使用画布作为学校作业在 python tkinter 上制作井字游戏,对于重启按钮,我找到了 2 个解决方案:

1)重置所有变量和画布。

2)打开一个新窗口并关闭前一个窗口,但无法跟踪胜利。

我目前选择了 2),因为我虽然是 python 和 tkinter 的新手,所以更容易制作。当我尝试重置画布时,我想简单地在它上面画一个大的白色方块并画回网格线,但是当我启动它时它只是出错并给了我:can't invoke "button" command: application has been destroyed.

当我搜索如何做到这一点时,似乎我必须执行主要功能(创建窗口、画布和按钮)并在程序开始时调用它,然后使用.destroy()main()在函数中重新启动。我在这篇没有重启问题的帖子上找到了它:井字游戏使用 python tkinter

问题是......当我启动程序时......窗口甚至不会弹出。我确实在最后输入了 main() ,但要么我做了一些愚蠢的事情,要么我编码的东西根本不起作用。

这是代码,对于整个代码中的法语单词感到抱歉,这是因为我显然是法语:)

## Importation des Modules ##
from tkinter import *

## Création de la fenêtre / creating the sheet ##
def main():
    fen = Tk()
    fen.title('Game')
    texte=Label(fen, text="Go ahead Mr Joestar")
    texte.grid(row=0, column=0)
    pos=Label(fen, text='(Nope;Nope)')
    pos.grid(row=0, column=1)

##Canvas##
    dessin=Canvas(fen, bg="white", width=301, height=301) #canvas
    dessin.grid(row = 1, column = 0, padx=2, pady=2, columnspan=2) #Position Canvas

    dessin.create_line(99, 0, 99, 301, width=1, fill='black')
    dessin.create_line(201, 0, 201, 301, width=1, fill='black')
    dessin.create_line(0, 99, 301, 99, width=1, fill='black')
    dessin.create_line(0, 201, 301, 201, width=1, fill='black')
##buttons##
    bouton_quitter = Button(fen, text='Quitter', command=fen.destroy) #Quitter
    bouton_quitter.grid(row=2, column=0)

    bouton_restart = Button(fen, text='Recommencer', command=restart(fen)) #Restart
    bouton_restart.grid(row=2, column=1)
##binds##
    dessin.bind("<Motion>", Position) #event motion mouse
    dessin.bind("<Button-1>", cases) #event mouse 1

##Liste / list ###
list=[[0,0,0],[0,0,0],[0,0,0]]
print(list)
##Variables##
Joueur=1 #Joueur1 (nommé Joestar) = 1 ; Joueur2 (nommé DArbi) = -1 / player1=1 ; player2=-1
V1=0#condition victoire j1 / Winning condition for player 1
V2=0#condition victoire j2 / Winning condition for player 2
IDC=0 #identifier la case / for identifying which cell
turns=0#nombre de tours

##Function position##
def Position(event):
    pos.configure(text='('+str(event.x)+'.'+str(event.y)+')')

##Fuction win##
def win(list, V1, V2): #pour voir qui a gagné / to see who won
    if list[0][0]+list[0][1]+list[0][2]==3: #Vérification lignes
        V1=1
    elif list[0][0]+list[0][1]+list[0][2]==-3:
        V2=1
    if list[1][0]+list[1][1]+list[1][2]==3:
        V1=1
    elif list[1][0]+list[1][1]+list[1][2]==-3:
        V2=1
    if list[2][0]+list[2][1]+list[2][2]==3:
        V1=1
    elif list[2][0]+list[2][1]+list[2][2]==-3:
        V2=1
    if list[0][0]+list[1][0]+list[2][0]==3: #Vérification colones
        V1=1
    elif list[0][0]+list[1][0]+list[2][0]==-3:
        V2=1
    if list[0][1]+list[1][1]+list[2][1]==3:
        V1=1
    elif list[0][1]+list[1][1]+list[2][1]==-3:
        V2=1
    if list[0][0]+list[1][1]+list[2][2]==3:#Diagonales
        V1=1
    elif list[0][0]+list[1][1]+list[2][2]==-3:
        V2=1
    if list[0][2]+list[1][1]+list[2][0]==3:
        V1=1
    elif list[0][2]+list[1][1]+list[2][0]==-3:
        V2=1
    if V1==1 and V2==0:
        texte.configure(text='Joestar win !')
    elif V1==0 and V2==1:
        texte.configure(text='DArbi win')
    elif turns==9 and V1==0 and V2==0 or V1==1 and V2==1:
        texte.configure(text='No one won...')

##Function remplir##
def remplir(list,IDC):#pour remplir les cases
    global Joueur #to edit Joueur for all the program
    if IDC ==1:#Cell 1
        if list[0][0]==0:
            list[0][0]=Joueur
            if list[0][0]==1:
                dessin.create_line(10,10,90,90, width=1) #cell 1 cross
                dessin.create_line(10, 90, 90, 10, width=1)
            elif list[0][0]==-1:
                dessin.create_oval(10, 10, 90, 90, width=1)#cell 1 circle
            Joueur=(-Joueur)#nextplayer
        elif list[0][0]!=0:
            print("case déjà prise")
    if IDC ==2:#Cell 2
        if list[0][1]==0:
            list[0][1]=Joueur
            if list[0][1]==1:
                dessin.create_line(110,10,190,90, width=1)
                dessin.create_line(110,90,190,10, width=1)
            elif list[0][1]==-1:
                dessin.create_oval(110, 10, 190, 90, width=1)
            Joueur=(-Joueur)
        elif list[0][1]!=0:
            print("case déjà prise")
    if IDC ==3:#Cell 3
        if list[0][2]==0:
            list[0][2]=Joueur
            if list[0][2]==1:
                dessin.create_line(210,10,290,90, width=1)
                dessin.create_line(210,90,290,10, width=1)
            elif list[0][2]==-1:
                dessin.create_oval(210, 10, 290, 90, width=1)
            Joueur=(-Joueur)
        elif list[0][2]!=0:
            print("case déjà prise")
    if IDC ==4: #Cell 4
        if list[1][0]==0:
            list[1][0]=Joueur
            if list[1][0]==1:
                dessin.create_line(10,110,90,190, width=1)
                dessin.create_line(10, 190, 90, 110, width=1)
            elif list[1][0]==-1:
                dessin.create_oval(10, 110, 90, 190, width=1)
            Joueur=(-Joueur)
        elif list[1][0]!=0:
            print("case déjà prise")
    if IDC ==5:#Cell 5
        if list[1][1]==0:
            list[1][1]=Joueur
            if list[1][1]==1:
                dessin.create_line(110,110,190,190, width=1)
                dessin.create_line(110,190,190,110, width=1)
            elif list[1][1]==-1:
                dessin.create_oval(110, 110, 190, 190, width=1)
            Joueur=(-Joueur)
        elif list[1][1]!=0:
            print("case déjà prise")
    if IDC ==6:#Cell 6
        if list[1][2]==0:
            list[1][2]=Joueur
            if list[1][2]==1:
                dessin.create_line(210,110,290,190, width=1)
                dessin.create_line(210,190,290,110, width=1)
            elif list[1][2]==-1:
                dessin.create_oval(210, 110, 290, 190, width=1)
            Joueur=(-Joueur)
        elif list[1][2]!=0:
            print("case déjà prise")
    if IDC ==7: #Cell 7
        if list[2][0]==0:
            list[2][0]=Joueur
            if list[2][0]==1:
                dessin.create_line(10,210,90,290, width=1)
                dessin.create_line(10, 290, 90, 210, width=1)
            elif list[2][0]==-1:
                dessin.create_oval(10, 210, 90, 290, width=1)
            Joueur=(-Joueur)
        elif list[2][0]!=0:
            print("case déjà prise")
    if IDC ==8:#Cell 8
        if list[2][1]==0:
            list[2][1]=Joueur
            if list[2][1]==1:
                dessin.create_line(110,210,190,290, width=1)
                dessin.create_line(110,290,190,210, width=1)
            elif list[2][1]==-1:
                dessin.create_oval(110, 210, 190, 290, width=1)
            Joueur=(-Joueur)
        elif list[2][1]!=0:
            print("case déjà prise")
    if IDC ==9:#Cell 9
        if list[2][2]==0:
            list[2][2]=Joueur
            if list[2][2]==1:
                dessin.create_line(210,210,290,290, width=1)
                dessin.create_line(210,290,290,210, width=1)
            elif list[2][2]==-1:
                dessin.create_oval(210, 210, 290, 290, width=1)
            Joueur=(-Joueur)
        elif list[2][2]!=0:
            print("case déjà prise")

##Fuction cases##
def cases(event):
    if int(event.x)>2 and int(event.x)<100 and int(event.y)>0 and int(event.y)<100: #CASE A1
        print('A1')
        IDC=1
        remplir(list,IDC)
        win(list, V1, V2)
    elif int(event.x)>102 and int(event.x)<200 and int(event.y)>0 and int(event.y)<100: #CASE A2
        print('A2')
        IDC=2
        remplir(list,IDC)
        win(list, V1, V2)
    elif int(event.x)>202 and int(event.x)<300 and int(event.y)>0 and int(event.y)<100: #CASE A3
        print('A3')
        IDC=3
        remplir(list,IDC)
        win(list, V1, V2)
    elif int(event.x)>2 and int(event.x)<100 and int(event.y)>100 and int(event.y)<200: #CASE B1
        print('B1')
        IDC=4
        remplir(list,IDC)
        win(list, V1, V2)
    elif int(event.x)>100 and int(event.x)<200 and int(event.y)>102 and int(event.y)<200: #CASE B2
        print('B2')
        IDC=5
        remplir(list,IDC)
        win(list, V1, V2)
    elif int(event.x)>202 and int(event.x)<300 and int(event.y)>102 and int(event.y)<200: #CASE B3
        print('B3')
        IDC=6
        remplir(list,IDC)
        win(list, V1, V2)
    elif int(event.x)>2 and int(event.x)<100 and int(event.y)>202 and int(event.y)<300: #CASE C1
        print('C1')
        IDC=7
        remplir(list,IDC)
        win(list, V1, V2)
    elif int(event.x)>100 and int(event.x)<200 and int(event.y)>202 and int(event.y)<300: #CASE C2
        print('C2')
        IDC=8
        remplir(list,IDC)
        win(list, V1, V2)
    elif int(event.x)>202 and int(event.x)<300 and int(event.y)>202 and int(event.y)<300: #CASE C3
        print('C3')
        IDC=9
        remplir(list,IDC)
        win(list, V1, V2)
    else:
        print('no')

##Fuctions:others##
def restart(fen):
    fen.destroy()
    main()


##Mainloop##
main()

请指出你发现的所有错误或奇怪的东西。

感谢您的时间 !

Edit1:Furas 指出了解决我的问题的一件事:按钮中的 () (command=restart())。它们是阻止我的重新启动按钮与重新启动功能中的任何内容一起工作的原因。谢谢弗拉斯!

感谢您还找到了一种使代码更加简洁紧凑的方法。但是我要改变我编码的内容,因为我不擅长编码,我认为我使用的方法更安全。

我将删除整个“主要”功能并使其重置按钮重置变量和画布。

无论如何再次感谢你。

Edit2:也许我现在应该删除那个帖子,因为真正的问题是重置整个游戏,我发现这是重启按钮(命令=)的问题。

标签: pythontkinter

解决方案


你的问题很少

  1. 你必须使用

    fen.mainloop()
    

    启动从系统获取键/鼠标事件的循环,将它们发送到小部件并在需要时(重新)绘制窗口

  2. command=需要没有(). 如果您必须为函数分配参数,那么您可以使用lambda创建没有参数的函数

    command=lambda:restart(fen)
    
  3. 在里面main()你必须使用globalfor pos, dessin,texte才能在其他函数中访问这些变量

    def main():
        global pos
        global dessin
        global texte
    
  4. list重新开始游戏时必须重置

    def restart(fen):
        global list
    
        list = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
    

    可能您可能必须对其他变量执行相同的操作,但我没有对其进行测试。


顺便说一句:当你在画布上创建对象时,你会得到它的 ID,这样你以后就可以访问它

items_id = dessin.create_line(...)

items_id = dessin.create_oval(...)

您可以将 ID 保留在列表中,稍后您可以使用 ID 从画布中删除项目,而不必destroy打开窗口。

但在这两种情况下,您都必须重置所有其他值。


顺便说一句:你可以remplir转换为IDCrow, column

row = (IDC-1) // 3
column = (IDC-1) % 3

然后您可以使用list[row][column]and create_line(column*100+10, row*100+10, column*100+90, row*100+90, ...)- 您不必编写相同的代码 9 次。


## Importation des Modules ##
from tkinter import *

## Création de la fenêtre / creating the sheet ##
def main():
    global pos
    global dessin
    global texte

    fen = Tk()
    fen.title('Game')
    texte=Label(fen, text="Go ahead Mr Joestar")
    texte.grid(row=0, column=0)
    pos=Label(fen, text='(Nope;Nope)')
    pos.grid(row=0, column=1)

##Canvas##
    dessin=Canvas(fen, bg="white", width=301, height=301) #canvas
    dessin.grid(row = 1, column = 0, padx=2, pady=2, columnspan=2) #Position Canvas

    dessin.create_line(99, 0, 99, 301, width=1, fill='black')
    dessin.create_line(201, 0, 201, 301, width=1, fill='black')
    dessin.create_line(0, 99, 301, 99, width=1, fill='black')
    dessin.create_line(0, 201, 301, 201, width=1, fill='black')
##buttons##
    bouton_quitter = Button(fen, text='Quitter', command=fen.destroy) #Quitter
    bouton_quitter.grid(row=2, column=0)

    bouton_restart = Button(fen, text='Recommencer', command=lambda:restart(fen)) #Restart
    bouton_restart.grid(row=2, column=1)
##binds##
    dessin.bind("<Motion>", Position) #event motion mouse
    dessin.bind("<Button-1>", cases) #event mouse 1
    fen.mainloop()

##Liste / list ###
list=[[0,0,0],[0,0,0],[0,0,0]]
print(list)
##Variables##
Joueur=1 #Joueur1 (nommé Joestar) = 1 ; Joueur2 (nommé DArbi) = -1 / player1=1 ; player2=-1
V1=0#condition victoire j1 / Winning condition for player 1
V2=0#condition victoire j2 / Winning condition for player 2
IDC=0 #identifier la case / for identifying which cell
turns=0#nombre de tours

##Function position##
def Position(event):
    pos.configure(text='('+str(event.x)+'.'+str(event.y)+')')

##Fuction win##
def win(list, V1, V2): #pour voir qui a gagné / to see who won
    if list[0][0]+list[0][1]+list[0][2]==3: #Vérification lignes
        V1=1
    elif list[0][0]+list[0][1]+list[0][2]==-3:
        V2=1
    if list[1][0]+list[1][1]+list[1][2]==3:
        V1=1
    elif list[1][0]+list[1][1]+list[1][2]==-3:
        V2=1
    if list[2][0]+list[2][1]+list[2][2]==3:
        V1=1
    elif list[2][0]+list[2][1]+list[2][2]==-3:
        V2=1
    if list[0][0]+list[1][0]+list[2][0]==3: #Vérification colones
        V1=1
    elif list[0][0]+list[1][0]+list[2][0]==-3:
        V2=1
    if list[0][1]+list[1][1]+list[2][1]==3:
        V1=1
    elif list[0][1]+list[1][1]+list[2][1]==-3:
        V2=1
    if list[0][0]+list[1][1]+list[2][2]==3:#Diagonales
        V1=1
    elif list[0][0]+list[1][1]+list[2][2]==-3:
        V2=1
    if list[0][2]+list[1][1]+list[2][0]==3:
        V1=1
    elif list[0][2]+list[1][1]+list[2][0]==-3:
        V2=1
    if V1==1 and V2==0:
        texte.configure(text='Joestar win !')
    elif V1==0 and V2==1:
        texte.configure(text='DArbi win')
    elif turns==9 and V1==0 and V2==0 or V1==1 and V2==1:
        texte.configure(text='No one won...')

##Function remplir##
def remplir(list,IDC):#pour remplir les cases
    global Joueur #to edit Joueur for all the program
    if IDC ==1:#Cell 1
        if list[0][0]==0:
            list[0][0]=Joueur
            if list[0][0]==1:
                dessin.create_line(10,10,90,90, width=1) #cell 1 cross
                dessin.create_line(10, 90, 90, 10, width=1)
            elif list[0][0]==-1:
                dessin.create_oval(10, 10, 90, 90, width=1)#cell 1 circle
            Joueur=(-Joueur)#nextplayer
        elif list[0][0]!=0:
            print("case déjà prise")
    if IDC ==2:#Cell 2
        if list[0][1]==0:
            list[0][1]=Joueur
            if list[0][1]==1:
                dessin.create_line(110,10,190,90, width=1)
                dessin.create_line(110,90,190,10, width=1)
            elif list[0][1]==-1:
                dessin.create_oval(110, 10, 190, 90, width=1)
            Joueur=(-Joueur)
        elif list[0][1]!=0:
            print("case déjà prise")
    if IDC ==3:#Cell 3
        if list[0][2]==0:
            list[0][2]=Joueur
            if list[0][2]==1:
                dessin.create_line(210,10,290,90, width=1)
                dessin.create_line(210,90,290,10, width=1)
            elif list[0][2]==-1:
                dessin.create_oval(210, 10, 290, 90, width=1)
            Joueur=(-Joueur)
        elif list[0][2]!=0:
            print("case déjà prise")
    if IDC ==4: #Cell 4
        if list[1][0]==0:
            list[1][0]=Joueur
            if list[1][0]==1:
                dessin.create_line(10,110,90,190, width=1)
                dessin.create_line(10, 190, 90, 110, width=1)
            elif list[1][0]==-1:
                dessin.create_oval(10, 110, 90, 190, width=1)
            Joueur=(-Joueur)
        elif list[1][0]!=0:
            print("case déjà prise")
    if IDC ==5:#Cell 5
        if list[1][1]==0:
            list[1][1]=Joueur
            if list[1][1]==1:
                dessin.create_line(110,110,190,190, width=1)
                dessin.create_line(110,190,190,110, width=1)
            elif list[1][1]==-1:
                dessin.create_oval(110, 110, 190, 190, width=1)
            Joueur=(-Joueur)
        elif list[1][1]!=0:
            print("case déjà prise")
    if IDC ==6:#Cell 6
        if list[1][2]==0:
            list[1][2]=Joueur
            if list[1][2]==1:
                dessin.create_line(210,110,290,190, width=1)
                dessin.create_line(210,190,290,110, width=1)
            elif list[1][2]==-1:
                dessin.create_oval(210, 110, 290, 190, width=1)
            Joueur=(-Joueur)
        elif list[1][2]!=0:
            print("case déjà prise")
    if IDC ==7: #Cell 7
        if list[2][0]==0:
            list[2][0]=Joueur
            if list[2][0]==1:
                dessin.create_line(10,210,90,290, width=1)
                dessin.create_line(10, 290, 90, 210, width=1)
            elif list[2][0]==-1:
                dessin.create_oval(10, 210, 90, 290, width=1)
            Joueur=(-Joueur)
        elif list[2][0]!=0:
            print("case déjà prise")
    if IDC ==8:#Cell 8
        if list[2][1]==0:
            list[2][1]=Joueur
            if list[2][1]==1:
                dessin.create_line(110,210,190,290, width=1)
                dessin.create_line(110,290,190,210, width=1)
            elif list[2][1]==-1:
                dessin.create_oval(110, 210, 190, 290, width=1)
            Joueur=(-Joueur)
        elif list[2][1]!=0:
            print("case déjà prise")
    if IDC ==9:#Cell 9
        if list[2][2]==0:
            list[2][2]=Joueur
            if list[2][2]==1:
                dessin.create_line(210,210,290,290, width=1)
                dessin.create_line(210,290,290,210, width=1)
            elif list[2][2]==-1:
                dessin.create_oval(210, 210, 290, 290, width=1)
            Joueur=(-Joueur)
        elif list[2][2]!=0:
            print("case déjà prise")

##Fuction cases##
def cases(event):
    if int(event.x)>2 and int(event.x)<100 and int(event.y)>0 and int(event.y)<100: #CASE A1
        print('A1')
        IDC=1
        remplir(list,IDC)
        win(list, V1, V2)
    elif int(event.x)>102 and int(event.x)<200 and int(event.y)>0 and int(event.y)<100: #CASE A2
        print('A2')
        IDC=2
        remplir(list,IDC)
        win(list, V1, V2)
    elif int(event.x)>202 and int(event.x)<300 and int(event.y)>0 and int(event.y)<100: #CASE A3
        print('A3')
        IDC=3
        remplir(list,IDC)
        win(list, V1, V2)
    elif int(event.x)>2 and int(event.x)<100 and int(event.y)>100 and int(event.y)<200: #CASE B1
        print('B1')
        IDC=4
        remplir(list,IDC)
        win(list, V1, V2)
    elif int(event.x)>100 and int(event.x)<200 and int(event.y)>102 and int(event.y)<200: #CASE B2
        print('B2')
        IDC=5
        remplir(list,IDC)
        win(list, V1, V2)
    elif int(event.x)>202 and int(event.x)<300 and int(event.y)>102 and int(event.y)<200: #CASE B3
        print('B3')
        IDC=6
        remplir(list,IDC)
        win(list, V1, V2)
    elif int(event.x)>2 and int(event.x)<100 and int(event.y)>202 and int(event.y)<300: #CASE C1
        print('C1')
        IDC=7
        remplir(list,IDC)
        win(list, V1, V2)
    elif int(event.x)>100 and int(event.x)<200 and int(event.y)>202 and int(event.y)<300: #CASE C2
        print('C2')
        IDC=8
        remplir(list,IDC)
        win(list, V1, V2)
    elif int(event.x)>202 and int(event.x)<300 and int(event.y)>202 and int(event.y)<300: #CASE C3
        print('C3')
        IDC=9
        remplir(list,IDC)
        win(list, V1, V2)
    else:
        print('no')

##Fuctions:others##
def restart(fen):
    global list

    fen.destroy()
    list=[[0,0,0],[0,0,0],[0,0,0]]
    main()


##Mainloop##
main()

推荐阅读