Не могу добраться до вещей в ткинтер, сделанных в классе - PullRequest
0 голосов
/ 25 августа 2018

Я новичок в Python и сейчас пытаюсь использовать tkinter в качестве первого GUI.Я привык делать это без занятий.И я впервые использую import tkinter as tk вместо import *

import tkinter as tk

def update():
    pass

#Game.statsFrame #doesn't work Game.statsFrame.stat1_amountLabel too
#Game.stat1_amountLabel #doesnt work < want to use update_idletasks() or 
#just type new cofnig...
#just errors like: "Game' has no attribute 'statsFrame" etc   #Game


class character:
    name = ""
    experience = 0
    level = 0
    gold = 0
    stat1 = 0
    stat2 = 0
    stat3 = 0
    stat4 = 0
    stat5 = 0
    avaiblePoints = 0
    def add_stat1(self):
        if self.avaiblePoints >= 1:
            self.stat1 += 1
            self.avaiblePoints -= 1
            update()
        else:
            pass
    def add_stat2(self):
        if self.avaiblePoints >= 1:
            self.stat2 += 1
            self.avaiblePoints -= 1
            update()
 [...]

myChar = character()
myChar.avaiblePoints = 3

class Game:
    def __init__(self, parent):
    self.myParent = parent
    self.myGame = tk.Frame(parent)
    self.myGame.grid()

    self.statsFrame = tk.Frame(self.myGame).grid()

    self.stat1Label = tk.Label(self.statsFrame)
    self.stat1Label.config(text="Strength:")
    self.stat1Label.grid(column=1, row=1)

    self.stat1_amountLabel = tk.Label(self.statsFrame)
    self.stat1_amountLabel.config(text=myChar.stat1)
    self.stat1_amountLabel.grid(column=2, row=1)

    self.add_stat1Button = tk.Button(self.statsFrame)
    self.add_stat1Button.config(text="+", command=myChar.add_stat1)
    self.add_stat1Button.grid(column=3, row=1)

root = tk.Tk()
myapp = Game(root)
root.mainloop()

Но я не могу получить (например) stat1Label и изменить текст внутри и после него использовать update_idletasks().Как будто его не существует.Ошибки показывают, что Game не имеет атрибутов, таких как stat1Label и т. Д.

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

1 Ответ

0 голосов
/ 25 августа 2018

Прекрасно, что вы используете import tkinter as tk вместо страшного «звездного» импорта и пытаетесь организовать свой код с помощью классов. Поначалу это может немного сбивать с толку, но делает ваш код более модульным, что очень помогает, особенно когда графический интерфейс становится большим.

Есть несколько проблем с вашим кодом. Наиболее важной является эта строка:

self.statsFrame = tk.Frame(self.myGame).grid()

Метод .grid.pack и .place) все возвращают None. Таким образом, эта строка сохраняет None в self.statsFrame, а не виджет Frame. Поэтому, когда вы позже попытаетесь сделать что-то с self.statsFrame, это не будет делать то, что вы ожидаете.

Другая проблема заключается в том, что атрибут text вашего self.stat1_amountLabel не отслеживает значение myChar.stat1, поэтому при изменении значения myChar.stat1 вам необходимо явно обновить метку с новым значением. В качестве альтернативы, вы могли бы использовать атрибут textvariable с IntVar для хранения статистики персонажа. См. Запись для textvariable в документации Label config для получения информации.

Ваш character класс имеет целую кучу атрибутов, таких как name, experience и т. Д. В качестве атрибутов класса. Это не очень хорошая идея, потому что атрибуты класса являются общими для всех экземпляров класса. Но вы, вероятно, хотите, чтобы каждый экземпляр персонажа имел свои собственные атрибуты экземпляра. Таким образом, вы должны дать character __init__ метод, в котором вы устанавливаете эти атрибуты. OTOH, можно использовать атрибуты класса для значений по умолчанию, которые переопределяются атрибутами экземпляра.

В любом случае, вот исправленная версия вашего кода с кнопкой, которая обновляет статистику силы. Я поместил статистику в список, вместо того, чтобы иметь кучу отдельных именованных статистик, которыми нужно будет управлять отдельно. И я дал Game метод make_stat, чтобы вы могли легко добавлять строки для других характеристик.

import tkinter as tk

class Character:
    def __init__(self, availablePoints=0):
        self.name = ""
        self.experience = 0
        self.level = 0
        self.gold = 0
        self.stats = [0] * 5
        self.availablePoints = availablePoints

    def add_stat(self, idx):
        if self.availablePoints >= 1:
            self.stats[idx] += 1
            self.availablePoints -= 1

class Game:
    def __init__(self, parent):
        self.myParent = parent
        self.myGame = tk.Frame(parent)
        self.myGame.grid()

        self.statsFrame = tk.Frame(self.myGame)
        self.statsFrame.grid()

        self.make_stat("Strength:", 0, 0)

    def make_stat(self, text, idx, row):
        label = tk.Label(self.statsFrame, text=text)
        label.grid(column=1, row=row)

        amount = tk.Label(self.statsFrame, text=myChar.stats[idx])
        amount.grid(column=2, row=row)

        def update():
            myChar.add_stat(idx)
            amount["text"] = myChar.stats[idx]

        button = tk.Button(self.statsFrame, text="+", command=update)
        button.grid(column=3, row=row)

myChar = Character(3)

root = tk.Tk()
myapp = Game(root)
root.mainloop()

Этот код все еще не идеален, но это улучшение. ;) Например, было бы хорошо дать Game метод для создания новых персонажей, а не создавать их в глобальном контексте. Вы можете сохранить их в атрибуте dict, равном Game, используя имя персонажа в качестве ключа.


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

import tkinter as tk

class Character:
    def __init__(self, availablePoints):
        self.name = ""
        self.experience = 0
        self.level = 0
        self.gold = 0
        self.stat1 = 0
        self.stat2 = 0
        self.stat3 = 0
        self.stat4 = 0
        self.stat5 = 0
        self.availablePoints = availablePoints

class Game:
    def __init__(self, parent):
        self.myParent = parent
        self.myGame = tk.Frame(parent)
        self.myGame.grid()

        self.statsFrame = tk.Frame(self.myGame)
        self.statsFrame.grid()

        self.make_stat("Strength:", "stat1", 1, 1)

    def make_stat(self, text, stat, column, row):
        label = tk.Label(self.statsFrame, text=text)
        label.grid(column=column, row=row)

        amount = tk.Label(self.statsFrame, text=getattr(myChar, stat))
        amount.grid(column=(column+1), row=row)

        def update():
            if myChar.availablePoints >= 1:
                v = getattr(myChar, stat) + 1
                setattr(myChar, stat, v)
                myChar.availablePoints -= 1
                amount["text"] = v

        button = tk.Button(self.statsFrame, text="+", command=update)
        button.grid(column=(column+2), row=row)

myChar = Character(5)

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