使用 tk 框架合并两个应用程序

Merging two applications using tk frames

我有一个用 python 和 tkinter 制作的记忆游戏。我还制作了一个带有简单 GUI 的应用程序,该 GUI 使用 tk.Frame 来显示不同的帧。我的问题是将记忆游戏放在 GUI 应用程序的框架之一中。

我有一个用于记忆游戏的 .py 文件和一个用于 GUI 的 .py 文件。 GUI 有多个 classes 和框架。我想将记忆游戏放在其中一个框架内,以便您可以通过菜单导航进入游戏。游戏应该只在导航到时显示。

我试过:

导入文件使两个应用程序在启动时尝试 运行 不同的 windows。将游戏代码复制到 GUI class 出现了很多错误。

我有 python 3.7 和 tkinter 8.6

记忆游戏首先创建一个 canvas,它利用了:

win = tk.Tk()
canvas = tk.Canvas(win, width = 600, height = 480)
canvas.pack()
class Tile(object):
    def __init__(self, x, y, text):
        self.y = y
        self.x = x
        self.text = text
    def drawFaceDown(self):
        canvas.create_rectangle(self.x, self.y, self.x + 100, self.y + 100, fill = "green")
...

这就是我如何使用 class 创建一个显示不同内容的框架:

class PageMG(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        # memory game goes here

如果有人想看,我可以展示整个文件

我希望游戏只显示,直到我单击将我带到我想要游戏的帧的按钮。

编辑:整个记忆游戏文件

import tkinter as tk
import time
from random import randint
from random import shuffle
win = tk.Tk()
canvas = tk.Canvas(win, width = 500, height = 500)
canvas.pack()
class Tile(object):
    def __init__(self, x, y, text):
        self.y = y
        self.x = x
        self.text = text
    def drawFaceDown(self):
        canvas.create_rectangle(self.x, self.y, self.x + 70, self.y + 70, fill = "blue")
        self.isFaceUp = False
    def drawFaceUp(self):
        canvas.create_rectangle(self.x, self.y, self.x + 70, self.y + 70, fill = "blue")
        canvas.create_text(self.x + 35, self.y + 35, text = self.text, width = 70, fill = "white", font='Helvetica 12 bold')
        self.isFaceUp = True
    def isUnderMouse(self, event):
        if(event.x > self.x and event.x < self.x + 70):
            if(event.y > self.y and event.y < self.y + 70):
                return True

tiles = []
colors = [
    "Eple",
    "Appelsin",
    "Banan",
    "Agurk",
    "Brokkoli",
    "Tomat",
    "Sitron",
    "Melon",
    "Hvitløk",
    "Erter",
    "Jordbær",
    "Blåbær"
]

selected = []
for i in range(10):
    randomInd = randint(0, len(colors) - 1)
    color = colors[randomInd]
    selected.append(color)
    selected.append(color)
    del colors[randomInd]
shuffle(selected)

flippedTiles = []

def mouseClicked(self):
    global numFlipped
    global flippedTiles
    for i in range(len(tiles)):
        if tiles[i].isUnderMouse(self):
            if (len(flippedTiles) < 2 and not(tiles[i].isFaceUp)) :
                tiles[i].drawFaceUp()
                flippedTiles.append(tiles[i])
            if (len(flippedTiles) == 2):
                if not(flippedTiles[0].text == flippedTiles[1].text):
                    time.sleep(1)
                    flippedTiles[0].drawFaceDown()
                    flippedTiles[1].drawFaceDown()

NUM_COLS = 5
NUM_ROWS = 4

for x in range(0,NUM_COLS):
    for y in range(0,NUM_ROWS):
            tiles.append(Tile(x * 78 + 10, y * 78 + 40, selected.pop()))

for i in range(len(tiles)):
    tiles[i].drawFaceDown()

flippedThisTurn = 0
def mouseClicked(event):
    global flippedTiles
    global flippedThisTurn
    for tile in tiles:
        if tile.isUnderMouse(event):
            if (not(tile.isFaceUp)) :
                tile.drawFaceUp()
                flippedTiles.append(tile)
                flippedThisTurn += 1

            if (flippedThisTurn == 2):
                win.after(1000, checkTiles)
                flippedThisTurn = 0

def checkTiles():
    if not(flippedTiles[-1].text == flippedTiles[-2].text): #check last two elements
        flippedTiles[-1].drawFaceDown() #facedown last two elements
        flippedTiles[-2].drawFaceDown()
        del flippedTiles[-2:] #remove last two elements

win.bind("<Button-1>", mouseClicked)


win.mainloop()
  1. importing the memorygame file at the top of the GUI file
  2. importing the memorygame file inside a class of the GUI file

这两种方式都会 "both the applications try to run on startup in different windows" 这是因为 memorygame 文件会生成一个新的 tk.Tk() window,您的 GUI 处理程序也是如此。

copying the whole memorygame code into a class of the GUI file

这可能会导致很多问题,具体取决于您将文件复制到的位置,因为这些文件有自己的导入依赖项,并且导入路径可能会根据您将文件复制到的位置而改变。

我建议您执行以下操作,我会更改您的记忆游戏代码,使记忆游戏成为 class(tk.Frame)(帧 class),然后您应该可以导入记忆游戏并将该框架粘贴到 GUI PageMk(tk.Frame),我不知道您的代码具有依赖性,但这应该可以。

Example of change using the provided code

class MemGame(tk.Frame):
    def __init__(self, parent):
        super(MemGame, self).__init__(parent)
        self.configure(width=600, height=480)
        canvas = tk.Canvas(self, width=600, height=480, bg="red")
        canvas.pack()

class Tile:
    def __init__(self, parent, x, y, text):
        self.parent = parent
        self.y = y
        self.x = x
        self.text = text
    def drawFaceDown(self):
        self.parent.create_rectangle(self.x, self.y, self.x + 100, self.y + 100, fill="green")

class PageMG(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        x = MemGame(self)
        x.pack()

My Edits to the full code:

import tkinter as tk
import time
from random import randint
from random import shuffle


class Controller(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        # the container is where we'll stack a bunch of frames
        # on top of each other, then the one we want visible
        # will be raised above the others
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        if True:
            self.frames = {}
            for F in (PageMG,):
                page_name = F.__name__
                frame = F(parent=container, controller=self)
                self.frames[page_name] = frame

                # put all of the pages in the same location;
                # the one on the top of the stacking order
                # will be the one that is visible.
                frame.grid(row=0, column=0, sticky="nsew")

            self.show_frame("PageMG")
        self.geometry("500x400")

    def show_frame(self, page_name):
        '''Show a frame for the given page name'''
        frame = self.frames[page_name]
        frame.tkraise()


class PageMG(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        x = MemGame(self)
        x.pack()


class Tile(object):
    def __init__(self, canvas, x, y, text):
        self.canvas = canvas
        self.y = y
        self.x = x
        self.text = text

    def drawFaceDown(self):
        self.canvas.create_rectangle(self.x, self.y, self.x + 70, self.y + 70, fill = "blue")
        self.isFaceUp = False

    def drawFaceUp(self):
        self.canvas.create_rectangle(self.x, self.y, self.x + 70, self.y + 70, fill = "blue")
        self.canvas.create_text(self.x + 35, self.y + 35, text = self.text, width = 70, fill = "white", font='Helvetica 12 bold')
        self.isFaceUp = True

    def isUnderMouse(self, event):
        if(event.x > self.x and event.x < self.x + 70):
            if(event.y > self.y and event.y < self.y + 70):
                return True


class MemGame(tk.Frame):
    def __init__(self, master):
        super(MemGame, self).__init__(master)
        self.configure(width=500, height=500)
        self.canvas = tk.Canvas(self, width=500, height=500)
        self.canvas.pack()
        self.tiles = []
        self.colors = [
            "Eple",
            "Appelsin",
            "Banan",
            "Agurk",
            "Brokkoli",
            "Tomat",
            "Sitron",
            "Melon",
            "Hvitløk",
            "Erter",
            "Jordbær",
            "Blåbær"
        ]

        selected = []
        for i in range(10):
            randomInd = randint(0, len(self.colors) - 1)
            color = self.colors[randomInd]
            selected.append(color)
            selected.append(color)
            del self.colors[randomInd]
        shuffle(selected)
        self.flippedTiles = []
        NUM_COLS = 5
        NUM_ROWS = 4

        for x in range(0, NUM_COLS):
            for y in range(0, NUM_ROWS):
                self.tiles.append(Tile(self.canvas, x * 78 + 10, y * 78 + 40, selected.pop()))

        for i in range(len(self.tiles)):
            self.tiles[i].drawFaceDown()
        self.flippedThisTurn = 0
        self.bind("<Button-1>", self.mouseClicked)

    # def mouseClicked(self):
    #     for i in range(len(self.tiles)):
    #         if self.tiles[i].isUnderMouse(self):
    #             if (len(self.flippedTiles) < 2 and not(self.tiles[i].isFaceUp)) :
    #                 self.tiles[i].drawFaceUp()
    #                 self.flippedTiles.append(self.tiles[i])
    #             if (len(self.flippedTiles) == 2):
    #                 if not(self.flippedTiles[0].text == self.flippedTiles[1].text):
    #                     time.sleep(1)
    #                     self.flippedTiles[0].drawFaceDown()
    #                     self.flippedTiles[1].drawFaceDown()

    def mouseClicked(self, event):
        for tile in self.tiles:
            if tile.isUnderMouse(event):
                if (not(tile.isFaceUp)) :
                    tile.drawFaceUp()
                    self.flippedTiles.append(tile)
                    self.flippedThisTurn += 1

                if (self.flippedThisTurn == 2):
                    self.after(1000, self.checkTiles)
                    self.flippedThisTurn = 0

    def checkTiles(self):
        if not(self.flippedTiles[-1].text == self.flippedTiles[-2].text): #check last two elements
            self.flippedTiles[-1].drawFaceDown()
            self.flippedTiles[-2].drawFaceDown()
            del self.flippedTiles[-2:]


if __name__ == '__main__':
    c = Controller()
    c.mainloop()

祝你好运:)