Related
I want to pass a button name to tkinter as a variable. This method works for Text fields, but not for buttons in my code.
I am building a gui app and I want to have a generic clear function that zaps a text entry field and resets a button from NORMAL to DiSABLED.
There are multiple buttons and fields, hence the desire to make this generic.
For the code I have, the buttons are present with the exception of clear all.
I am setting the variable w_button to the specific name of the (existing) button based on what is passed to the function.
def switch_clear(elem_type):
if elem_type == 'scn':
w_button = 'b_clear_scn'
clear_field = 'scn_file_entry'
print ('scenario')
elif elem_type == 'sol2':
w_button = 'b_clear_sol2'
clear_field = 'sol2_file_entry'
print ('sol2')
elif elem_type == 'mdl':
w_button = 'b_clear_mdlList'
clear_field = 'mdlList_file_entry'
print ('mdl')
elif elem_type == 'all':
print ('clear all TBD')
return()
if w_button["state"] == NORMAL:
clear_field.delete(0, END)
w_button["state"] = DISABLED
return()
Here's what happens:
C:\utils>my_frame3.py
scenario
Traceback (most recent call last):
File "C:\utils\my_frame3.py", line 127, in <module>
b_clear_scn = Button(first_frame, text = "Clear scenario", command = switch_clear('scn'), height = 2, state=DISABLED)
File "C:\utils\my_frame3.py", line 100, in switch_clear
if w_button["state"] == NORMAL:
TypeError: string indices must be integers
C:\utils>
I realize I could duplicate and push the clear operations into the if/elif statements, and I may have to live with that but - is it possible to reference buttons as variables? How can I do this?
Complete code as requested below. The preview is a mess despite using the code widget, but in my file lines are correctly formatted (notepad++). Tx
import os, sys
from tkinter import *
from tkinter import messagebox
from tkinter import filedialog
root2 = Tk()
root2.title('Model Processing')
root2.geometry('{}x{}'.format(512, 400))
# colors
color1 = 'light cyan'
color2 = 'gold'
color3 = 'RosyBrown1'
color4 = 'lavender'
color5 = 'linen'
bg_color = 'azure'
# number of items to process; until >1 OK is disabled; if >1 OK is enabled TBD
l_to_do = [] # items to process; scn, sol2, modelList, installed models
# functions/commands
def callback():
print ('A button was clicked.')
return;
def my_exit():
result = messagebox.askquestion("Cancel Model Processing", "Are you sure?", icon='warning')
if result == 'yes':
root2.quit()
else: # user changed mind
pass
def choose_import_file(str_ftype):
which_field = ''
which_clear_btn = ''
ftype = str_ftype
mdl_opts = {}
if ftype == 'scn':
title_msg = 'Choose a scenario file'
mdl_opts['filetypes'] = [('Supported types', ('.scn')),
('scenario files',('.scn'))]
which_field = scn_file_entry
which_clear_btn = 'b_clear_scn'
elif ftype == 'sol2':
title_msg = 'Choose a SOL2 file'
mdl_opts['filetypes'] = [('Supported types', ('.txt')),
('sol2 files',('.txt'))]
which_field = sol2_file_entry
elif ftype == 'mdllist':
title_msg = 'Choose a ModelList file'
print ('TBD: ModelList file')
file_input = filedialog.askopenfilename(title = title_msg, **mdl_opts)
if file_input == '':
print ('error or cancelled by user')
return
else:
f_inp_file = os.path.basename(file_input)
f_inp_file_base = str(file_input.split('.')[0])
f_inp_file_ext = str.lower(str(file_input.split('.')[1]))
f_inp_d_name = os.path.dirname(file_input)
print('File chosen:', f_inp_file_base)
# populate scenario file field
which_field.insert(INSERT,file_input)
which_clear_btn["state"] = NORMAL
# define appropriate clear button active
# define_clear_btn.configure(state = ACTIVE)
return
def switch_clear(elem_type):
if elem_type == 'scn':
if b_clear_scn["state"] == NORMAL:
scn_file_entry.delete(0, END)
b_clear_scn["state"] = DISABLED
elif elem_type == 'sol2':
f b_clear_sol2["state"] == NORMAL:
clear_field = 'sol2_file_entry'
b_clear_sol2["state"] = DISABLED
elif elem_type == 'mdl':
if b_clear_mdlList["state"] == NORMAL:
clear_field = 'mdlList_file_entry'
b_clear_mdlList["state"] = DISABLED
elif elem_type == 'all':
print ('clear all TBD')
return()
return()
# create all of the main containers
first_frame = Frame(root2, bg=color5, width = 512, height=90, pady=10)
second_frame = Frame(root2, bg=color5, width = 512, height=90, pady=10)
third_frame = Frame(root2, bg=color5, width=512, height=90, pady=10)
fourth_frame = Frame(root2, bg=color5, width = 512, height = 90, pady=10)
# layout all of the main containers
root2.grid_rowconfigure(3, weight=1)
root2.grid_rowconfigure(2, weight=1)
root2.grid_rowconfigure(1, weight=1)
root2.grid_columnconfigure(0, weight=1)
first_frame.grid(row=0, sticky="ew")
second_frame.grid(row=1, sticky="ew")
third_frame.grid(row=2, sticky="ew")
fourth_frame.grid(row = 3, sticky="e")
# create the widgets for the first frame
#scn_label = Label(first_frame, text = 'Scenario file')
scn_file_entry = Entry(first_frame, background=bg_color, width = 50)
b_choose_scn = Button(first_frame, text = "Choose a scenario..", command = lambda: choose_import_file('scn'), height = 2)
b_clear_scn = Button(first_frame, text = "Clear scenario", command = switch_clear('scn'), height = 2, state=DISABLED)
# layout the widgets in the first frame
#scn_label.grid(row = 0, column = 0, padx = (10,50), pady=5)
scn_file_entry.grid(row = 0, column = 1, padx = (10,10))
b_choose_scn.grid(row=0, column=0, padx = (10,10), sticky=W)
b_clear_scn.grid(row=2, column=0, padx = (10,10), sticky=W)
# second frame
# sol2_label = Label(second_frame, text = 'Sol2 file')
sol2_file_entry = Entry(second_frame, background=bg_color, width = 50)
b_choose_sol2 = Button(second_frame, text = "Choose SOL2 file..", command = lambda: choose_import_file('sol2'), height = 2)
b_clear_sol2 = Button(second_frame, text = "Clear SOL2", command = switch_clear('sol2'), height = 2, state=DISABLED)
# layout the widgets in the second frame
# sol2_label.grid(row = 0, column = 0, padx = (10,50), pady=5)
sol2_file_entry.grid(row = 0, column = 1, padx = (10,10), sticky=EW)
b_choose_sol2.grid(row=0, column=0, padx = (10,10), sticky=W)
b_clear_sol2.grid(row=2, column=0, padx = (10,10), sticky=W)
# third frame
# mdlList_label = Label(third_frame, text = 'ModelList.txt file')
mdlList_file_entry = Entry(third_frame, background=bg_color, width = 50)
b_choose_mdlList = Button(third_frame, text = "Choose ModelList.txt file..", command = callback, height = 2)
b_clear_mdlList = Button(third_frame, text = "Clear ModelList", command = callback, height = 2, state=DISABLED)
# layout the widgets in the third frame
#mdlList_label.grid(row = 0, column = 0, padx = (10,10), pady=5, sticky = 'ns')
mdlList_file_entry.grid(row = 0, column = 1, padx = (10,10), sticky=EW)
b_choose_mdlList.grid(row=0, column=0, padx = (10,10), sticky=W)
b_clear_mdlList.grid(row=2, column=0, padx = (10,10), sticky=W)
#####################################################################
# create bottom widgets
#####################################################################
clear_all = Button(fourth_frame, text='Clear All', padx = '5', command = callback, height = 2, state=DISABLED)
ok_btn = Button(fourth_frame, text='OK', padx = '5', command = callback, height = 2, state=DISABLED)
cancel_btn = Button(fourth_frame, text='Cancel', height = 2, padx = '12', command = my_exit)
#####################################################################
# layout the bottom widgets
#####################################################################
clear_all.grid(row = 0, column = 2, sticky = 'e')
ok_btn.grid(row = 0, column = 3, sticky = 'e')
cancel_btn.grid(row = 0, column = 4, sticky = 'e')
# commands/bindings
root2.mainloop()
I believe this is what you are trying to do. The below is fully commented with explanations. switch_clear becomes entirely unnecessary with this method. The buttons directly clear their corresponding entry in their command, and Entry validation takes care of the corresponding button state.
Note: I wrote all of this before you posted your full code
import tkinter as tk
root = tk.Tk()
root.geometry('400x400')
#toggle the state of buttons based on entry text length
def toggle_button(name, text):
global btn_switch
btn_switch[name]['state'] = 'normal' if len(text) else 'disabled'
return True
#to hold the buttons so they are easy to position
#just for this example
buttons = tk.Frame(root)
buttons.pack(side='top', anchor='nw')
#create a tcl wrapper for the validate command
vcmd = tk.Widget.register(root, toggle_button)
#mock-up of your entries ~ validate on key press. send widget name and full text to vcmd
scn_file_entry = tk.Entry(root, width=20)
scn_file_entry.configure(validate="key", validatecommand=(vcmd, '%W', '%P'))
scn_file_entry.pack(side='left', anchor='nw')
sol2_file_entry = tk.Entry(root, width=20)
sol2_file_entry.configure(validate="key", validatecommand=(vcmd, '%W', '%P'))
sol2_file_entry.pack(side='left', anchor='nw')
mdlList_file_entry = tk.Entry(root, width=20)
mdlList_file_entry.configure(validate="key", validatecommand=(vcmd, '%W', '%P'))
mdlList_file_entry.pack(side='left', anchor='nw')
#mock-up of your buttons ~ delete the entry text in a lambda and let entry validation handle the button state
b_clear_scn = tk.Button(buttons, text="scn", state='disabled')
b_clear_scn.configure(command=lambda: scn_file_entry.delete(0, 'end'))
b_clear_scn.pack(side='left', anchor='nw')
b_clear_sol2 = tk.Button(buttons, text="sol2", state='disabled')
b_clear_sol2.configure(command=lambda: sol2_file_entry.delete(0, 'end'))
b_clear_sol2.pack(side='left', anchor='nw')
b_clear_mdlList = tk.Button(buttons, text="mdl", state='disabled')
b_clear_mdlList.configure(command=lambda: mdlList_file_entry.delete(0, 'end'))
b_clear_mdlList.pack(side='left', anchor='nw')
#create a dictionary of 'widget name':corresponding button, for toggle_button to reference
btn_switch = {
f'{scn_file_entry}':b_clear_scn,
f'{sol2_file_entry}':b_clear_sol2,
f'{mdlList_file_entry}':b_clear_mdlList,
}
root.mainloop()
I have been messing around with Tkinter and embedded graphs and from a tutorial I found on the net, I have been able to make the following snippet of code work perfectly:
from tkinter import *
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg # NavigationToolbar2TkAgg
from matplotlib.figure import Figure
root = Tk()
# Typical matplotlib code
f = Figure(figsize = (4,3), dpi = 100)
a = f.add_subplot(111)
a.plot([1,2,4,3,5,7,6,7,8,8,9,6,7,8,7,5,6,4,3,4,3,2,1])
canvas = FigureCanvasTkAgg(f, root)
canvas.draw()
canvas.get_tk_widget().pack()
canvas._tkcanvas.pack()
root.mainloop()
The problem is I have not been able to incorporate the idea into a program I have been working on (Collatz Conjecture algorithm). What I'm trying to do is to plot a graph of the iteration data points but the graph does not display, notwithstanding the fact that the relevant portions of code in my script and the example snippet are identical. See my code below:
#!/usr/local/bin/env python3
# -*- coding: utf-8 -*-
from tkinter import *
from tkinter import messagebox
root=Tk()
root.title("Collatz Conjecture")
import textwrap
# Matplotlib imports
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg # NavigationToolbar2TkAgg
from matplotlib.figure import Figure
# Functions
lst = []
def collatz(num):
lst.clear()
while num != 1:
lst.append(num)
if num % 2 == 0:
num = int(num / 2)
else:
num = int(3 * num + 1)
def main(event):
num = int(input.get())
collatz(num)
output1.delete(1.0, END)
output1.insert(END, lst)
output2.delete(1.0, END)
output2.insert(END, "Number of iterations: " + str(len(lst)))
lbl1 = Label(root, width = 20, text = "Type in number\n & press Enter")
lbl1.grid(row = 1, column = 0, sticky = W)
lbl2 = Label(root, width = 40, text = "THE COLLATZ CONJECTURE")
lbl2.grid(row = 4, column = 0)
input = Entry(root, width = 20, bg = "light grey")
input.grid(row = 1, padx = 6, sticky = E)
input.get()
input.bind("<Return>", main)
# Matplotlib Graph - typical code
f = Figure(figsize = (4,3), dpi = 100) # Create the figure
a = f.add_subplot(111) # Add subplot
a.plot(lst)
# Plot data in background
# Canvas
canvas = FigureCanvasTkAgg(f, root)
canvas.draw()
canvas.get_tk_widget().grid(row = 6, column = 0)
canvas._tkcanvas.grid(row = 6, column = 0)
# canvas = Canvas(root, width= 350, height= 350, bg = "white")
# canvas.grid(row = 6, column = 0, padx = (5,5), pady = (5,5))
bt1 = Button(root, width = 10, text = "About")
bt1.grid(row = 7, column = 0, pady = (5,7))
output1 = Text(root, wrap = WORD, width = 50, height = 7, bg = "light grey") # Note word wrap attribute
output1.grid(row = 3, column = 0, padx = (5,1), sticky = W)
output2 = Text(root, width = 50, height = 1, bg = "white")
output2.grid(row = 2, column = 0, sticky = W)
def about():
messagebox.showinfo("About", "The Collatz conjecture states that if you pick any positive whole number, and if its even, you divide it by two and if its odd, you multiply it by three and add one, and if you repeat this procedure often enough, the number that you started with will eventually reduce to one and if you play this game for long enough, your friends will eventually stop calling to see if you want to hang out ")
btn1 = Button(root, text = "About", command = about)
btn1.grid(row = 7, column = 0, pady = (5,7))
root.mainloop()
I'm pretty sure its an indent problem and that I'm going to be very embarrassed when someone points out my novice mistake but I've tried moving the code around in seeminlgly every possible way but without success.
Could someone please have a look at it and tell me not only where I went wrong but more importantly, WHY its wrong.
The issue is fundamental. Your tkinter window loop keeps refreshing the plot canvas so you don't get to see the data. What you could do instead is take the canvas out of your window loop and stick it in the main function.
Obviously there are other/better solutions but I hope this one highlights the issue you are facing.
# -*- coding: utf-8 -*-
from tkinter import *
from tkinter import messagebox
root=Tk()
root.title("Collatz Conjecture")
import textwrap
# Matplotlib imports
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg # NavigationToolbar2TkAgg
from matplotlib.figure import Figure
# Functions
lst = []
def collatz(num):
lst.clear()
while num != 1:
lst.append(num)
if num % 2 == 0:
num = int(num / 2)
else:
num = int(3 * num + 1)
def main(event):
num = int(inp_ut.get())
collatz(num)
output1.delete(1.0, END)
output1.insert(END, lst)
output2.delete(1.0, END)
output2.insert(END, "Number of iterations: " + str(len(lst)))
# Generate the data and populate the canvas once.
f = Figure(figsize = (4,3), dpi = 100) # Create the figure
a = f.add_subplot(111) # Add subplot
a.plot(lst)
canvas = FigureCanvasTkAgg(f, root)
canvas.draw()
canvas.get_tk_widget().grid(row = 6, column = 0)
canvas._tkcanvas.grid(row = 6, column = 0)
lbl1 = Label(root, width = 20, text = "Type in number\n & press Enter")
lbl1.grid(row = 1, column = 0, sticky = W)
lbl2 = Label(root, width = 40, text = "THE COLLATZ CONJECTURE")
lbl2.grid(row = 4, column = 0)
inp_ut = Entry(root, width = 20, bg = "light grey")
inp_ut.grid(row = 1, padx = 6, sticky = E)
inp_ut.get()
inp_ut.bind("<Return>", main)
# Canvas
# canvas = Canvas(root, width= 350, height= 350, bg = "white")
# canvas.grid(row = 6, column = 0, padx = (5,5), pady = (5,5))
bt1 = Button(root, width = 10, text = "About")
bt1.grid(row = 7, column = 0, pady = (5,7))
output1 = Text(root, wrap = WORD, width = 50, height = 7, bg = "light grey") # Note word wrap attribute
output1.grid(row = 3, column = 0, padx = (5,1), sticky = W)
output2 = Text(root, width = 50, height = 1, bg = "white")
output2.grid(row = 2, column = 0, sticky = W)
def about():
messagebox.showinfo("About", "The Collatz conjecture states that if you pick any positive whole number, and if its even, you divide it by two and if its odd, you multiply it by three and add one, and if you repeat this procedure often enough, the number that you started with will eventually reduce to one and if you play this game for long enough, your friends will eventually stop calling to see if you want to hang out ")
btn1 = Button(root, text = "About", command = about)
btn1.grid(row = 7, column = 0, pady = (5,7))
root.mainloop()
I'm a 11th grader (5th year student) that just started studying Python programming. I am trying to make a GUI where I can chose what shape I want to draw with turtle and input the values needed to draw out the shape. I managed to do that with the following code (where I already did the functions of the turtle fractals and imported that file):
from tkinter import *
import turtlegraphics
from turtle import *
import math
#set up the window
root = Tk()
root.title('Turtle shapes')
root.geometry('300x200+100+100')
#make the interface
turtleLabel = Label(root, text = 'Turtle Fractals Generator')
turtleLabel.grid(row = 0, column =1, columnspan =2)
#order widgets
orderLabel = Label(root, text ='Order')
orderLabel.grid(row = 1, column =0)
orderStr = StringVar()
orderEntry = Entry(root, textvariable = orderStr)
orderEntry.grid(row = 1, column = 1, columnspan = 2)
#length widgets
lengthLabel = Label(root, text ='Length')
lengthLabel.grid(row = 2, column =0)
lengthStr = StringVar()
lengthEntry = Entry(root, textvariable = lengthStr)
lengthEntry.grid(row = 2, column = 1, columnspan = 2)
#button widgets
def clearF():
#Clear the entries
orderStr.set('')
lengthStr.set('')
return
#end def
clearButton = Button(root, text ='Clear', command = clearF)
clearButton.grid(row = 3, column =1)
def treeF():
order = int(orderStr.get())
length = float(lengthStr.get())
turtlegraphics.tree(order,length, pen)
return
#end def
treeButton = Button(root, text ='Tree', command = treeF)
treeButton.grid(row = 1, column =3)
#make a gasket button
def gasketF():
order = int(orderStr.get())
length = float(lengthStr.get())
turtlegraphics.gasket(order,length,pen)
return
#end def
gasButton = Button(root, text ='Gasket', command = gasketF)
gasButton.grid(row = 2, column =3)
#make a dandelion button
def dandelionF():
order = int(orderStr.get())
length = float(lengthStr.get())
turtlegraphics.tree4(order,length,pen)
return
#end def
danButton = Button(root, text ='Dandelion', command = dandelionF)
danButton.grid(row = 3, column =3)
#make flalke button
def kevinF():
order = int(orderStr.get())
length = float(lengthStr.get())
turtlegraphics.k(order,length,pen)
return
#end def
def flakeF():
order = int(orderStr.get())
length = float(lengthStr.get())
turtlegraphics.flake(order,length,pen)
return
#end def
flakeButton = Button(root, text ='Flake', command = flakeF)
flakeButton.grid(row = 4, column =3)
#make a screen and a pen
pen = Pen()
screen = Screen()
pen.speed(0)
pen.color('blue')
pen.width(3)
screen.bgcolor('white')
root.mainloop()
However, I want to try and put a list to chose the shape from rather than having several buttons. I don't understand much about lists due to the fact that I wasn't taught it yet but after doing research this is what I got:
'''
program gui to draw turtle fractals
'''
from tkinter import *
import turtlegraphics
from turtle import *
import math
#make a screen and a pen
pen = Pen()
def treeF():
order = int(orderStr.get())
length = float(lengthStr.get())
turtlegraphics.tree(order,length, pen)
return
#end def
#make a gasket button
def gasketF():
order = int(orderStr.get())
length = float(lengthStr.get())
turtlegraphics.gasket(order,length,pen)
return
#end def
#make a dandelion button
def dandelionF():
order = int(orderStr.get())
length = float(lengthStr.get())
turtlegraphics.tree4(order,length,pen)
return
#end def
#make flalke button
def kevinF():
order = int(orderStr.get())
length = float(lengthStr.get())
turtlegraphics.k(order,length,pen)
return
#end def
def flakeF():
order = int(orderStr.get())
length = float(lengthStr.get())
turtlegraphics.flake(order,length,pen)
return
#end def
screen = Screen()
pen.speed(0)
pen.color('blue')
pen.width(3)
screen.bgcolor('white')
#set up the window
root = Tk()
root.title('turtle shapes')
root.geometry('600x300+100+100')
#make the interface
turtleLabel = Label(root, text = 'Turtle Fractals Generator')
turtleLabel.grid(row = 0, column =1, columnspan =2)
#order widgets
orderLabel = Label(root, text ='Order')
orderLabel.grid(row = 1, column =0)
orderStr = StringVar()
orderEntry = Entry(root, textvariable = orderStr)
orderEntry.grid(row = 1, column = 1, columnspan = 2)
#length widgets
lengthLabel = Label(root, text ='Length')
lengthLabel.grid(row = 2, column =0)
lengthStr = StringVar()
lengthEntry = Entry(root, textvariable = lengthStr)
lengthEntry.grid(row = 2, column = 1, columnspan = 2)
#button widgets
def clearF():
#Clear the entries
orderStr.set('')
lengthStr.set('')
return
#end def
clearButton = Button(root, text ='Clear', command = clearF)
clearButton.grid(row = 3, column =1)
#list
def selection():
obj = nameList.curselection()[0]
if obj == 'tree':
command = treeF
return
if obj == 'dandelion':
command = dandelionF
return
if obj == 'flake':
command = flakeF
return
if obj == 'gasketF':
command = gasketF
return
#end if
#end def
#create list
listbox = Listbox(root,selectmode = SINGLE) #select mode is type of
selection
listButton= Button(root, text = 'chose fractal')
labelVar = StringVar()
nameLabel = Label(root, textvariable = labelVar)
nameLabel.grid(row = 2 , column = 7, columnspan = 2)
labelVar.set('choose a fractal')
names = ['tree','dandelion','flake','gasket']
nameList = Listbox(root)
for i in names:
nameList.insert(END, i)
nameList.grid(row = 4, column =7, columnspan = 2)
selectionButton = Button(root, text = 'draw', command = selection)
selectionButton.grid(row = 5, column = 7, columnspan = 2)
root.mainloop()
I know something is wrong with my code, but I can't tell what I did wrong. When I run my code I get no error whatsoever, but it does not draw the shape. In addition, the clear button does not do its function when clicked. How can I can I fix this?
Your immediate problem is how selection() works -- it was comparing numbers to strings and have the code necessary to execute any of the subprograms. I've reworked it below to get the behavior you desire. I've also made other changes and simplifications:
from tkinter import *
from turtle import Pen, Screen
import turtlegraphics
def treeF():
order = int(orderEntry.get())
length = float(lengthEntry.get())
turtlegraphics.tree(order, length, pen)
def dandelionF():
order = int(orderEntry.get())
length = float(lengthEntry.get())
turtlegraphics.tree4(order, length, pen)
def flakeF():
order = int(orderEntry.get())
length = float(lengthEntry.get())
turtlegraphics.flake(order, length, pen)
def gasketF():
order = int(orderEntry.get())
length = float(lengthEntry.get())
turtlegraphics.gasket(order, length, pen)
def kevinF():
order = int(orderEntry.get())
length = float(lengthEntry.get())
turtlegraphics.k(order, length, pen)
fractals = [('tree', treeF), ('dandelion', dandelionF), ('flake', flakeF), ('gasket', gasketF), ('kevin', kevinF)]
# make a screen and a pen
screen = Screen()
screen.bgcolor('white')
pen = Pen()
pen.speed('fastest')
pen.color('blue')
pen.width(3)
# set up the window
root = Tk()
root.title('turtle shapes')
root.geometry('600x400+100+100')
# make the interface
turtleLabel = Label(root, text='Turtle Fractals Generator')
turtleLabel.grid(row=0, column=1, columnspan=2)
# order widgets
orderLabel = Label(root, text='Order')
orderLabel.grid(row=1, column=0)
orderEntry = Entry(root)
orderEntry.grid(row=1, column=1, columnspan=2)
# length widgets
lengthLabel = Label(root, text='Length')
lengthLabel.grid(row=2, column=0)
lengthEntry = Entry(root)
lengthEntry.grid(row=2, column=1, columnspan=2)
# button widgets
def clearF():
# Clear the entries
orderEntry.delete(0, 'end')
lengthEntry.delete(0, 'end')
clearButton = Button(root, text='Clear', command=clearF)
clearButton.grid(row=3, column=1)
# list
def selection():
selections = nameList.curselection()
if selections:
selection = selections[0]
if selection < len(fractals):
name, definition = fractals[selection]
definition()
# create list
listbox = Listbox(root, selectmode=SINGLE) # select mode is type of selection
listButton = Button(root, text='chose fractal')
labelVar = StringVar()
nameLabel = Label(root, textvariable=labelVar)
nameLabel.grid(row=2, column=7, columnspan=2)
labelVar.set('choose a fractal')
nameList = Listbox(root)
for name, definition in fractals:
nameList.insert(END, name)
nameList.grid(row=4, column=7, columnspan=2)
selectionButton = Button(root, text='Draw', command=selection)
selectionButton.grid(row=5, column=7, columnspan=2)
root.mainloop()
General comments about your code:
Find and follow a good Python coding style -- it makes understanding your code more difficult when you invent your own coding "style".
This isn't the correct way to integrate turtle with tkinter. Search StackOverflow, or the turtle documentation, for RawTurtle and TurtleScreen, the classes you use instead of Turtle (aka Pen) and Screen when embedding in an existing Tk window structure.
I am new in creating GUI. I am doing it in Python with Tkinter. In my program I calculate following characteristics
def my_myfunction():
my code ...
print("Centroid:", centroid_x, centroid_y)
print("Area:", area)
print("Angle:", angle)
I would like to ask for any help/tips how to display those values in GUI window or how to save them in .txt file so that I can call them in my GUI
Thanks in advance
Tkinter is easy and an easy way to do a GUI, but sometimes it can be frustrating. But you should have read the docs before.
However, you can do in this way.
from tkinter import *
yourData = "My text here"
root = Tk()
frame = Frame(root, width=100, height=100)
frame.pack()
lab = Label(frame,text=yourData)
lab.pack()
root.mainloop()
There are several ways to display the results of any operation in tkiner.
You can use Label, Entry, Text, or even pop up messages boxes. There are some other options but these will probably be what you are looking for.
Take a look at the below example.
I have a simple adding program that will take 2 numbers and add them together. It will display the results in each kind of field you can use as an output in tkinter.
import tkinter as tk
from tkinter import messagebox
class App(tk.Frame):
def __init__(self, master):
self.master = master
lbl1 = tk.Label(self.master, text = "Enter 2 numbers to be added \ntogether and click submit")
lbl1.grid(row = 0, column = 0, columnspan = 3)
self.entry1 = tk.Entry(self.master, width = 5)
self.entry1.grid(row = 1, column = 0)
self.lbl2 = tk.Label(self.master, text = "+")
self.lbl2.grid(row = 1, column = 1)
self.entry2 = tk.Entry(self.master, width = 5)
self.entry2.grid(row = 1, column = 2)
btn1 = tk.Button(self.master, text = "Submit", command = self.add_numbers)
btn1.grid(row = 2, column = 1)
self.lbl3 = tk.Label(self.master, text = "Sum = ")
self.lbl3.grid(row = 3, column = 1)
self.entry3 = tk.Entry(self.master, width = 10)
self.entry3.grid(row = 4, column = 1)
self.text1 = tk.Text(self.master, height = 1, width = 10)
self.text1.grid(row = 5, column = 1)
def add_numbers(self):
x = self.entry1.get()
y = self.entry2.get()
if x != "" and y != "":
sumxy = int(x) + int(y)
self.lbl3.config(text = "Sum = {}".format(sumxy))
self.entry3.delete(0, "end")
self.entry3.insert(0, sumxy)
self.text1.delete(1.0, "end")
self.text1.insert(1.0, sumxy)
messagebox.showinfo("Sum of {} and {}".format(x,y),
"Sum of {} and {} = {}".format(x, y, sumxy))
if __name__ == "__main__":
root = tk.Tk()
myapp = App(root)
root.mainloop()
I am trying to set up validation on text entry boxes. Three of the boxes need to only accept integers and one text as a postcode. I am not sure whether to do this in a function previously defined or when the entry boxes are created. Also how would i make the values from the text entry boxes be accessable in the function QuoteCreation. All my code is below.
from tkinter import *
class quote():
def __init__(self, master):
self.master=master
self.master.title("Quote Screen")
self.master.geometry("2100x1400")
self.master.configure(background = "white")
self.Borras = PhotoImage(file = "Borras.Logo.2.gif") #sets up image
self.Borras.image = self.Borras
self.BorrasLabel = Label(self.master, image = self.Borras, bg = "white")#puts image onto label
self.BorrasLabel.place(anchor=NW)
self.Title = Label(self.master, text = "New Quote", font = ("calibri", 20), bg = "White")
self.Title.place(x=650, y = 10)
self.SubmitButton = PhotoImage(file = "Submit.Button.gif") #sets up image
self.SubmitButton.image = self.SubmitButton
self.SubmitButtonLabel = Button(self.master, image = self.SubmitButton, bg = "white", command= self.QuoteCreation)#puts image onto a button
self.SubmitButtonLabel.place(x=900, y=290)
PostCodeVar = StringVar()
PostCodeEntry = Entry(master,width=50, font=20, textvariable=PostCodeVar)
PostCodeEntry.place(x = 20, y = 150)
PostCodeVar.set("Please enter the Post Code")
PostCodeValue = PostCodeVar.get()
HeightVar = StringVar()
HeightEntry = Entry(master, width=50, font=20, textvariable=HeightVar)
HeightEntry.place(x = 20, y = 220)
HeightVar.set("Please enter the Height")
HeightValue = HeightVar.get()
LengthVar = StringVar()
LengthEntry = Entry(master, width=50, font=20, textvariable=LengthVar)
LengthEntry.place(x = 20, y = 290)
LengthVar.set("Please enter the Length")
LengthValue = LengthVar.get()
PitchVar = StringVar()
PitchEntry = Entry(master, width=50, font=20, textvariable=PitchVar)
PitchEntry.place(x = 20, y = 360)
PitchVar.set("Please enter the Pitch")
PitchValue = PitchVar.get()
RiseVar = StringVar()
RiseEntry = Entry(master, width=50, font=20, textvariable=RiseVar)
RiseEntry.place(x = 20, y = 430)
RiseVar.set("Please enter the Rise")
RiseValue = RiseVar.get()
self.SubmitButton = PhotoImage(file = "Submit.Button.gif")
self.SubmitButton.image = self.SubmitButton
self.SubmitButtonLabel = Button(self.master, image = self.SubmitButton, bg = "white", command= self.QuoteCreation)#puts image onto a button
self.SubmitButtonLabel.place(x=900, y=290)
def on_button(self):
print(self.entry.get())
def QuoteCreation(self):
print(' ')
def quitWindow(self):
self.master.destroy()
def backToWelcome(self):
self.master.destroy()
You would set up separate functions to deal with the validation, when the submit button is pressed.
So, as an example, your submit button may look a bit like this:
submitButton = Button(master, text="Submit", command=validation)
The validation, in your case would then want to carry out these checks:
def validation():
postcode = PostCodeVar.get()
length = LengthVar.get()
pitch = PitchVar.get()
rise = RiseVar.get()
if postcodeCheck(postcode) == True and length.isdigit() == True and pitch.isdigit() == True and rise.isdigit() == True:
#carry out chosen process
In your case, you can try setting the postcode, length, pitch and height variables before calling the function, and setting them as global. The postcode should be created, and if it is okay, the function should then:
return True
...so it matches the outcome of the if statement.
I hope this is what you were looking for, and can adapt the example to your specific problem!