将字典集中的项目分配给组合框 [英] Assigning items from dictionary's set to a Combobox

查看:34
本文介绍了将字典集中的项目分配给组合框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的计划是创建一个包含个人姓名的组合框,以便用户可以从集合中选择一个名称并将其点数输入到输入框中.我尝试这样做,但我的下拉列表没有显示个人集中的名称列表,而是显示所有 5 个集合:Team1、Team2、Team3、Team4 和 Individuals.

My plan was to create a combobox with the names of individuals, so that user can select a name from the set and enter its points into the Entry box. I tried to do this, but my drop-down list does not show a list of names in the Individual set, but just all 5 sets: Team1, Team2, Team3, Team4 and Individuals.

最初,一切都被安排好,以便用户输入个人的姓名,该姓名保存在字典中 teams = {... 'Individuals': set()} 之后是姓名显示在列表框中.在下一个窗口中,应该有一个下拉列表,其中包含个人集合中的所有名称,但是,正如我上面所说,我无法创建它.

Initially, everything is arranged so that the user enters the name of the Individual, which is saved in the dictionary teams = {... 'Individuals': set()} after which the names are displayed in the list box. In the next window, there should be a drop-down list with all the names that are in the set of Individuals, but, as I said above, I could not create it.

我想知道如何解决这个问题.

I would like to know how to solve this problem.

我的代码:

from tkinter import *
from tkinter import messagebox
import tkinter.ttk as ttk

# This code is a simplified version of a full program code. In the original program, there is not only a list
# of individuals, but also lists of team1, team2 ... team4.
# However, now I am only interested in the problems associated with individual list,
# and I cut out all the part of the code related to team.


class CollegeApp(Tk):
    def __init__(self):
        Tk.__init__(self)
        container = ttk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        self.frames = {}
        for F in (IndividPage, listCheckPage, counterPage):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(IndividPage)
        self.lift()

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()


# In this  class I have created a window with entry widget to input name of individual and save it in
# eponymous set "Individual"

class IndividPage(ttk.Frame):

    def __init__(self, parent, controller):
        self.controller = controller
        ttk.Frame.__init__(self, parent)
        self.userEntry()

    def userEntry(self):
        headingTest = Label(self, text="Enter your User Name:", font="Arial 20")
        headingTest.grid(row=0, column=0, pady=5, padx=5)

        self.usernameEnter = Entry(self, width=40)
        self.usernameEnter.grid(row=0, column=1, padx=5, pady=5)

        self.TeamName = StringVar(self)
        self.TeamName.set("Individual")

        confirmBtn = Button(self, text="Confirm User", font="Arial 16",
                            command=self.confirm)

        confirmBtn.config(height=4, width=12)
        confirmBtn.grid(row=2, column=2, sticky=E, padx=45, pady=360)

# Checking the "add_to_team" function has been executed and moving to the next page.
    def confirm(self):
        if self.add_to_team():
            self.controller.show_frame(listCheckPage)

# Function to check the presence of input

    def add_to_team(self):
        user = self.usernameEnter.get()
        if len(user) == 0:
            messagebox.showwarning(title='No user', message='Please enter a username!')
            return
        if self.usernameEnter.get():
            self.controller.show_frame(listCheckPage)

        team_name = self.TeamName.get()
        team = teams[team_name]

        team.add(user)
        self.controller.frames[listCheckPage].team_listboxes[team_name].insert(END, user)
        print(teams)

# Class that creates page with lists of four teams and individuals (Focusing on individuals right now)
# Also there is two buttons "Add User" and "Start Counter" to start points calculator

class listCheckPage(ttk.Frame):
    def __init__(self, parent, controller):
        self.controller = controller
        ttk.Frame.__init__(self, parent)
        self.userEntry()

    def userEntry(self):
        self.team_listboxes = {}
        for col_num, teamname in enumerate(teams):
            teamMembers = Listbox(self)
            teamMembers.config(height=13, width=15)
            teamMembers.grid(row=0, column=col_num, padx=5, pady=50, sticky=S)
            for i, user in enumerate(teams[teamname]):
                teamMembers.insert(i, user)
            self.team_listboxes[teamname] = teamMembers

        INDHeading = Label(self, text="Individuals", font="Arial 16")
        INDHeading.grid(row=0, column=4, pady=0, padx=15, sticky=N)

        addUserBtn = Button(self, text="Add User", font="Arial 16",
                            command=lambda: self.controller.show_frame(IndividPage))
        addUserBtn.config(height=3, width=80)
        addUserBtn.grid(row=1, column=0, columnspan=5, pady=0, sticky=N)

        CounterBtn = Button(self, text="Start Counter", font="Arial 16",
                            command=lambda: self.controller.show_frame(counterPage))
        CounterBtn.config(height=3, width=80)
        CounterBtn.grid(row=2, column=0, columnspan=5, pady=0, sticky=N)

