python how to get button name from database - python

hello stack overflow members
my question is
how i can get the Button names when the buttons are automatically generating from a database
like this
for index, dat in enumerate(data2):
ttk.Button(master, text=dat[0]).grid(row=index+1, column=1,pady=0,padx=0)
any help<3

Or do you just want to know which button was pressed? Then try this:
from tkinter import *
import tkinter.ttk as ttk
master = Tk()
data2 = ['Orange','Apple','Banana','Kiwi']
button_dict = {}
def callback_function(x): print('Pressed:', x)
for index, dat in enumerate(data2):
button = ttk.Button(master, text=dat[0],
command=lambda dat=dat: callback_function(dat))
button.grid(row=index+1, column=1,pady=0,padx=0)
button_dict[dat] = button # Stores a reference to the button under
# the name from the database
for name in data2:
print(name, button_dict[name]) # prints all button/name associations
master.mainloop()

Related

How to display the label ( text) value dynamically based on combo box selection value ( List box) in Tkinter?

I am new to tkinter application. The below code is working fine. Please help how to implement mentioned features.
The dynamic value should be displayed above clear button or below the combo box ( Used pack is bottom )- Now working
Clear the label value on combo box selection.
import tkinter as tk
from tkinter import ttk
from tkinter import *
from datetime import datetime
# root window
root = tk.Tk()
root.geometry("500x350")
root.resizable(False, False)
root.title('Test')
# Log Generator in frame
Generator = tk.Frame(root)
Generator.pack(padx=10, pady=10, fill='x', expand=True)
def clear():
combo.set('')
# Function to print the index of selected option
# in Combobox
def get_log_file_name(*arg):
date_Value = datetime.now().strftime("%Y_%m_%d_%I%M%S")
output_file_name_value = "Log_"+date_Value
if var.get() == "apple":
Label(Generator, text="The value at index: "+output_file_name_value+".txt", font=('Helvetica 12')).pack()
else:
Label(Generator, text="The value at index: "+output_file_name_value+".html", font=('Helvetica 12')).pack()
# Define Tuple of months
months = ('apple','banana')
# Create a Combobox widget
label = ttk.Label(Generator, text="Selection_Option:",font=('Helvetica', 10, 'bold'))
label.pack(fill='x', expand=True)
var = StringVar()
combo = ttk.Combobox(Generator, textvariable=var)
combo['values'] = months
combo['state'] = 'readonly'
combo.pack(padx=5, pady=5)
# Set the tracing for the given variable
var.trace('w', get_log_file_name)
# Create a button to clear the selected combobox
# text value
button = Button(Generator, text="Clear", command=clear)
button.pack(side=left)
# Make infinite loop for displaying app on
# the screen
Generator.mainloop()
Clear the label value on combo box selection.
You need to capture the ComboboxSelect event to do that and the function to execute if captured
the function should be like this
What you want to do here, is to capture the combobox event, and then, do the label configuration when capturing it,
Below is the code to do the thing. and you can add code there.
def comboboxEventCapture(e=None):
label.configure(text='')
# Your code after resetting variables!
Here's the event capturing part
combo.bind("<<ComboboxSelect>>", comboboxEventCapture)
You can name the function whatever you want though.
Note that the arguement e is needed because if the event is captured, the event itself is passed as a parameter into the function, that is of no use here (unless you are going to do something with it, then use e.objname)
The dynamic value should be displayed above clear button
The second label could be outside of get_log_file_name() function.
And also configure inside function. So you don't do duplicate Label widget, naming Label2
Also the pack() must be split to prevent an error.
To clear Label2 use .configure(text='')
We will be using ttk. So don't do this from tkinter import *
Code:
import tkinter as tk
from tkinter import ttk
from datetime import datetime
root = tk.Tk()
root.geometry("500x350")
root.resizable(False, False)
root.title('Test')
Generator = tk.Frame(root)
Generator.pack(padx=10, pady=10, fill='x', expand=True)
def clear():
label2.configure(text='')
def get_log_file_name(*arg):
date_Value = datetime.now().strftime("%Y_%m_%d_%I%M%S")
output_file_name_value = "Log_"+date_Value
if var.get() == "apple":
label2.configure(text="The value at index: "+output_file_name_value+".txt", font=('Helvetica 12'))
else:
label2.configure(text="The value at index: "+output_file_name_value+".html", font=('Helvetica 12'))
# Define Tuple of months
months = ('apple','banana')
# Create a Combobox widget
label2 = ttk.Label(Generator)
label2.pack()
label = ttk.Label(Generator, text="Selection_Option:",font=('Helvetica', 10, 'bold'))
label.pack(fill='x', expand=True)
var = tk.StringVar()
combo = ttk.Combobox(Generator, textvariable=var)
combo['values'] = months
combo['state'] = 'readonly'
combo.pack(padx=5, pady=5)
# Set the tracing for the given variable
var.trace('w', get_log_file_name)
# Create a button to clear the selected combobox
# text value
button = ttk.Button(Generator, text="Clear", command=clear)
button.pack(side='left')
# Make infinite loop for displaying app on
# the screen
Generator.mainloop()
Screenshot for apple:
Screenshot for banana:
Screenshot to clear Label2:

Frame in Tkinter Popup Putting Content into Main Window instead of Popup

I am trying to create an app using the Tkinter Python library, and I created a preferences popup. I want to add checkboxes to it, and I want to do it in Frames via pack().
I want something like this:
Expected Result (IK it's Edited but Proof of Concept)
This is what I'm getting:
Actual Result (Look at Bottom of Image)
This is what I wrote:
# Import Libraries
from tkinter import *
from tkinter import ttk
from tkinter import simpledialog, messagebox
from tkinter.filedialog import asksaveasfile
from pygame import mixer as playsound
from datetime import datetime as date
from time import sleep
import pyttsx3
import json
import os
# Set Initial Window
window = Tk()
window.title("TTSApp")
window.geometry('500x580')
window.resizable(width=False,height=False)
playsound.init()
# Settings and Menu
preferences = {}
def preferencesHandler():
if os.path.exists('preferences.pref'):
preferences = {'AutoSave':True,'AutoSavePrompt':True,'AutoSaveAutomaticLoad':False}
with open('preferences.pref', 'w') as pref:
json.dump(preferences, pref)
else:
preferences = json.load(open('preferences.pref', 'r'))
pref.close()
sessionOptions = {'SessionName':'Untitled','VoiceSpeed':100}
def topmenucommands_file_newsession():
messagebox.showerror("New Session", "I haven't done this yet... you shouldn't even be able to see this...")
def topmenucommands_file_preferences():
preferencesWin = Toplevel(window)
preferencesWin.geometry("350x500")
preferencesWin.title("Preferences")
preferences_autosave = BooleanVar()
preferences_autosaveprompt = BooleanVar()
preferences_autosaveautomaticload = BooleanVar()
def topmenucommands_file_preferences_changed(*args):
with open('preferences.pref') as pref:
preferences['AutoSave'] = preferences_autosave.get()
preferences['AutoSavePrompt'] = preferences_autosaveprompt.get()
preferences['AutoSaveAutomaticLoad'] = preferences_autosaveautomaticload.get()
json.dump(preferences, pref)
pref.close()
Label(preferencesWin, text="Preferences", font=('helvetica', 24, 'bold')).pack()
autosave_container = Frame(preferencesWin,width=350).pack()
Label(autosave_container, text="Create Autosaves:", font=('helvetica', 12, 'bold')).pack(side=LEFT)
ttk.Checkbutton(autosave_container,command=topmenucommands_file_preferences_changed,variable=preferences_autosave,onvalue=True,offvalue=False).pack(side=RIGHT)
window.wait_window(preferencesWin)
pref.close()
def topmenucommands_session_renamesession():
topmenucommands_session_renamesession_value = simpledialog.askstring(title="Rename Session",prompt="New Session Name:")
sessionOptions['SessionName'] = topmenucommands_session_renamesession_value
topmenu = Menu(window)
topmenu_file = Menu(topmenu, tearoff=0)
#topmenu_file.add_command(label="New Session")
#topmenu_file.add_command(label="Save Session")
#topmenu_file.add_command(label="Save Session As...")
topmenu_file.add_command(label="Preferences", command=topmenucommands_file_preferences)
topmenu.add_cascade(label="File", menu=topmenu_file)
topmenu_session = Menu(topmenu, tearoff=0)
topmenu_session.add_command(label="Rename Session", command=topmenucommands_session_renamesession)
topmenu.add_cascade(label="Session", menu=topmenu_session)
# Create All of the Widgets and Buttons and Kiknacks and Whatnot
# Input Window
inputText = Text(window,height=20,width=62)
inputText.pack()
# Label for Speed Slider
speedText = Label(window, text='Voice Speed', fg='black', font=('helvetica', 8, 'bold'))
speedText.pack()
# Speed Slider
speed = Scale(window, from_=50, to=200, length=250, tickinterval=25, orient=HORIZONTAL, command=speedslidersavestate)
speed.set(100)
speed.pack()
# Dropdown for Voice Selection
voice = OptionMenu(window, voiceSelection, *voiceNames.keys())
voice.pack()
# Warning/Notice Label
warning = Label(window, text='', fg='red', font=('helvetica', 12, 'bold'))
warning.pack()
# Container for All Preview and Save (and PreviewRaw)
buttons = Frame(window)
buttons.pack()
# PreviewRaw Button; Huh... There's Nothing Here
# Preview Button
preview = Button(buttons,text='Preview',height=5,width=25,command=preview)
preview.pack(side=LEFT)
# Save Button
save = Button(buttons,text='Save to File',height=5,width=25,command=save)
save.pack(side=RIGHT)
window.config(menu=topmenu)
preferencesHandler()
window.mainloop()
Did I do something wrong or is there a better way to go about this or is this question a mess (this is my first time doing this)? Also, I clipped out all of the unnecessary content.
Edit: Added More Code
I figured it out. Apparently, I needed to pack() the Frame separately.
The answer was:
autosave_container = Frame(preferencesWin,width=350)
autosave_container.pack()
Instead of:
autosave_container = Frame(preferencesWin,width=350).pack()

How to make a button with the name of a file and also call that file?

So I am trying to make a sort of journal program where you can create an entry that is then saved as a text file. I currently have it set up so you can recall an entry by typing in the file name and clicking load, but I want to make a list of buttons on the right side that has all of the file names and then will load the respective file when clicked, any suggestions?
Here is my code:
from cProfile import label
from cgitb import text
from email.quoprimime import quote
import tkinter as tk
from tkinter import *
from tkinter import ttk
import tkinter
from traceback import print_tb
import os
from pip import main
def open_main():
#instantiate main screen
mainscreen = tk.Tk()
mainscreen.state("zoomed")
mainscreen.title("Welcome")
#file name text box
filename = tk.Entry(mainscreen)
filename.place(relx=.5, rely=.1, anchor=CENTER)
#save entry function
def save_entry():
savefile = open("%s .txt" % filename.get(), "w+")
savefile.write(T.get("1.0","end"))
savefile.close
refresh()
#load entry function
def loadentry():
loadentry = open("%s .txt" % filename.get(), "r")
quote = loadentry.readlines()
T.delete("1.0", END)
T.insert(END, quote)
#create frame to place main text box
mainframe = tkinter.Frame(mainscreen)
mainframe.place(relwidth=.65, relheight=.75, relx=.05, rely=.5, anchor=W)
#label the file name text box
tk.Label(mainscreen, text="Make an Entry:").place(relx=.5, rely=.035, anchor=CENTER)
tk.Label(mainscreen, text="Date: MMDDYYYY").place(relx=.5, rely=.07, anchor=CENTER)
#create main text box within the main frame
S = Scrollbar(mainframe)
T = Text(mainframe)
S.pack(side=RIGHT, fill=Y)
T.pack(side=LEFT, expand=True, fill=BOTH)
S.config(command=T.yview)
T.config(yscrollcommand=S.set)
#create second frame next to main frame to hold buttons
sideframe = tkinter.Frame(mainscreen)
sideframe.place(relwidth=.2, relheight=.75, relx=.7, rely=.5, anchor=W)
side_bar = Scrollbar(sideframe)
side_box = Text(sideframe)
side_bar.pack(side=RIGHT, fill=Y)
side_box.pack(side=LEFT, expand=True, fill=BOTH)
#create and load buttons
def loadbutton(item):
bfilename = item
bfileentry = open(bfilename, "r")
bquote = bfileentry.readlines()
T.delete("1.0",END)
T.insert(END,bquote)
#add buttons to box initially
entry_initate = [f for f in os.listdir(os.getcwd()) if f.endswith('.txt')]
for item in entry_initate:
mybutton = Button(side_box, text=item, command = lambda m = item: loadbutton(item))
mybutton.pack(fill=BOTH)
#refresh buttons when a new entry is saved
def refresh():
entry_raw = [f for f in os.listdir(os.getcwd()) if f.endswith('.txt')]
for item in entry_raw:
mybutton = Button(side_box, text=item, command = lambda m = item: loadbutton(item))
mybutton.pack(fill=BOTH)
list = side_box.slaves()
for l in list:
l.destroy()
for item in entry_raw:
mybutton = Button(side_box, text=item, command = lambda m = item: loadbutton(item))
mybutton.pack(fill=BOTH)
#Save and load entry buttons
Button(mainscreen, text="Save Entry", command=save_entry).place(relx=.5, rely=.9, anchor=CENTER)
Button(mainscreen, text="Load Entry", command=loadentry).place(relx=.5, rely=.95, anchor=CENTER)
mainscreen.mainloop()
I currently just have the side box just commented out, it was originally just a text box that had the file names listed in it.
Sorry if its a little messy, im still pretty new to python.
You should use variable loadfileb instead of button_press on .readlines() inside loadbutton(). Also use read() instead of readlines() and you need to insert the read content into text box.
def loadbutton(button_press):
with open(button_press, "r") as loadfileb:
quote = loadfileb.read()
T.delete('1.0', 'end')
T.insert('end', quote)
for item in entry_raw:
tk.Button(sideframe, text=item, command=lambda m=item: loadbutton(m)).pack()
Note that there are different way to initiate widgets, like tk.Entry(...), tkinter.Frame(...) and Button(...) in your code. So I think you have imported tkinter like below:
import tkinter
from tkinter import *
import tkinter as tk
Recommend to use import tkinter as tk only.

Tkinter entry widget - typed values gets copied to other entries

I am trying to create multiple Entry widgets on different pages of a notebook widget. However, when I type something in one Entry, it gets automatically copied to corresponding Entry on all pages. Please help. Here is my code.
import tkinter as tk
from tkinter import ttk
from tkinter import *
app = Tk()
nb = ttk.Notebook(app)
pages = []
canvas_left = []
canvas_right = []
entry_labels = []
entry_values = []
for i in range(3):
pages.append(ttk.Frame(nb))
canvas_left.append(tk.Canvas(pages[i], width=500, height=400, bd=0, highlightthickness=0))
canvas_left[i].pack(side=LEFT)
entry_values.append([])
for j in range(8):
entry_values[i].append(Entry(app, width=20, text="Window "+str(j+1), fg="white", bg="gray", font=("Helvetica", 12)))
canvas_left[i].create_window(125, 20 + j*35, anchor="w", window=entry_values[i][j])
nb.add(pages[i], text="Display "+(i+1).__str__())
nb.pack(side=TOP)
app.mainloop()
The text option of Entry widget is the same as textvariable option. So you use same variable name across the frames and they will be updated at the same time when one of them is updated.
Remove the text option from those Entry(...).

tkinter programmaticall creation of buttons

Hi I am trying to create a GUI with tkinter but I am unable to programmatically make the buttons show and/or behave properly.
This is the code I am using to create the buttons based on a a dict:
from tkinter import *
import sqlite3
from functools import partial
def query(x):
conn = sqlite3.connect("_db")
cur = conn.cursor()
q = cur.execute("SELECT text, option1, option2, option3 FROM tbl_1 WHERE id=?", [x, ])
actions = q.fetchone()
return actions
def pkey(identifier, label):
q = query(identifier)
buttons = {}
text = q[0]
label.config(text=text)
for entry in q:
if entry != text and entry is not None:
buttons[int(entry[0])] = entry[3:]
new_button = Button(root)
for k, v in buttons.items():
new_button.config(text=v, command=partial(pkey, k, label))
new_button.pack(fill=X)
print(buttons)
lbl.pack()
root = Tk()
root.geometry("300x200")
text_frame = LabelFrame(root, bg="#A66D4F")
text_frame.pack(fill=BOTH, expand=Y)
options_frame = LabelFrame(root, bg="cyan").pack(fill=X)
lbl = Label(text_frame)
pkey(1, lbl)
root.mainloop()
This creates the buttons within a frame, but when I click one of the buttons and they should replace the existing buttons all I get is a instance of the buttons on top of the existing one. Going from 3 buttons to 6 buttons.
Is there a way to replace the existing instance of the buttons with a new one after clicking?
Thanks
#BryanOakley Thank you for the reply. You were correct I was missing a destroy.
i have updated the code with the below and it is working properly now.
def destroy(frame, key, label):
frame.destroy()
frame = LabelFrame(self.parent, bg="cyan")
frame.pack(fill=X)
option_buttons(frame, key, label)
Thanks again

Categories