python - python 中的名称错误(类)

标签 python tkinter

我目前正在开发一个项目(为了好玩),其中包括创建一个完全可玩的国际象棋游戏! 我尝试在我的项目中创建一个“结构”,并将所有类分隔在不同的文件中...... 我还有一个 luncher.py 文件,您需要执行该文件来启动游戏。 但执行时出现错误:

Traceback (most recent call last):
  File "d:/Paul/Document/Python/Projet Echecs/luncher.py", line 12, in <module>
    from classes.ChessBoard import *
  File "d:\Paul\Document\Python\Projet Echecs\classes\ChessBoard.py", line 4, in <module>
    from classes.Pieces import *
  File "d:\Paul\Document\Python\Projet Echecs\classes\Pieces.py", line 15, in <module>
    class Pieces(ChessBoard):
NameError: name 'ChessBoard' is not defined

这是该项目的结构:

  • 文件夹项目:
    • 文件夹类别:
      • ChessBoard.py
      • Pieces.py
      • Rook.py
    • 文件夹 img:包含所有图像
    • luncher.py(根文件)

这是每个文件的代码:

luncher.py:

'''Ce fichier est le fichier root du projet! 
C'est lui qu'i faut executer pour le lancer!
'''

#On importe les modules necessaires
from tkinter import *
from classes.ChessBoard import *

#On creer un fenetre, puis l'échiquier (On appelle la classe ChessBoard)

fenetre = Tk()
fenetre.title("Echecs")
test = ChessBoard(fenetre, 650, 650)
fenetre.mainloop()

ChessBoard.py:

# On importe tous les modules necessaire au bon fonctionnement de la classe
from tkinter import *
from classes.Pieces import *
import os

# Creation de la classe

class ChessBoard:
    # On initialise l'objet
    def __init__(self, window, height=650, width=650, color="#546760", wdCase=76):
        '''
        Parametre obligatoire: - une fenetre TKinter
        Parametres facultatifs: -hauteur de la fenetre
                                - largeur de la fenetre
                                - couleur des cases
                                - largeur des cases
        '''

        self.height = height
        self.width = width
        self.backgroundColor = color
        self.wdCase = wdCase
        self.window = window
        self.game = self.getGame()


        self.rows = ["1", "2", "3", "4", "5", "6", "7", "8"]
        self.columns = ["A","B","C","D","E","F","G","H"]

        # On creer le plateau
        self.board = Canvas(self.window, height=self.height, width=self.width)
        self.board.pack()

        self.case = [[self.board.create_rectangle(i * self.wdCase, j * self.wdCase, (i+1) * self.wdCase, (j+1) * self.wdCase,fill = "#F3F3F3")for i in range(8)] for j in range(8)]
        self.board.create_line(2, 2, 2, self.wdCase * 8)
        self.board.create_line(2, 2, self.wdCase * 8, 2)

        # On implemente les couleurs des cases qui peuvent etre modifiées en passant color=.... en parametre

        for i in range(0,8,2):
            for j in range(1,9,2):
                self.board.itemconfigure(self.case[i][j],fill=self.backgroundColor)
                self.board.itemconfigure(self.case[j][i],fill=self.backgroundColor)

        # On implemente les labels de lignes et de colonnes : A-F et de 1-8
        # On créer une variable locale pour les coordonnées des lettres et des chiffres a place dans le Canvas
        textPositionX = self.wdCase / 2
        textPositionY = self.wdCase / 2
        a = (self.wdCase) * 8 + (self.wdCase / 4)

        for i in range(8):

            self.board.create_text(textPositionX, a, text=self.columns[i])
            self.board.create_text(a, textPositionY, text=self.rows[-i - 1])
            textPositionX += self.wdCase
            textPositionY += self.wdCase

        # On peut maintenant générer les pieces

        test = Rook(303, 532, "Noir")

    def getGame(self):
        """
            Cette méthode de la classe ChessBoard permet de récuperer une partie en cours si il en existe
            une et dans le cas contraire créer une nouvelle partie.

            Dans tous les cas, la methode renvoie un tableau décrivant la disposition des pieces sur le plateau.
        """

        # On verifie si le fichier saves.txt existe
        if os.path.exists("saves.txt"):
            # Si il existe, on l'ouvre et on recupere les donnees
            with open("save.txt") as save:
                #A FINIR
                pass
        else:
            #Sinon on creer une nouvelle partie
            piece = [["."]*8]*8
            piece[0] = ["TN", "CN", "FN", "DN", "RN", "FN", "CN", "TN"]
            piece[1] = ["PN"]*8
            piece[7] = ["TB", "CB", "FB", "DB", "RB", "FB", "CB", "TB"]
            piece[6] = ["PB"]*8

            return piece