# Main problem  start here
# This class creating dropdown menu (or combobox) with sets "teamX" and "Individual" but it was unplanned
# I want this combobox to show not all possible sets (team1, team2 etc.).
# Instead of that I want the combobox will show all the names that were entered in the "Individuals" set.
# I would also like to point out that the same process will be used for the sets of team1, team2 etc.


class counterPage(ttk.Frame):
    def __init__(self, parent, controller):
        self.controller = controller
        ttk.Frame.__init__(self, parent)
        self.userEntry()

    def userEntry(self):

        indivLabel = Label(self, text="Please select an individual: ", font="Arial 20")
        indivLabel.grid(row=0, column=0, pady=10, padx=10)

        IndivName = StringVar(self)
        IndivName.set(teams['Individual'])

        indivMenu = OptionMenu(self, IndivName, *teams)
        indivMenu.grid(row=0, column=1, pady=10, padx=10)

        backBtn = Button(self, text="BACK", font="Arial 16", height=2, width=6,
                         command=lambda: self.controller.show_frame(IndividPage))
        backBtn.grid(row=7, column=0, sticky=W, pady=245, padx=10)


if __name__ == '__main__':
    teams = {}
    for team in range(1, 5):
        teams[f'Team{team}'] = set()
    teams = {'Team1': set(), 'Team2': set(), 'Team3': set(), 'Team4': set(), 'Individual': set()}
    pointsInd = []
    app = CollegeApp()
    app.geometry("800x500")
    app.resizable(False, False)
    app.title('Points Counter')
    app.mainloop()

推荐答案

ok,所以我想我想通了(我用注释标记了代码中的更改,他们有很多-"所以这就是你会知道(总共有 3 个地方的变化(5 条评论中有很多-")):

ok, so I think I figured it out (I marked changes in the code with comments, they have a lot of "-" so that is how You will know (in total changes in 3 places (5 comments that have a lot of "-"))):

from tkinter import *
from tkinter import messagebox
import tkinter.ttk as ttk

# This code is a simplified version of a full program code. In the original program, there is not only a list
# of individuals, but also lists of team1, team2 ... team4.
# However, now I am only interested in the problems associated with individual list,
# and I cut out all the part of the code related to team.


class CollegeApp(Tk):
    def __init__(self):
        Tk.__init__(self)
        container = ttk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        self.frames = {}
        for F in (IndividPage, listCheckPage, counterPage):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(IndividPage)
        self.lift()

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()
        if cont == counterPage:  # changes here ----------------------------------------------------------------------------------------------------------
            frame.userEntry()  # ------------------------------------------------------------------------------


# In this  class I have created a window with entry widget to input name of individual and save it in
# eponymous set "Individual"

class IndividPage(ttk.Frame):

    def __init__(self, parent, controller):
        self.controller = controller
        ttk.Frame.__init__(self, parent)
        self.userEntry()

    def userEntry(self):
        headingTest = Label(self, text="Enter your User Name:", font="Arial 20")
        headingTest.grid(row=0, column=0, pady=5, padx=5)

        self.usernameEnter = Entry(self, width=40)
        self.usernameEnter.grid(row=0, column=1, padx=5, pady=5)

        self.TeamName = StringVar(self)
        self.TeamName.set("Individual")

        confirmBtn = Button(self, text="Confirm User", font="Arial 16",
                            command=self.confirm)

        confirmBtn.config(height=4, width=12)
        confirmBtn.grid(row=2, column=2, sticky=E, padx=45, pady=360)

# Checking the "add_to_team" function has been executed and moving to the next page.
    def confirm(self):
        if self.add_to_team():
            self.controller.show_frame(listCheckPage)

