【问题标题】:I want the "Edit" button to open a new window and then be able to edit the values on the display我希望“编辑”按钮打开一个新窗口,然后能够编辑显示屏上的值
【发布时间】:2021-07-08 02:35:48
【问题描述】:

我希望“编辑”按钮打开一个新窗口,然后能够编辑显示屏上的值。例如,我希望它打开一个带有“Daniel Keelagher”的窗口,然后能够从所玩的游戏、进球、助攻等中 +1 或 -1。请详细说明你的答案,因为我是个笨蛋和初学者。

#Edit Function

root = Tk()
#Labels
lblTitle = Label(text="Chelsea FC Player Statistics",font=('bold', 15), fg="blue",).grid(row=0, column=1)
#Player Names Labels
lblPlayerNames = Label(text="Player Names",font=('bold')).grid(columnspan=1,row=1, column=1)
lblDKName = Label(text="Daniel Keelagher").grid(columnspan=1,row=2, column=1)
lblJKName = Label(text="Joseph Keelagher").grid(columnspan=1,row=3, column=1)
lblBMName = Label(text="Benjamin Miller").grid(columnspan=1,row=4, column=1)
lblJTName = Label(text="Jordan Terlato").grid(columnspan=1,row=5, column=1)
#Matches Played Labels
lblMatchesPlayed = Label(text="Matches Played",font=('bold')).grid(columnspan=1,row=1, column=2)
lblDKMatches = Label(text="10").grid(columnspan=1,row=2, column=2)
lblJKMatches = Label(text="9").grid(columnspan=1,row=3, column=2)
lblBMMatches = Label(text="9").grid(columnspan=1,row=4, column=2)
lblJTMatches = Label(text="8").grid(columnspan=1,row=5, column=2)
#Goals Labels
lblGoals = Label(text="Goals",font=('bold')).grid(row=1, column=3)
lblDKGoals = Label(text="4").grid(columnspan=1,row=2, column=3)
lblJKGoals = Label(text="2").grid(columnspan=1,row=3, column=3)
lblBMGoals = Label(text="0").grid(columnspan=1,row=4, column=3)
lblJTGoals = Label(text="1").grid(columnspan=1,row=5, column=3)
#Assists Labels
lblAssists = Label(text="Assists",font=('bold')).grid(columnspan=1,row=1, column=4)
lblDKAssists = Label(text="4").grid(columnspan=1,row=2, column=4)
lblJKAssists = Label(text="2").grid(columnspan=1,row=3, column=4)
lblBMAssists = Label(text="0").grid(columnspan=1,row=4, column=4)
lblJTAssists = Label(text="1").grid(columnspan=1,row=5, column=4)
#YellowCards Labels
lblYellowCards = Label(text="YC",font=('bold')).grid(columnspan=1,row=1, column=5)
lblDKYellowCards = Label(text="0").grid(columnspan=1,row=2, column=5)
lblJKYellowCards = Label(text="1").grid(columnspan=1,row=3, column=5)
lblBMYellowCards = Label(text="1").grid(columnspan=1,row=4, column=5)
lblJTYellowCards = Label(text="3").grid(columnspan=1,row=5, column=5)
#RedCards Labels
lblYellowCards = Label(text="RC",font=('bold')).grid(columnspan=1,row=1, column=6)
lblDKRedCards = Label(text="0").grid(columnspan=1,row=2, column=6)
lblJKRedCards = Label(text="0").grid(columnspan=1,row=3, column=6)
lblBMRedCards = Label(text="0").grid(columnspan=1,row=4, column=6)
lblJTRedCards = Label(text="1").grid(columnspan=1,row=5, column=6)