Pieces.py

'''Ce module contient la classe Piece'''

# On importe les modules necessaires
from tkinter import *
from classes.ChessBoard import *

# On peu modifier la variable path pour charger les images
path = "D:\Paul\Document\Python\Projet Echecs\img\Pieces\\"


class Pieces(ChessBoard):

    def __init__(self, X, Y, color):
        self.color = color
        self.coordinateX = X
        self.coordinatY = Y

最后是Rook.py:

from tkinter import *
from classes.ChessBoard import *
from classes.Pieces import *


class Rook(Pieces):

    def __init__(self, X, Y, color):

        Pieces.__init__(self, X, Y, color)

        self.img = PhotoImage(file=path + "T{}.gif".format(self.color[0].upper()))
        self.board.create_image(self.coordinatX, self.coordinatY, anchor=NW, image=self.img)

最佳答案

您有一个循环导入。

ChessBoard中导入棋子:

from classes.Pieces import *

此时ChessBoard基本上是空的,因为唯一执行完毕的一行是from tkinter import *

在导入 Pieces 期间,您可以导入空的 ChessBoard 模块:

from classes.ChessBoard import *

此时没有 ChessBoard 类;您导入的只是 tkinter 名称。

您可以在回溯中看到这一点:

  File "d:/Paul/Document/Python/Projet Echecs/luncher.py", line 12, in <module>
    from classes.ChessBoard import *

ChessBoardluncher.py 导入

  File "d:\Paul\Document\Python\Projet Echecs\classes\ChessBoard.py", line 4, in <module>
    from classes.Pieces import *

第 4 行导入 Pieces,并且

  File "d:\Paul\Document\Python\Projet Echecs\classes\Pieces.py", line 15, in <module>
    class Pieces(ChessBoard):

尝试使用 ChessBoard,但该类仅在第 4 行之后几行定义。

如果您必须访问 ChessBoard 中的 Pieces 类,则必须将导入行移至 class ChessBoard 定义下方.

但是,我认为您的根本错误是让 Pieces 类继承自 ChessBoard 。棋子不是棋盘!如果您必须在 ChessBoard 类和 Pieces 类之间共享某些功能,请将其分解到一个单独的模块中,然后供两者使用。

类继承是一种共享功能以及对类进行分类的方式,这是有意义的。棋盘和棋盘上的棋子通常不共享功能;例如,棋盘不移动,也不属于一个玩家或另一个玩家。

不继承 ChessBoard 类会将其他两个模块简化为:

'''Ce module contient la classe Piece'''

# On peu modifier la variable path pour charger les images
path = "D:\\Paul\\Document\\Python\\Projet Echecs\\img\\Pieces\\"

class Pieces:
    def __init__(self, board, X, Y, color):
        self.board
        self.color = color
        self.coordinateX = X
        self.coordinatY = Y

from tkinter import *
from classes.Pieces import path, Pieces

class Rook(Pieces):
    def __init__(self, board, X, Y, color):
        Pieces.__init__(self, board, X, Y, color)

        self.img = PhotoImage(file=path + "T{}.gif".format(self.color[0].upper()))
        self.board.create_image(self.coordinatX, self.coordinatY, anchor=NW, image=self.img)

请注意,我还为 Pieces 类提供了 board 参数,正如您在 Rook.__init__() 中使用的那样。因此,当您创建 Rook 实例时,请传入 board:

test = Rook(self, 303, 532, "Noir")

关于python - python 中的名称错误(类),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58467452/

相关文章:

python - 如何使用与 get_height() 中的值不同的值注释条形图

python - 如何使 Toplevel() 小部件出现在主根窗口上方?

python - 如何防止 Tk 添加空间?

Python tkinter : Countdown Timer not accurate

python - 使用装饰器检查可选参数

python - 类型错误 : execv() arg 2 must contain only strings

python - 将 python 海龟 Canvas 转换为位图时如何保持 Canvas 大小

python - 通过另一个过程更新 tkinter gui 中的 matplotlib 图

python - 使用 python 在句子列表中形成单词的二元组并计算二元组

python - 如何使用 mpld3 和 flask 将 matplotlib 图放入 html 容器中