App / Homepage отображается как пустое окно при использовании структур классов с tkinter в Python 3.7 - PullRequest
1 голос
/ 25 апреля 2019

Я новичок в питоне / программировании (опыт 2-3 недели), и я пытаюсь создать приложение с графическим интерфейсом для tkinter для игры Battleship, которую я написал изначально как игру cmd line для моего первого проекта. Мне бы хотелось, чтобы в этом графическом интерфейсе было несколько разных экранов / фреймов, которые помогают пользователю настроить и играть в игру в режиме одиночной игры или двух игроков.

ПРОБЛЕМА: я могу процедурно сгенерировать одну домашнюю страницу в окне с фоновым изображением, которое я хочу разместить в качестве метки, однако, когда я пытаюсь внедрить этот же код в структуру класса, чтобы начать создавать несколько экранов, скрипт будет работать, но все, что я получаю, это окно, которое полностью пустое.

Большая часть кода структуры класса извлечена более или менее прямо из учебного пособия, и я также видел, как он плавал по форуму в этом контексте. Тем не менее, большинство вопросов, которые я нашел, похоже, имеют дело с ошибками, тогда как мой код работает, он просто не делает то, что я хочу. Я все еще изучаю ООП и структуры классов, поэтому я предполагаю, что упускаю что-то прямое.

Я попытался объявить ключи: значения для словаря self.frames индивидуально вместо использования цикла for.

Я отдельно пытался использовать .pack, .grid и .place для размещения контейнера и фреймов домашней страницы / двухслойного.

Я попытался сохранить изображение, которое я хочу разместить в качестве фона в переменной класса вместо переменной экземпляра. (Другой вопрос о нескольких кадрах с tkinter предположил, что в некоторых случаях это может быть проблемой)

from tkinter import *
from PIL import Image, ImageTk

class Battleship(Tk):

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

        self.geometry("1920x1080")

        container = Frame(self)
        container.pack(side="top", fill="both")
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for F in (Homepage, Twoplayer):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky = "nsew")

        self.show_frame(Homepage)

    def show_frame(self, page_name):
        """Show given frame"""
        frame=self.frames[page_name]
        frame.tkraise()


class Homepage(Frame):
    def __init__(self, parent, controller):
        Frame.__init__(self, parent)
        # Add battleship photo to background
        mainBG = ImageTk.PhotoImage(Image.open("CSEdit.jpg"))
        BGlabel = Label(parent, image=mainBG)
        BGlabel.grid()


class Twoplayer(Frame):
    # This code not relevant to problem, can't even get Homepage to work

root = Battleship()
root.mainloop()

Когда я не использую структуру классов, это работает для создания экрана, который я хочу для домашней страницы в окне:

from tkinter import *
from PIL import Image, ImageTk

root=Tk()
root.geometry("1920x1080")
container=Frame(root)
container.pack(side="top", fill= "both")

mainBG = ImageTk.PhotoImage(Image.open("CSEdit.jpg"))
BGlabel = Label(container, image=mainBG)
BGlabel.pack()

root.mainloop()

Однако попытка создать этот экран аналогично, но внутри структуры класса, приводит только к пустому белому окну.

1 Ответ

0 голосов
/ 25 апреля 2019

У вас есть одна ошибка и одна проблема с ошибкой.

  1. Вы положили Label в parent, что означает container, но вы должны поместить его в Homepage -это означает self.

    BGlabel = Label(self, image=self.mainBG)
    
  2. есть ошибка, которая удаляет PhotoImage из памяти, когда вы создаете ее в функции и присваиваете локальную переменную.Вы должны назначить глобальную переменную или переменную класса - т.е.self.main.BG

    self.mainBG = ImageTk.PhotoImage(Image.open("CSEdit.jpg"))
    BGlabel = Label(self, image=self.mainBG)
    

Рабочий код:

from tkinter import *
from PIL import Image, ImageTk

class Battleship(Tk):

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

        self.geometry("1920x1080")

        container = Frame(self)
        container.pack(side="top", fill="both")
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for F in (Homepage, Twoplayer):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky = "nsew")

        self.show_frame(Homepage)

    def show_frame(self, page_name):
        """Show given frame"""
        frame=self.frames[page_name]
        frame.tkraise()


class Homepage(Frame):
    def __init__(self, parent, controller):
        Frame.__init__(self, parent)
        # Add battleship photo to background
        self.mainBG = ImageTk.PhotoImage(Image.open("CSEdit.jpg"))
        BGlabel = Label(self, image=self.mainBG)
        BGlabel.grid()


class Twoplayer(Frame):
    # This code not relevant to problem, can't even get Homepage to work
    def __init__(self, parent, controller):
        Frame.__init__(self, parent)
        pass

root = Battleship()
root.mainloop()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...