#Buttons
btnDKEdit = Button(root, text="Edit",).grid(columnspan=1,row=2, column=7)
btnJKEdit = Button(root, text="Edit", ).grid(columnspan=1,row=3, column=7)
btnBMEdit = Button(root, text="Edit", ).grid(columnspan=1,row=4,column=7)
btbJTEdit = Button(root, text="Edit",).grid(columnspan=1,row=5, column=7)```

【问题讨论】:

  • SO 不是询问示例代码的地方。建议阅读一些关于tkinter 的教程,尤其是关于使用Toplevel 和使用Entry 小部件创建窗口的教程。然后针对您在尝试实现目标时遇到的问题提出问题。
  • @acw1668 是的,但我不知道该怎么做 :( 我假设它是一个功能,但 idk
  • 它不仅仅是一个简单的功能。首先,您需要定义StringVar() 对象以将您的标签链接到。可以更改这些对象以更改屏幕上的值。然后,您需要以可从函数访问的方式存储它们(例如,将它们放在全局列表中或将整个小部件合并到具有共享属性的类中)。然后,您需要该功能打开一个带有链接到实际功能的商店按钮的新窗口。此函数必须从 Entry 小部件中读取所有值并为每个新字段设置 StringVar()。您需要教程,而不是代码 sn-ps。

标签: python function tkinter button


【解决方案1】:

这是我的解决方案(很长,但我会尽我所能解释大部分部分(解释如下)但是在这种情况下不会有一个新窗口,而且这更多是一个例子怎么做只是为了给你一个想法。):

from tkinter import Tk, Button, Frame, Label, StringVar
from tkinter.ttk import Separator
from functools import partial


stored_data = {'Lionel Notmessi': {'Games Played': 340, 'Goals': 102, 'Assists': 223}, 'Firstname Lastname': {'Games Played': 279, 'Goals': 84, 'Assists': 56}}


class MainWindow(Tk):
    def __init__(self):
        Tk.__init__(self)
        self.resizable(False, False)

        self.players_frame = Frame(self)
        self.players_frame.pack(fill='both', expand=True)

        self.data_value_list = []

        for index, player in enumerate(list(stored_data)):
            player_frame = Frame(self.players_frame)
            player_frame.pack(side='left')
            Label(player_frame, text=player, height=2, width=30, anchor='n', font='default 11 bold').pack(side='top', pady=10)

            var = StringVar()
            self.data_value_list.append(var)

            Label(player_frame, textvariable=self.data_value_list[index], height=8, width=30).pack(side='top', pady=10)

            Button(player_frame, text='Edit', command=partial(self.select, player)).pack(side='bottom', pady=10, fill='x', expand=True)

        self.refresh_data()

    def select(self, key):
        self.players_frame.pack_forget()
        player_edit_frame = EditData(self, stored_data, key)
        player_edit_frame.pack(fill='both', expand=True)

    def refresh_data(self):
        for var, player in zip(self.data_value_list, list(stored_data)):
            data = ''
            for name, value in stored_data[player].items():
                data += f'{name}: {value}\n\n'
            var.set(data)


class EditData(Frame):
    def __init__(self, parent, data, key):
        Frame.__init__(self, parent)
        self.parent = parent
        self.data = data
        self.key = key

        self.total_width = len(list(data[key].keys()))

        name = Label(self, text=key, anchor='n', height=3)
        name.grid(row=0, column=0, columnspan=self.total_width, sticky='nsew', pady=10)

        self.value_list = []
        index = 0
        for key, value in data[self.key].items():
            item_frame = Frame(self)
            item_frame.grid(row=1, column=index, sticky='nsew', padx=5)
            for i in range(3):
                item_frame.columnconfigure(i, minsize=50)

            var = StringVar()
            var.set(value)
            self.value_list.append(var)

            Label(item_frame, text=key).grid(row=0, column=0, columnspan=3, sticky='nsew')

            minus = Button(item_frame, text='-', command=partial(self.change, self.value_list[index], '-', key))
            minus.grid(row=1, column=0, sticky='nsew')

            value_label = Label(item_frame, textvariable=self.value_list[index])
            value_label.grid(row=1, column=1, sticky='nsew')

            plus = Button(item_frame, text='+', command=partial(self.change, self.value_list[index], '+', key))
            plus.grid(row=1, column=2, sticky='nsew')

            index += 1

        Separator(self, orient='horizontal').grid(row=2, column=0, columnspan=self.total_width, sticky='nsew', pady=5)

        Button(self, text='Done', command=self.done).grid(row=3, column=0, columnspan=self.total_width, sticky='nsew')

    def change(self, var, operator, key):
        current = var.get()
        if operator == '-':
            total = int(current) - 1
            var.set(str(total))
            self.data[self.key][key] = total
        if operator == '+':
            total = int(current) + 1
            var.set(str(total))
            self.data[self.key][key] = total

    def done(self):
        self.parent.refresh_data()
        self.parent.players_frame.pack(expand=True, fill='both')
        self.destroy()


root = MainWindow()
root.mainloop()

所以首先要导入所有需要用到的模块。

接下来,我将变量stored_data 设置为一个字典,该字典将是存储所有玩家数据的主要数据存储位置。

然后我创建了一个名为 MainWindow 的类,它继承自 tkinter 的主窗口 Tk,这样就可以获得 Tk() 功能,例如 .mainloop() 方法。

MainWindow 构造函数方法(初始化时会调用它)中,我首先将窗口设置为在 x 和 y 方向上都不可调整大小,以免导致小部件不可见的问题。

然后我创建了一个框架来组织所有播放器内容的显示位置,还创建了另一个列表来存储 StringVar 值,以便轻松更新当前数据标签(启动程序时看到的标签)。

然后,我为字典中的每个键创建了一个框架来再次组织显示的小部件。然后在框架中我打包了所有相关的东西,我输入了玩家姓名、他们的统计数据和编辑按钮(因为我只关注那个功能)。还为每个玩家附加了一个 StringVar 列表。那些 StringVar 设置将显示统计信息的标签的值。并且 StringVar 是通过索引访问的。

然后我调用了self.refresh_data(),它基本上将列表中每个 StringVar 的值设置为相应的字典值。基本上显示统计数据。

然后还定义了select() 方法(由按钮调用),该方法启动EditData,然后在从几何管理器中删除self.players_frame 后将其放在屏幕上,使其不再可见并且只有编辑框可见。

EditData 类。启动后,它接受给它的参数并将它们设置为类属性,以便在整个类中更轻松地访问。

然后测量总宽度以计算网格的列跨度,它是通过测量由stored_data 键创建的列表的长度来完成的,所以长度基本上就是玩家的数量。

然后名字就会出现在屏幕上。

再次创建另一个self.value_list 用于存储StringVar,并将索引设置为0(因为我不知道如何在for 循环中实现它(很简单)(使用enumerate()))。并且每次迭代都会增加索引。

然后创建标签和按钮并将其网格化到item_frame,它位于继承自 Frame 的类内部,因此基本上该类是一个更大的 Frame,并且在其中程序创建更小的框架用于数据更改和布局组织目的。然后在item_frame 内部,每一列都设置为 minsize=50 以便它们的大小相同,因为无论如何都没有数据占用那么多空间。

然后再次设置一个 StringVar 并将其附加到列表中以便稍后访问它。

整体

  name 
- data + 

创建布局并将按钮设置为方法change() 并给定参数(partial() 将这些函数设置为始终使用相同的给定变量执行,以便可以轻松地在循环中创建按钮)。调用更改时,它会获取该数据部分的当前值,然后根据它是“-”还是“+”,它会从当前值中添加或减去,并将其设置为新值,并更改字典,以便下次显示此帧时,它会显示新数据,并且“首页”上的统计信息会显示更新后的数据。

还有一个“完成”按钮,按下该按钮时会调用done() 方法,然后调用父(即MainWindow)方法refresh_data() 来显示新数据,然后将已删除的帧打包回之前调用这个类然后销毁自己。

然后我们就发起MainWindow:

root = MainWindow()
root.mainloop()

就是这样。

显然可以进行一些设计改进。
此外,如果您想保存数据,以便每次启动时都会显示更改的数据,您可以在关闭窗口之前将数据写入文件。

如果您有任何问题,请直接问他们。

关于该文件的保存:

您可以添加这个(MainWindow 类):

self.protocol('WM_DELETE_WINDOW', lambda: self.save(stored_data))

__init__方法执行关闭窗口时给出的函数

还要加上这个:

with open('stored_data.json') as file:
    stored_data = json.load(file)

在您文件的开头,但请确保您的目录中也有该文件您必须:

import json

然后定义关闭窗口时调用的save()方法(在MainWindow类中):

def save(self, data):
        with open('stored_data.json', 'w') as file_:
            json.dump(data, file_, indent=2)
        self.destroy()

以便它将更新的数据写入该文件并记住之后销毁窗口,否则它不会关闭。

现在您可以在运行程序时加载数据,如果您进行更改,它们将保存到文件中,以便下次运行程序时访问它们。

如果你有问题再问他们。

添加了 Toplevel(确实是最小的更改,但添加了一些内容,例如 bind 以确保如果用户将焦点移出编辑窗口,它会被关闭,从而不会打开多个相同的窗口(因此还定义了另一种方法),所有更改如下):

from tkinter import Tk, Button, Frame, Label, StringVar, Toplevel, Entry
from tkinter.ttk import Separator
from functools import partial


stored_data = {'Lionel Notmessi': {'Games Played': 340, 'Goals': 102, 'Assists': 223}, 'Firstname Lastname': {'Games Played': 279, 'Goals': 84, 'Assists': 56}}


class MainWindow(Tk):
    def __init__(self):
        Tk.__init__(self)
        self.resizable(False, False)

        self.players_frame = Frame(self)
        self.players_frame.pack(fill='both', expand=True)

        self.data_value_list = []

        for index, player in enumerate(list(stored_data)):
            player_frame = Frame(self.players_frame)
            player_frame.pack(side='left')
            Label(player_frame, text=player, height=2, width=30, anchor='n', font='default 11 bold').pack(side='top', pady=10)

            var = StringVar()
            self.data_value_list.append(var)

            Label(player_frame, textvariable=self.data_value_list[index], height=8, width=30).pack(side='top', pady=10)

            Button(player_frame, text='Edit', command=partial(self.select, player)).pack(side='bottom', pady=10, fill='x', expand=True)

        self.refresh_data()

    def select(self, key):
        player_edit_frame = EditData(self, stored_data, key)
        player_edit_frame.focus_force()

    def refresh_data(self):
        for var, player in zip(self.data_value_list, list(stored_data)):
            data = ''
            for name, value in stored_data[player].items():
                data += f'{name}: {value}\n\n'
            var.set(data)


class EditData(Toplevel):
    def __init__(self, parent, data, key):
        Toplevel.__init__(self, parent)
        self.parent = parent
        self.data = data
        self.key = key

        self.bind('<FocusOut>', self.focus_out)

        self.total_width = len(list(data[key].keys()))

        name = Label(self, text=key, anchor='n', height=3)
        name.grid(row=0, column=0, columnspan=self.total_width, sticky='nsew', pady=10)

        self.value_list = []
        index = 0
        for key, value in data[self.key].items():
            item_frame = Frame(self)
            item_frame.grid(row=1, column=index, sticky='nsew', padx=5)
            for i in range(3):
                item_frame.columnconfigure(i, minsize=50)

            var = StringVar()
            var.set(value)
            self.value_list.append(var)

            Label(item_frame, text=key).grid(row=0, column=0, columnspan=3, sticky='nsew')

            minus = Button(item_frame, text='-', command=partial(self.change, self.value_list[index], '-', key))
            minus.grid(row=1, column=0, sticky='nsew')

            value_label = Label(item_frame, textvariable=self.value_list[index])
            value_label.grid(row=1, column=1, sticky='nsew')

            plus = Button(item_frame, text='+', command=partial(self.change, self.value_list[index], '+', key))
            plus.grid(row=1, column=2, sticky='nsew')

            index += 1

        Separator(self, orient='horizontal').grid(row=2, column=0, columnspan=self.total_width, sticky='nsew', pady=5)

        Button(self, text='Done', command=self.done).grid(row=3, column=0, columnspan=self.total_width, sticky='nsew')

    def change(self, var, operator, key):
        current = var.get()
        if operator == '-':
            total = int(current) - 1
            var.set(str(total))
            self.data[self.key][key] = total
        if operator == '+':
            total = int(current) + 1
            var.set(str(total))
            self.data[self.key][key] = total

    def done(self):
        self.parent.refresh_data()
        self.destroy()

    def focus_out(self, event):
        self.parent.refresh_data()
        if event.widget == self:
            self.destroy()


root = MainWindow()
root.mainloop()

更改MainWindow

更改了select() 方法以显示顶层

def select(self, key):
        player_edit_frame = EditData(self, stored_data, key)
        player_edit_frame.focus_force()

EditFrame 的变化:

从顶层继承

class EditData(Toplevel):
    def __init__(self, parent, data, key):
        Toplevel.__init__(self, parent)

添加绑定

self.bind('<FocusOut>', self.focus_out)

bind 附带的方法(它检查焦点是否在整个窗口之外,否则即使焦点在入口小部件之外也会导致它关闭)

def focus_out(self, event):
        self.parent.refresh_data()
        if event.widget == self:
            self.destroy()

【讨论】:

  • 用保存文件的选项更新了我的答案
  • 非常感谢您的详细回答,我将如何用我的代码实现这一点,这样当我按下“编辑”时,它会打开一个包含确切玩家姓名和统计数据的新窗口。说真的,我不能感谢你的帮助。如果您可以用我的代码实现这一点,这将是最重要的。
  • @Volted 我添加了代码(在底部)以包含 Toplevel。现在几乎不可能在您的代码中实现我的方法,因为我的方法使用完全不同的方式来存储数据、创建标签等,因为您的方法是非常硬编码的,而我使用字典来存储数据并创建基于需要(使用 for 循环),因此很难实现。此外,我的回答几乎是一个完整的东西,只是作为一个例子,但我解释这么多的原因是为了让你可以从中学到一些东西并尝试自己实现它。
  • 另外,如果您想自己执行此操作,则无需使用类,我认为也可以使用函数来完成(从我的角度来看可能不那么容易(也不那么紧凑) ) 但如果您对类一无所知(我建议您将其用于 GUI),我建议您使用 this tutorial(更像系列,但它应该有所帮助)。显然问你是否对某事有疑问。
  • 所以如果几乎不可能在我的代码中实现它,我可以以某种方式重新编码它,以便我仍然拥有相同的外观/概念吗?您是否可以从您制作的代码中添加链接到“编辑”按钮的开始部分? tysm
【解决方案2】:

这是另一种方法(函数式编程方式):

from tkinter import Tk, Frame, Button, Label, StringVar, Toplevel
from functools import partial


stored_data = {'Lionel Notmessi': {'Games Played': 340, 'Goals': 102, 'Assists': 223}, 'Firstname Lastname': {'Games Played': 279, 'Goals': 84, 'Assists': 56}}


def open_edit_window(player):
    tp = Toplevel(root)
    tp.focus_force()

    def del_n_refresh(event=None):
        tp.destroy()
        pack_all_players()

    tp.bind('<FocusOut>', del_n_refresh)
    tp.protocol('WM_DELETE_WINDOW', del_n_refresh)

    total_length = len(stored_data[player])

    def change(variable, stat_name, sign):
        current = int(variable.get())
        if sign == '-':
            stored_data[player][stat_name] = current - 1
            variable.set(current - 1)
        elif sign == '+':
            stored_data[player][stat_name] = current + 1
            variable.set(current + 1)

    stats_edit_frame = Frame(tp)
    stats_edit_frame.pack()

    Label(stats_edit_frame, text=player).grid(row=0, column=0, columnspan=total_length)

    value_list = []
    
    counter = 0
    for stats, values in stored_data[player].items():
        var = StringVar()
        var.set(values)
        value_list.append(var)

        edit_data_frame = Frame(stats_edit_frame)
        edit_data_frame.grid(row=1, column=counter, padx=5, pady=5)
        for i in range(3):
            edit_data_frame.columnconfigure(i, minsize=50)

        Label(edit_data_frame, text=stats).grid(row=0, column=0, columnspan=3)

        Button(edit_data_frame, text='-', command=partial(change, value_list[counter], stats, '-')).grid(row=1, column=0, sticky='nsew')

        Label(edit_data_frame, textvariable=value_list[counter]).grid(row=1, column=1)

        Button(edit_data_frame, text='+', command=partial(change, value_list[counter], stats, '+')).grid(row=1, column=2, sticky='nsew')
        counter += 1

    done = Button(stats_edit_frame, text='Done', command=del_n_refresh)
    done.grid(row=3, column=0, columnspan=total_length, sticky='nsew', pady=5, padx=5)


def pack_all_players():
    # this for loop is for refreshing the data
    for widget in all_player_frame.winfo_children():
        widget.destroy()

    for player in stored_data:
        player_frame = Frame(all_player_frame, width=100)
        player_frame.pack(side='left', pady=20, padx=20)

        Label(player_frame, text=player, font='default 12 normal').pack(side='top', pady=5)

        stats_frame = Frame(player_frame)
        stats_frame.pack(side='top', pady=10)
        for stats, values in stored_data[player].items():
            Label(stats_frame, text=f'{stats}: {values}').pack()

        Button(player_frame, text='Edit', width=15, command=partial(open_edit_window, player)).pack(side='bottom', pady=5)


root = Tk()

all_player_frame = Frame(root)
all_player_frame.pack()

pack_all_players()

root.mainloop()

所以这个过程已经在另一个答案中解释过,在这里它几乎相同,几乎相同的循环,几乎相同的调用,但使用函数而不是类。如果您问这是否可以实现:那么如果您的意思只是将这些函数添加到您的代码(您发布的那个)中,那么这些函数就可以完成所有操作,因此唯一的实现是在您的代码上复制粘贴,那么您还可以更改一些功能,修改它们等等,因为它们根据需要创建小部件,所以基本上字典中的玩家数量以及这将创建的相应小部件的数量(您的方法似乎是硬编码信息)。如果你想保存到我在另一个答案中也提到过的文件中。

【讨论】:

  • 非常感谢您的辛勤工作。组合代码时,我不确定如何将它们与 4 个名称和该数据链接在一起。您能否使用这 4 个名称和统计信息将“编辑”按钮链接到我的原始代码。 ?我知道我要求很多,但我会永远很棒
  • 非常感谢您的辛勤工作。组合代码时,我不确定如何将它们与 4 个名称和该数据链接在一起。您能否使用这 4 个名称和统计信息将“编辑”按钮链接到我的原始代码。 ?我知道我要求很多,但我会永远很棒
  • @Volted 我可以让你的编辑按钮打开一个新窗口,但问题是你不存储数据,你不能只把它放在标签中你必须创建一个字典(因为那是最简单的方法)并将数据放在字典中的标签上,而不是相反。所以第一件事是您创建一个字典,您将在其中存储所有数据(将向您确切显示我的意思(您的方式(几乎)但我告诉您您必须学习如何使用循环来创建小部件,否则您将拥有每次添加更多玩家时手动创建新小部件))
  • 那真是太好了,我希望现在可以做剩下的球员了。我现在唯一需要的是代码的#cmets,因为我不明白其中一些说明代码的作用
  • @Volted 你在说哪个代码?最近的答案还是这个(带函数)?
【解决方案3】:

所以这完全是你的方式(至少是我能找到的最接近的方式,也是最糟糕的方式,但你做你):

# import what is necessary
from tkinter import Tk, Label, Button, IntVar, Toplevel
import json

# first try doing this code of block and if it raises the FileNotFoundError use the other bloc
try:
    # open 'settings.json' file and load the data (import json first)
    with open('settings.json') as file:
        stored_data = json.load(file)

except FileNotFoundError:
    # create sample data to add to the created file
    stored_data = {'Daniel Keelagher': {'Matches Played': 10, 'Goals': 4, 'Assists': 4, 'YC': 0, 'RC': 0},
                   'Joseph Keelagher': {'Matches Played': 9, 'Goals': 2, 'Assists': 2, 'YC': 1, 'RC': 0},
                   'Benjamin Miller': {'Matches Played': 9, 'Goals': 0, 'Assists': 0, 'YC': 1, 'RC': 0},
                   'Jordan Terlato': {'Matches Played': 8, 'Goals': 1, 'Assists': 1, 'YC': 3, 'RC': 1}}
    # create 'settings.json' file if the file was not found
    with open('settings.json', 'w') as file:
        # dump all the data in 'settings.json'
        json.dump(stored_data, file, indent=2)

# define function change which will be responsible for changing data in stored_data dictionary
def change(player, stat, value, operator):  # set required arguments for the function which will be the: player (key in the dictionary, i.e. 'Daniel Keelagher'); stat (key in the player dictionary i.e. 'Goals', 'Assists'); value (refers to the IntVar associated with the respective Label); operator (determines whether value will be subtracted or added)
    # getting the current value of the associated IntVar
    cur_value = value.get()
    # eval to determine the operation if/elif
    if operator == '-':
        # accessing the stored_data key and dictionary key under the stored_data[key]
        stored_data[player][stat] = cur_value - 1
        # setting the IntVar value
        value.set(cur_value - 1)
    elif operator == '+':
        # same as previous but adding value
        stored_data[player][stat] = cur_value + 1
        value.set(cur_value + 1)


# defining edit_dk which will be responsible for editing Daniel Keelagher so such similar functions should be created for all players i.e. edit_jk, edit_bm
def edit_dk():
    # creating a new window for data editing
    tp = Toplevel(root)

    # packing a label to display name
    Label(tp, text='Daniel Keelagher').grid(row=0, column=0, columnspan=15)

    # packing edit buttons and value label for data editing, command is set to change() and can be followed through using previous comments this explanation is for all the Label-Button groups below defined in this function
    Button(tp, text='-', command=lambda: change('Daniel Keelagher', 'Matches Played', dk_matches_var, '-')).grid(row=1, column=0)
    Label(tp, textvariable=dk_matches_var).grid(row=1, column=1)
    Button(tp, text='+', command=lambda: change('Daniel Keelagher', 'Matches Played', dk_matches_var, '+')).grid(row=1, column=2)

    Button(tp, text='-', command=lambda: change('Daniel Keelagher', 'Goals', dk_goals_var, '-')).grid(row=1, column=3)
    Label(tp, textvariable=dk_goals_var).grid(row=1, column=4)
    Button(tp, text='+', command=lambda: change('Daniel Keelagher', 'Goals', dk_goals_var, '+')).grid(row=1, column=5)

    Button(tp, text='-', command=lambda: change('Daniel Keelagher', 'Assists', dk_assists_var, '-')).grid(row=1, column=6)
    Label(tp, textvariable=dk_assists_var).grid(row=1, column=7)
    Button(tp, text='+', command=lambda: change('Daniel Keelagher', 'Assists', dk_assists_var, '+')).grid(row=1, column=8)

    Button(tp, text='-', command=lambda: change('Daniel Keelagher', 'YC', dk_yc_var, '-')).grid(row=1, column=9)
    Label(tp, textvariable=dk_yc_var).grid(row=1, column=10)
    Button(tp, text='+', command=lambda: change('Daniel Keelagher', 'YC', dk_yc_var, '+')).grid(row=1, column=11)

    Button(tp, text='-', command=lambda: change('Daniel Keelagher', 'RC', dk_rc_var, '-')).grid(row=1, column=12)
    Label(tp, textvariable=dk_rc_var).grid(row=1, column=13)
    Button(tp, text='+', command=lambda: change('Daniel Keelagher', 'RC', dk_rc_var, '+')).grid(row=1, column=14)


# initiating Tk class which also creates a window
root = Tk()

# Labels
Label(text="Chelsea FC Player Statistics", font=('bold', 15), fg="blue",).grid(row=0, column=1)

# Player Names Labels
Label(text="Player Names", font='bold').grid(columnspan=1, row=1, column=1)
Label(text="Daniel Keelagher").grid(columnspan=1, row=2, column=1)

# Matches Played Labels
Label(text="Matches Played", font='bold').grid(columnspan=1, row=1, column=2)
# setting up an IntVar for matches: for other players it could be for example bm_matches_var and is related to matches label (below) this explanation fits other IntVars too.
dk_matches_var = IntVar()
# set the variable to statistics the same for the rest
dk_matches_var.set(stored_data['Daniel Keelagher']['Matches Played'])
Label(textvariable=dk_matches_var).grid(columnspan=1, row=2, column=2)


# Goals Labels
Label(text="Goals", font='bold').grid(row=1, column=3)
dk_goals_var = IntVar()
dk_goals_var.set(stored_data['Daniel Keelagher']['Goals'])
Label(textvariable=dk_goals_var).grid(columnspan=1, row=2, column=3)

# Assists Labels
Label(text="Assists", font='bold').grid(columnspan=1, row=1, column=4)
dk_assists_var = IntVar()
dk_assists_var.set(stored_data['Daniel Keelagher']['Assists'])
Label(textvariable=dk_assists_var).grid(columnspan=1, row=2, column=4)

# YellowCards Labels
Label(text="YC", font='bold').grid(columnspan=1, row=1, column=5)
dk_yc_var = IntVar()
dk_yc_var.set(stored_data['Daniel Keelagher']['YC'])
Label(textvariable=dk_yc_var).grid(columnspan=1, row=2, column=5)

# RedCards Labels
Label(text="RC", font='bold').grid(columnspan=1, row=1, column=6)
dk_rc_var = IntVar()
dk_rc_var.set(stored_data['Daniel Keelagher']['RC'])
Label(textvariable=dk_rc_var).grid(columnspan=1, row=2, column=6)


# Buttons for other it could be something like `command=edit_bm`
Button(root, text="Edit", command=edit_dk).grid(columnspan=1, row=2, column=7)

# main loop of tkinter
root.mainloop()

# save file after closing the window
with open('settings.json', 'w') as file:
    json.dump(stored_data, file, indent=2)

这是一个播放器,您必须为字典中的每个播放器执行此操作,在首页添加所有这些标签,所有这些变量,按钮,并为每个播放器定义函数(类似于我有显示在这个例子中)你还必须匹配那些字典键(如函数中定义的那样)(只是通过例子来做,你应该没问题,但我真的建议你看看我给出的其他答案,“研究它们”并使用这些,看看教程(正如已经提到的 cmets 中的某人)或某事,因为这是最糟糕的方法,特别是因为有很多更简单的方法可以做到这一点,所以这就是你可以做到的方法但你不应该这样做,因为这在客观上是不必要的)

您唯一不必更改的是change 函数定义以及如果您有问题。

如果您对此感兴趣,我已经在第一个答案中介绍了保存到文件。

【讨论】:

  • 我注意到你很好地应用了这个解决方案,`\` 有一个小的语法错误,但其他方面看起来相当不错(除了它不是在第一名)
  • 在存储的数据中有所有的数字,但是当我运行我的代码时,它们都设置为0,这很好,但是一旦我编辑了它如何保存呢?跨度>
  • @Volted 编辑的代码包括我忘记将 IntVar()s 设置为 value 所以也看一下(在我为每个 IntVar 添加的代码中)(这也是为什么 0显示)
猜你喜欢
  • 1970-01-01
  • 2015-03-26
  • 2014-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多