# Function to check the presence of input

    def add_to_team(self):
        user = self.usernameEnter.get()
        if len(user) == 0:
            messagebox.showwarning(title='No user', message='Please enter a username!')
            return
        if self.usernameEnter.get():
            self.controller.show_frame(listCheckPage)

        team_name = self.TeamName.get()
        team = teams[team_name]

        team.add(user)
        self.controller.frames[listCheckPage].team_listboxes[team_name].insert(END, user)
        print(teams)

# Class that creates page with lists of four teams and individuals (Focusing on individuals right now)
# Also there is two buttons "Add User" and "Start Counter" to start points calculator

class listCheckPage(ttk.Frame):
    def __init__(self, parent, controller):
        self.controller = controller
        ttk.Frame.__init__(self, parent)
        self.userEntry()

    def userEntry(self):
        self.team_listboxes = {}
        for col_num, teamname in enumerate(teams):
            teamMembers = Listbox(self)
            teamMembers.config(height=13, width=15)
            teamMembers.grid(row=0, column=col_num, padx=5, pady=50, sticky=S)
            for i, user in enumerate(teams[teamname]):
                teamMembers.insert(i, user)
            self.team_listboxes[teamname] = teamMembers

        INDHeading = Label(self, text="Individuals", font="Arial 16")
        INDHeading.grid(row=0, column=4, pady=0, padx=15, sticky=N)

        addUserBtn = Button(self, text="Add User", font="Arial 16",
                            command=lambda: self.controller.show_frame(IndividPage))
        addUserBtn.config(height=3, width=80)
        addUserBtn.grid(row=1, column=0, columnspan=5, pady=0, sticky=N)

        CounterBtn = Button(self, text="Start Counter", font="Arial 16",
                            command=lambda: self.controller.show_frame(counterPage))
        CounterBtn.config(height=3, width=80)
        CounterBtn.grid(row=2, column=0, columnspan=5, pady=0, sticky=N)

# Main problem  start here
# This class creating dropdown menu (or combobox) with sets "teamX" and "Individual" but it was unplanned
# I want this combobox to show not all possible sets (team1, team2 etc.).
# Instead of that I want the combobox will show all the names that were entered in the "Individuals" set.
# I would also like to point out that the same process will be used for the sets of team1, team2 etc.


class counterPage(ttk.Frame):
    def __init__(self, parent, controller):
        self.controller = controller
        ttk.Frame.__init__(self, parent)
        # self.userEntry() this method call seems to be useless -------------------------------------------------

    def userEntry(self):

        indivLabel = Label(self, text="Please select an individual: ", font="Arial 20")
        indivLabel.grid(row=0, column=0, pady=10, padx=10)

        list_ = []  # changes here ----------------------------------------------------------------------------------------------------
        for set_ in teams.values():
            for name in set_:
                list_.append(name)

        IndivName = StringVar(self)
        IndivName.set(list_[0] if len(list_) else None)
        indivMenu = OptionMenu(self, IndivName, list_)
        indivMenu.grid(row=0, column=1, pady=10, padx=10)  # --------------------------------------------------------------------------------

        backBtn = Button(self, text="BACK", font="Arial 16", height=2, width=6,
                         command=lambda: self.controller.show_frame(IndividPage))
        backBtn.grid(row=7, column=0, sticky=W, pady=245, padx=10)


if __name__ == '__main__':
    # teams = {}
    # for team in range(1, 5):
    #     teams[f'Team{team}'] = set()
    teams = {'Team1': set(), 'Team2': set(), 'Team3': set(), 'Team4': set(), 'Individual': set()}
    pointsInd = []
    app = CollegeApp()
    # app.geometry("x500")
    # app.resizable(False, False)
    app.title('Points Counter')
    app.mainloop()

基本上,我这样做是为了在用户到达该框架时调用 userEntry 函数,而不是在类启动时调用,这意味着每次有人切换到该框架时它都会更新,还使其单独显示每个名称.

Basically I made it so that the userEntry function gets called when user gets to that frame instead when the class is initiated which means it will upadate every time someone switches to that frame, also made it so that it displays each name individually.

此外,我建议遵循 PEP 8 并使用 snake_case 作为函数、变量和方法名称,并使用 CapitalCase 作为类名称.我也建议遵循其他 PEP 8 规则(它们不是强制性的)

Also I suggest following PEP 8 and using snake_case for function, variable and method names and using CapitalCase for class names. And I suggest following other PEP 8 rules too (they are not mandatory tho)

这篇关于将字典集中的项目分配给组合框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