I am trying to create a pop-up box to select multiple years. I have the box created but I cannot figure out how to make a button to actually select multiple years. The goal is to take that selection and store it in a list.
from tkinter import *
import pandas as pd
import tkinter as tk
test_years = ["2016", "2017", "2018", "2019"]
root = tk.Tk()
root.title("Test Year Selection")
lb = Listbox(root, selectmode=MULTIPLE, height = len(test_years), width = 50) # create Listbox
for x in test_years: lb.insert(END, x)
lb.pack() # put listbox on window
root.mainloop()
To clarify I am looking to select lets say 2017 and 2018 and have that selection stored in a list using tkinter listbox.
Any assistance would be greatly appreciated.
A example to get the value you select when you press the Start button:
from tkinter import *
# import pandas as pd
import tkinter as tk
def printIt():
SelectList = lb.curselection()
print([lb.get(i) for i in SelectList]) # this will print the value you select
test_years = ["2016", "2017", "2018", "2019"]
root = tk.Tk()
root.title("Test Year Selection")
lb = Listbox(root, selectmode=MULTIPLE, height = len(test_years), width = 50) # create Listbox
for x in test_years: lb.insert(END, x)
lb.pack() # put listbox on window
tk.Button(root,text="Start",command=printIt).pack()
root.mainloop()
Basically you want to add the value of selected item of listbox to a list. you need to call bind() method on the listbox widget. here is the code from this amazing tutorial on tkinter listbox
def get_value(event):
# Function to be called on item click
# Get the index of selected item using the 'curseselection' method.
selected = l.curselection()
if selected: # If item is selected
print("Selected Item : ",l.get(selected[0])) # print the selected item
# Create a listbox widget
l = Listbox(window)
l.bind('<>',get_value)
l.pack()
Related
I have these five lists:
list_1 = ['1','2','3','4','5']
list_2 = ['2','4','6','8','10']
list_3 = ['3','6','9','12','18']
list_4 = ['1','3','5','7','9']
list_5 = ['2','3','5','7','8']
What I am trying to do is make a simulation that will have drop down menus, where each menu 1 through 5 is correlated with each list 1 through 5 respectively.
But, the trick is that if there is a string value that is already choosen and present in one of the menus, the other menus that has the same string value will no longer have that as an option.
For example, '3' is present in list_1, list_3, list_4, and list_5.If I choose '3' for menu 4, then the option of '3' will no longer be available for list_1, list_3, and list_5.
What I have done:
I imported the itertools library, so I could find all possible combinations of the lists, respective to each menu.
import itertools
combos = list(itertools.product(list_1, list_2, list_3, list_4, list_5))
I know this might not be useful for the actual code later, but I thought it would be a good reference point. Next, I started looking into libraries that might be useful for this approach, I found tkinter was a good library.
import tkinter as tk
# Creating the main window
window = tk.Tk()
After this point, I'm sort of confused. How should I go about trying to code? I'm using the following documentation:
https://docs.python.org/3/library/tk.html
I've tried playing around with it, and was able to make a click me button, though this is not what I want:
import tkinter as tk
# Creating the main window
window = tk.Tk()
# Click me button to the main window
button = tk.Button(window, text="Click Me")
button.pack()
# Running Tkinter loop for button
window.mainloop()
This is an example of a Tkinter window that enables and disables menu items as per your description. If menu_item 3 is selected, then that menu is disabled, and the rest are enabled.
Here is the code:
Code:
from tkinter import *
from tkinter import ttk, messagebox
import copy
def disable_menuitem(menu_item):
enable_all_menus()
for i, m in enumerate(menu_list_items):
if menu_item in m:
menus[i].entryconfig(m.index(menu_item)+1, state="disabled")
print(f"List{i} - menu value {menu_item}")
# Function to enable all of the menu items
def enable_all_menus():
for i, m in enumerate(menu_list_items):
for j in m:
menus[i].entryconfig(m.index(j), state="normal")
# Create the Frame and menubar
root = Tk(className=' Example by ScottC')
root.geometry("200x200")
ttk.Entry(root).grid()
menubar = Menu(root)
# Create the menu widgets
menu1 = Menu(menubar)
menu2 = Menu(menubar)
menu3 = Menu(menubar)
menu4 = Menu(menubar)
menu5 = Menu(menubar)
menus = [menu1, menu2, menu3, menu4, menu5]
# Add menu widgets to the menubar
for i, m in enumerate(menus):
menubar.add_cascade(menu=m, label=f"List{i+1}")
# Define the names of each menu
list_1 = ['1','2','3','4','5']
list_2 = ['2','4','6','8','10']
list_3 = ['3','6','9','12','18']
list_4 = ['1','3','5','7','9']
list_5 = ['2','3','5','7','8']
menu_list_items = [list_1, list_2, list_3, list_4, list_5]
# Add menu items to the menu widgets
for i, l in enumerate(menu_list_items):
for item in l:
menus[i].add_command(label=item, command=lambda y=item: disable_menuitem(y))
root['menu'] = menubar
root.mainloop()
Output when 3 is selected:
i want to add multiple values that the user select from different comboboxes. I then want to add together the values and display the total value next to the boxes. The problem seems to be that the "values" from the comboboxes are strings, and can therefore not be added together.
If you wanna run the program, just comment out the variable "totalvalues before the last for loop. (i know it looks wierd, i just tried to make a new program to show my problem)
import tkinter as tk
from tkinter import ttk
from tkinter import scrolledtext
win=tk.Tk() #window
win.title("Moskalkylator")
antalcomboboxes=4
mighty=ttk.LabelFrame(win,text='Welcome')
mighty.grid(column=0,row=0,padx=8 ,pady=4)
Items=['Wood','Iron','Plastic','Glass']
def click():
calculate = ttk.Label(win, text="Your total number of items is : " + totalvalues.get()) # See row 27
calculate.grid(column=1, row=0)
buttons_frame=ttk.LabelFrame(mighty)
buttons_frame.grid(column=1,row=8, padx=3, pady=3,sticky=tk.W)
calculate=ttk.Button(buttons_frame,text='Count', command=click).grid(column=1,row=8)
#Creates combobox 1
list1=list(range(11))
number_chosen1= ttk.Combobox(mighty,values=list1, state="readonly") #The number you pick in the combobox
number_chosen1.grid(column=1,row=1,sticky=tk.W)
#Creates combobox 2
list2=list(range(11))
number_chosen2= ttk.Combobox(mighty,values=list2, state="readonly")
number_chosen2.grid(column=1,row=3,sticky=tk.W)
###############
totalvalues=number_chosen1+number_chosen2 #This does not work! COMMENT THIS
###############
#Loop to get the names of the items above combobox
Items_order=0
row_move_loop2=0
for element in Items:
article = ttk.Label(mighty, text=Items[Items_order])
article.grid(column=1, row=row_move_loop2)
Items_order=Items_order+1
row_move_loop2=row_move_loop2+2
win.mainloop()
You have to use the get() method to get the values from combobox and convert them to integers. Also, don't keep creating new label everytime you want to display the count instead create the label once and use configure method to change the text.
Here is your corrected code:
import tkinter as tk
from tkinter import ttk
from tkinter import scrolledtext
win=tk.Tk() #window
win.title("Moskalkylator")
antalcomboboxes=4
mighty=ttk.LabelFrame(win,text='Welcome')
mighty.grid(column=0,row=0,padx=8 ,pady=4)
Items=['Wood','Iron','Plastic','Glass']
def click():
global totalvalues
if number_chosen1.get() != '' and number_chosen2.get() != '':
totalvalues= int(number_chosen1.get()) + int(number_chosen2.get())
calculate.configure(text="Your total number of items is : " + str(totalvalues))
buttons_frame=ttk.LabelFrame(mighty)
buttons_frame.grid(column=1,row=8, padx=3, pady=3,sticky=tk.W)
calculate=ttk.Button(buttons_frame,text='Count', command=click).grid(column=1,row=8)
#Creates combobox 1
list1=list(range(11))
number_chosen1= ttk.Combobox(mighty,values=list1, state="readonly") #The number you pick in the combobox
number_chosen1.grid(column=1,row=1,sticky=tk.W)
#Creates combobox 2
list2=list(range(11))
number_chosen2= ttk.Combobox(mighty,values=list2, state="readonly")
number_chosen2.grid(column=1,row=3,sticky=tk.W)
###############
print(number_chosen1.get())
totalvalues = 'None'
calculate = ttk.Label(win) # See row 27
calculate.grid(column=1, row=0)
###############
#Loop to get the names of the items above combobox
Items_order=0
row_move_loop2=0
for element in Items:
article = ttk.Label(mighty, text=Items[Items_order])
article.grid(column=1, row=row_move_loop2)
Items_order=Items_order+1
row_move_loop2=row_move_loop2+2
win.mainloop()
when u retrieve values as a string u need to convert them.
totalvalues=int(number_chosen1)+int(number_chosen2)
or
totalvalues=float(number_chosen1)+float(number_chosen2)
I'm new to Python and Tkinter and was trying to create an interface to search & plot data. I created a very simple toplevel window to get the values from a combobox that would be selected from users. However, I find the script would only print the first item in the list if comboxlist2.current(0) was set or it would print nothing, no matter which one is selected in the box. I created a sample script to test this. If I click on the "search & create", then the return values can change according to the user selection in comboxlist1, while it would all return "1" no matter what the user selected in comboxlist2. So may I ask where is the issue and how to solve?
Thanks in advance for the potential suggestions or solutions!
import tkinter as tk
from tkinter import ttk
from tkinter import *
def root_print():
reg_in = comboxlist1.get()
print(reg_in) #print the value selected
def on_click():
tl = Toplevel()
comvalue2 = tk.StringVar()
comboxlist2 = ttk.Combobox(tl,textvariable=comvalue2)
comboxlist2["values"] = ("1","2","3")
comboxlist2.grid()
comboxlist2.current(0) #select the first one as default
#mm = comboxlist2.get()
#print(mm) #print directly
go(comboxlist2,tl)
tl.wait_window()
return
def go(comboxlist2,tl):
mm = comboxlist2.get()
Button(tl,text='go', command=lambda:test(mm)).grid()
def test(mm):
print(mm) #do the same thing for the comboxlist2
root = Tk()
root.title('search') #create an interface
root.geometry('+400+200') #size and position
Label(text='region ').grid(row=2,column=0)
comvalue1 = tk.StringVar()
comboxlist1=ttk.Combobox(root,textvariable=comvalue1)
comboxlist1["values"]=("all","africa","asia","australia","canada","europe","mexico","southamerica","usa")
comboxlist1.grid(row=2,column=1)
comboxlist1.current(0)
Button(text='search & create', command=root_print).grid(row=0,column=4)
Button(text='click', command=on_click).grid(row=1, column=4)
loop = mainloop()#go!
Here is the working code, which should take care of your needs. I have removed the imports and some code snippets which are not useful.
import tkinter as tk
from tkinter import ttk
def root_print():
reg_in = comboxlist1.get()
print(reg_in)
def on_click():
tl = tk.Toplevel()
comvalue2 = tk.StringVar()
comboxlist2 = ttk.Combobox(tl,textvariable=comvalue2)
comboxlist2["values"] = ("1","2","3")
comboxlist2.grid()
comboxlist2.current(0) #select the first one as default
tk.Button(tl,text='go', command=lambda: test(comboxlist2.get())).grid()
tl.wait_window()
def test(mm):
print(mm)
root = tk.Tk()
root.title('search') #create an interface
root.geometry('+400+200') #size and position
tk.Label(text='region ').grid(row=2,column=0)
comvalue1 = tk.StringVar()
comboxlist1=ttk.Combobox(root,textvariable=comvalue1)
comboxlist1["values"]=("all","africa","asia","australia","canada","europe","mexico","southamerica","usa")
comboxlist1.grid(row=2,column=1)
comboxlist1.current(0)
tk.Button(text='search & create', command=root_print).grid(row=0,column=4)
tk.Button(text='click', command=on_click).grid(row=1, column=4)
root.mainloop()
I am trying to make a program which enables comparison of data from selected files in one graph. The order in which they are depcited as well as the distance between them is important. However the order in which I select them in the window created by using Tkinter is not the same as the order in which they are passed to the program. The order in which I have to select them in order to get the correct order is 2, 3, 4, 5, 1 this results in order 1, 2, 3, 4, 5 in the program.
It is not a big problem once you know it but the intention is that others will be using the program as well so I need it to work as simple and robust as possible. Below is the snippet of the code that I use where Tkinter is involved.
root = Tkinter.Tk()
filez = tkFileDialog.askopenfilenames(parent=root,title='Choose a file')
filez= root.tk.splitlist(filez)
root.destroy()
There are no options for controlling the order in listed in the documentation. Your best bet is to use multiple file selection dialogs one after another.
tkFileDialog doesn't have function to remeber order of selected files so you can build own FileDialog or...
... build some Dialog to select order of files after you get files from tkFileDialog
import Tkinter as tk
import tkFileDialog
def Selector(data):
def append(widget, element, results, display):
# append element to list
results.append(element)
# disable button
widget['state'] = 'disabled'
# add element to label
current = display['text']
if current:
current += '\n'
display['text'] = current + element
# create window
root = tk.Tk()
# list for correct order
results = []
# label to display order
tk.Label(root, text='ORDER').pack()
l = tk.Label(root, anchor='w', justify='left')
l.pack(fill='x')
# buttons to select elements
tk.Label(root, text='SELECT').pack()
for d in data:
b = tk.Button(root, text=d, anchor='w')
b['command'] = lambda w=b, e=d, r=results, d=l:append(w, e, r, d)
b.pack(fill='x')
# button to close window
b = tk.Button(root, text='Close', command=root.destroy)
b.pack(fill='x', pady=(15,0))
# start mainloop
root.mainloop()
return results
# --- main ---
root = tk.Tk()
filez = tkFileDialog.askopenfilenames(parent=root,title='Choose a file')
root.destroy()
print(filez)
filez = Selector(filez)
print(filez)
...
self.myListbox=tkinter.Listbox()
self.myListbox.pack()
self.myButton=tkinter.Button(self.myListbox,text="Press")
self.myListbox.insert(1,myButton.pack())
...
I want to insert a button into listbox like inserting a sting. How can I do this?
You can't. From the listbox documentation: "A listbox is a widget that displays a list of strings".
You can, of course, use pack, place or grid to put a button inside the widget but it won't be part of the listbox data -- it won't scroll for example, and might obscure some of the data.
An alternative to a ListBox is a scrollable frame;
import functools
try:
from tkinter import *
import tkinter as tk
except ImportError:
from Tkinter import *
import Tkinter as tk#
window = Tk()
frame_container=Frame(window)
canvas_container=Canvas(frame_container, height=100)
frame2=Frame(canvas_container)
myscrollbar=Scrollbar(frame_container,orient="vertical",command=canvas_container.yview) # will be visible if the frame2 is to to big for the canvas
canvas_container.create_window((0,0),window=frame2,anchor='nw')
def func(name):
print (name)
mylist = ['item1','item2','item3','item4','item5','item6','item7','item8','item9']
for item in mylist:
button = Button(frame2,text=item,command=functools.partial(func,item))
button.pack()
frame2.update() # update frame2 height so it's no longer 0 ( height is 0 when it has just been created )
canvas_container.configure(yscrollcommand=myscrollbar.set, scrollregion="0 0 0 %s" % frame2.winfo_height()) # the scrollregion mustbe the size of the frame inside it,
#in this case "x=0 y=0 width=0 height=frame2height"
#width 0 because we only scroll verticaly so don't mind about the width.
canvas_container.pack(side=LEFT)
myscrollbar.pack(side=RIGHT, fill = Y)
frame_container.pack()
window.mainloop()