Python 是否有其他方法可以将单击的互动程序与间隙交换?

Python 是否有其他方法可以将单击的互动程序与间隙交换?,python,tkinter,Python,Tkinter,如何在间隙平铺和单击的平铺之间进行交换? 我下面的代码显示了单击的内容,但只要我想交换这两个内容,就会出现一个错误 最终目标是创建一个滑动益智游戏,但首先我只想交换两个瓷砖,然后我将设置一个条件,即只能单击间隙瓷砖周围的瓷砖 对不起,如果这是一个愚蠢的问题,我已经坐了2天与此代码,并开始看到双!xD from tkinter import* from tkinter import filedialog from PIL import Image, ImageTk import random im

如何在间隙平铺和单击的平铺之间进行交换? 我下面的代码显示了单击的内容,但只要我想交换这两个内容,就会出现一个错误

最终目标是创建一个滑动益智游戏,但首先我只想交换两个瓷砖,然后我将设置一个条件,即只能单击间隙瓷砖周围的瓷砖

对不起,如果这是一个愚蠢的问题,我已经坐了2天与此代码,并开始看到双!xD

from tkinter import*
from tkinter import filedialog
from PIL import Image, ImageTk
import random
import os

#=========================================================================================================================================================================
class Tiles(Label):
    def __init__(self,grid):
        self.tiles = []
        self.grid = grid
        self.gap = None

    def add(self,tile):
        self.tiles.append(tile)

    def getTile(self, *pos):
        for tile in self.tiles:
            if tile.pos == pos:
                return tile

    def getTileAroundGap(self):
        gRow,gCol = self.gap.pos
        return self.getTile(gRow,gCol-1),self.getTile(gRow-1,gCol),self.getTile(gRow,gCol+1),self.getTile(gRow+1,gCol)

    def changeGap(self,tile):
        gPos = self.gap.pos
        self.gap.pos = tile.pos
        tile.pos = gPos

    def slide(self, pos):
        #left,top,down,right = self.getTileAroundGap()
        self.changeGap(self.getTile(pos))

    def setGap(self, index):
        self.gap = self.tiles[index]
        self.show()

    def shuffle(self):
        random.shuffle(self.tiles)
        i=0
        for row in range(self.grid):
            for col in range(self.grid):
                self.tiles[i].pos = (row,col)
                i +=1

    def show(self):
        for tile in self.tiles:
            if self.gap != tile:
                tile.show()


#=========================================================================================================================================================================
class Tile(Label):
    def __init__(self, parent, image, pos):
        Label.__init__(self, parent, image=image)
        self.bind("<Button-1>", self.click)

        self.image = image
        self.pos = pos
        self.curPos = pos

    def click(self, event):
        print("clicked on", self.pos)
        Board.slideIt(Board,self.pos)

    def show(self):
        self.grid(row = self.pos[0], column = self.pos[1])


#=========================================================================================================================================================================
class Board(Frame):
    MAX_SIZE = 450
    def __init__(self,parent,image,grid,*args,**kwargs):
        Frame.__init__(self,parent,*args,**kwargs)

        self.parent = parent
        self.grid = grid
        self.image = self.openImage(image)
        self.tileSize = self.image.size[0]/self.grid
        self.tiles = self.createTiles()
        self.tiles.shuffle()
        self.tiles.show()

    def openImage(self,image):
        image = Image.open(image)

        if (image.size[0] > 450 or image.size[1] > 450):
            image = image.resize((self.MAX_SIZE,self.MAX_SIZE),Image.ANTIALIAS)

        if image.size[0] != image.size[1]:
            image = image.crop((0,0,image.size[0],image.size[0]))
        return image

    def slideIt(self, pos):
        self.tiles.slide(pos)


    def createTiles(self):
        tiles = Tiles(self.grid)
        for row in range(self.grid):
            for col in range(self.grid):
                x0 = col*self.tileSize
                y0 = row*self.tileSize
                x1 = x0+self.tileSize
                y1 = y0+self.tileSize
                tileImage = ImageTk.PhotoImage(self.image.crop((x0,y0,x1,y1)))
                tile = Tile(self,tileImage,(row,col))
                tiles.add(tile)
                tiles.show()
        tiles.setGap(-1)
        return tiles



# def importCSV():
#         global csvFilePath
#         csvFilePath = filedialog.askopenfilename()

#=========================================================================================================================================================================
class Main():
    def __init__(self,parent):
        self.parent = parent
        self.image = StringVar()
        self.createWidgets()

    def createWidgets(self):
        self.mainFrame = Frame(self.parent)
        Label(self.mainFrame, text = 'AI Puzzle Game', font= ("Times New Roman",40)).pack(padx = 10, pady = 10)
        frame = Frame(self.mainFrame)

        Label(frame, text = 'Image').grid(sticky = W)
        Entry(frame,textvariable = self.image).grid(row=0, column=1, padx = 30, pady = 30)
        Button(frame, text = "Browse", command = self.browse).grid(row=0, column=2, padx = 30, pady = 30)

        frame.pack(padx = 30, pady = 30)
        Button(self.mainFrame, text = "Start", command = self.start,font= ("Arial",15,"bold")).pack(padx = 30, pady = 30)
        self.mainFrame.pack()
        self.board = Frame(self.parent)
        self.winFrame = Frame(self.parent)

    def start(self):
        image = self.image.get()
        if os.path.exists(image):
            self.board = Board(self.parent,image,3)
            self.mainFrame.pack_forget()
            self.board.pack()

    def browse(self):
        self.image.set(filedialog.askopenfilename(title = "Select Image", filetype = (("JPG File","*.jpg"),("PNG File","*.png"))))

