Jump to content

Python - How to assign items from dictionary's set to Option Menu?

I just can't figure out how to create an option menu (drop-down list or combobox) with items from the set in the dictionary. I have various sets, but I'm only interested in the "Individuals" set at the moment.

The instructions that I found on the Internet tell how to create an option menu with already existing items in the list or set, but my set is initially empty, and gradually fills up when the user enters a new name in this set.

I would like to know how to create an option menu that will display all the names that are in the "Individuals" set.

 

The final result should look like:

Please select an individual: Name1

________________________ Name2

________________________ Name3 etc.

My current option menu just displays all the sets that are in the dictionary, and not the names in the "Individuals" Set.

My code:

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()}
    app = CollegeApp()
    app.geometry("800x500")
    app.resizable(False, False)
    app.title('Points Counter')
    app.mainloop()

 
Link to comment
Share on other sites

Link to post
Share on other sites

39 minutes ago, Aleks_Retr0 said:

indivMenu = OptionMenu(self, IndivName, *teams)

Can't look in-depth at the moment, but from a quick glance, you feed it the entire dictionary, so it's only natural all the entries in the dictionary show up no? If you want it to only show entries in "Individuals" you'll need to pass only that set.

Crystal: CPU: i7 7700K | Motherboard: Asus ROG Strix Z270F | RAM: GSkill 16 GB@3200MHz | GPU: Nvidia GTX 1080 Ti FE | Case: Corsair Crystal 570X (black) | PSU: EVGA Supernova G2 1000W | Monitor: Asus VG248QE 24"

Laptop: Dell XPS 13 9370 | CPU: i5 10510U | RAM: 16 GB

Server: CPU: i5 4690k | RAM: 16 GB | Case: Corsair Graphite 760T White | Storage: 19 TB

Link to comment
Share on other sites

Link to post
Share on other sites

3 minutes ago, tikker said:

Can't look in-depth at the moment, but from a quick glance, you feed it the entire dictionary, so it's only natural all the entries in the dictionary show up no? If you want it to only show entries in "Individuals" you'll need to pass only that set.

@tikker Yes, but the problem is that if I will change 

*teams

to 

*Individual

It doesn't work, PyCharm just underline it with red line

Link to comment
Share on other sites

Link to post
Share on other sites

9 minutes ago, Aleks_Retr0 said:

@tikker Yes, but the problem is that if I will change 


*teams

to 


*Individual

It doesn't work, PyCharm just underline it with red line

It probably  underliens it because Individual doesn't exist as a variable? It would be teams['Individual']

Crystal: CPU: i7 7700K | Motherboard: Asus ROG Strix Z270F | RAM: GSkill 16 GB@3200MHz | GPU: Nvidia GTX 1080 Ti FE | Case: Corsair Crystal 570X (black) | PSU: EVGA Supernova G2 1000W | Monitor: Asus VG248QE 24"

Laptop: Dell XPS 13 9370 | CPU: i5 10510U | RAM: 16 GB

Server: CPU: i5 4690k | RAM: 16 GB | Case: Corsair Graphite 760T White | Storage: 19 TB

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×