if __name__ == "__main__":
    root = Tk()
    Main(root)
    root.mainloop()

我很难理解这是如何工作的,但有一个问题;从
tile()
创建每个磁贴时,不会保存对父(板)的引用。然后在方法
中单击()
调用类
Board()
,而不是实例=self.parent

class Tile(Label):
    def __init__(self, parent, image, pos):
        Label.__init__(self, parent, image=image)
        self.bind("<Button-1>", self.click)
        self.parent = parent    # Save reference to parent
        self.image = image
        self.pos = pos
        self.curPos = pos

    def click(self, event):
        self.parent.slideIt(self.pos)   # Call method on parent

    def show(self):
        self.grid(row = self.pos[0], column = self.pos[1])

此代码不会为我生成任何错误

嘿,伙计,谢谢你的回复!它的工作原理是,当我点击“开始”时,它会创建一个电路板。然后一个图像被裁剪并分为9个平铺(在createTiles中),其中一个设置为间隙平铺。它将在板上显示瓷砖。我尝试了你的解决方案,但还是遇到了同样的错误。我得到了大致的想法,但是
Tiles()
类中有很多方法,我没有费心去理解它们。但是我对代码的修改肯定比我想象的要多,所以我在我的整个示例中都发布了。我已经将其缩短为不必每次运行时都打开文件等。现在它从电路板错误更改为:AttributeError:'NoneType'对象没有属性'pos',非常感谢!那么我的问题到底是什么呢?这都在我的答案中;调用类而不是实例,然后提供具有错误参数的方法。
class Tile(Label):
    def __init__(self, parent, image, pos):
        Label.__init__(self, parent, image=image)
        self.bind("<Button-1>", self.click)
        self.parent = parent    # Save reference to parent
        self.image = image
        self.pos = pos
        self.curPos = pos

    def click(self, event):
        self.parent.slideIt(self.pos)   # Call method on parent

    def show(self):
        self.grid(row = self.pos[0], column = self.pos[1])
from tkinter import*
from tkinter import filedialog
from PIL import Image, ImageTk
import random
import os

#=========================================================================================================================================================================
class Tiles(Label):
    def __init__(self,grid):
        self.tiles = []
        self.grid = grid
        self.gap = None

    def add(self,tile):
        self.tiles.append(tile)

    def getTile(self, pos):
        for tile in self.tiles:
            if tile.pos == pos:
                return tile

    def getTileAroundGap(self):
        gRow,gCol = self.gap.pos
        return self.getTile(gRow,gCol-1),self.getTile(gRow-1,gCol),self.getTile(gRow,gCol+1),self.getTile(gRow+1,gCol)

    def changeGap(self, tile):
        gPos = self.gap.pos
        self.gap.pos = tile.pos
        tile.pos = gPos

    def slide(self, pos):
        #left,top,down,right = self.getTileAroundGap()

        self.changeGap(self.getTile(pos))

    def setGap(self, index):
        self.gap = self.tiles[index]
        self.show()

    def shuffle(self):
        random.shuffle(self.tiles)
        i=0
        for row in range(self.grid):
            for col in range(self.grid):
                self.tiles[i].pos = (row,col)
                i +=1

    def show(self):
        for tile in self.tiles:
            if self.gap != tile:
                tile.show()


#=========================================================================================================================================================================
class Tile(Label):
    def __init__(self, parent, image, pos):
        Label.__init__(self, parent, image=image)
        self.bind("<Button-1>", self.click)
        self.parent = parent    # Save reference to parent
        self.image = image
        self.pos = pos
        self.curPos = pos

    def click(self, event):
        self.parent.slideIt(self.pos)   # Call method on parent

    def show(self):
        self.grid(row = self.pos[0], column = self.pos[1])


#=========================================================================================================================================================================
class Board(Frame):
    MAX_SIZE = 450
    def __init__(self, parent, image, grid, *args, **kwargs):
        Frame.__init__(self,parent,*args,**kwargs)

        self.parent = parent
        self.grid = grid
        self.image = self.openImage(image)
        self.tileSize = self.image.size[0]/self.grid
        self.tiles = self.createTiles()
        self.tiles.shuffle()
        self.tiles.show()

    def openImage(self,image):
        image = Image.open(image)

        if (image.size[0] > 450 or image.size[1] > 450):
            image = image.resize((self.MAX_SIZE,self.MAX_SIZE),Image.ANTIALIAS)

        if image.size[0] != image.size[1]:
            image = image.crop((0,0,image.size[0],image.size[0]))
        return image

    def slideIt(self, pos):
        self.tiles.slide(pos)

    def createTiles(self):
        tiles = Tiles(self.grid)
        for row in range(self.grid):
            for col in range(self.grid):
                x0 = col*self.tileSize
                y0 = row*self.tileSize
                x1 = x0+self.tileSize
                y1 = y0+self.tileSize
                tileImage = ImageTk.PhotoImage(self.image.crop((x0,y0,x1,y1)))
                tile = Tile(self, tileImage, (row,col))
                tiles.add(tile)
                tiles.show()
        tiles.setGap(-1)
        return tiles


if __name__ == "__main__":  # Reduced the code a bit...
    root = Tk()
    image = 'images/idle.png'
    board = Board(root, image, 3)
    board.pack()
    root.mainloop()