Related
I am trying to make a Python program that asks the user for a number then reverses it using recursion. My attempt is below, but my code gives me TypeError: unsupported operand type(s) for //: 'Entry' and 'int' - any ideas?
from tkinter import *
def reverseInteger(n, r):
if n==0:
return r
else:
return reverseInteger(n//10, r*10 + n%10)
window = Tk()
window.title("Reverse Integer")
frame1 = Frame(window)
frame1.pack()
number = StringVar()
numEntry = Entry(frame1, textvariable=number)
btGetName = Button(frame1, text = "Calculate", command = reverseInteger(numEntry, 0))
label3 = Label(frame1)
numEntry.grid(row = 1, column = 1)
btGetName.grid(row = 1, column = 2)
label3.grid(row = 2, column = 1, sticky="w")
window.mainloop()
Your recursive function is perfectly fine but there are several other
problems in your code.
The main one is that the command parameter of Button must be the
function that will be called when the user presses on the buttton. In
your code, command is set to the return value of reverseInteger
which is an int. So there is a problem here.
Also it seems to me that you want to put the result of your
calculation in label3 so your StringVar should be attached to it
and not to numEntry.
So here is a version that seems ok to me:
from tkinter import *
def reverseInteger(n, r):
if n==0:
return r
else:
return reverseInteger(n//10, r*10 + n%10)
def reverse(): # called when the user click on the button
value = reverseInteger(int(numEntry.get()), 0)
number.set(value) # change the text of the label
window = Tk()
window.title("Reverse Integer")
frame1 = Frame(window)
frame1.pack()
number = StringVar()
numEntry = Entry(frame1)
btGetName = Button(frame1, text = "Calculate", command = reverse)
label3 = Label(frame1, textvariable=number)
numEntry.grid(row = 1, column = 1)
btGetName.grid(row = 1, column = 2)
label3.grid(row = 2, column = 1, sticky="w")
window.mainloop()
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'm new here and new in PY, I'm trying to write a simple GUI with Tkinter (py 2.7.10) where there are two buttons: the first one starts printing stuff and the second one quits.
I'd like the first button to change the text after the first click from "START" to "STOP" and of course to stop the loop, so I can pause instead of closing and reopen every time.
Also feel free to give any advice to improve it :)
I hope it's clear, here is the code.
import random, time
from Tkinter import *
START, STOP = "start", "stop"
class AppBase:
def __init__(self, root):
self.myRoot = root
self.frame1 = Frame(root)
self.frame1["background"] = "LightSteelBlue"
self.frame1.pack()
self.delay = Scale(self.frame1, from_=100, to=0)
self.delay.pack(side = LEFT, padx=5, pady=15)
self.label0 = Label(self.frame1, text="Notes", background="LightSteelBlue", foreground="darkblue")
self.label0.pack(padx=5, pady=15)
self.label1 = Label(self.frame1, text="NOTE", background="LightSteelBlue", foreground="SteelBlue")
self.label1.pack(padx=30, pady=10)
self.label2 = Label(self.frame1, text="STRING", background="LightSteelBlue", foreground="SteelBlue")
self.label2.pack(padx=30, pady=7)
self.label3 = Label(self.frame1, text="FINGER", background="LightSteelBlue", foreground="SteelBlue")
self.label3.pack(padx=30, pady=7)
self.puls1 = Button(self.frame1)
self.puls1.configure(text = "Start", background = "CadetBlue", borderwidth = 3, command = self.generate_notes)
self.puls1.pack(side = LEFT, padx=5, pady=15)
self.puls2 = Button(self.frame1)
self.puls2.configure(text = "Exit", background = "CadetBlue", borderwidth = 3)
self.puls2.pack(side = LEFT, padx=5, pady=15)
self.puls2.bind("<Button-1>", self.close_all)
self.notes_process=1
def generate_notes(self):
self.notes = ['DO','DO#','RE','RE#','MI','MI#','FA','FA#','SOL','SOL#','LA','LA#','SI','SI#']
self.strings = ['1^ corda','2^ corda','3^ corda','4^ corda','5^ corda','6^ corda']
self.fingers = ['Indice','Medio','Anulare','Mignolo']
self.note = random.randrange(0, len(self.notes))
self.string = random.randrange(0, len(self.strings))
self.finger = random.randrange(0, len(self.fingers))
self.timer=self.delay.get()
if self.timer == '':
self.timer = 500
elif int(self.timer) < 1:
self.timer = 500
else:
self.timer=int(self.delay.get())*100
self.label1["text"] = self.notes[self.note]
self.label2["text"] = self.strings[self.string]
self.label3["text"] = self.fingers[self.finger]
self.myRoot.after(self.timer, self.generate_notes)
def close_all(self, evento):
self.myRoot.destroy()
self.myRoot.quit()
def main():
master = Tk()
master.title("Notes")
appBase = AppBase(master)
master.mainloop()
main()
I found a solution, thanks to everybody for their help and of course if you want to keep talking about different and (sure) better way to do, you are more than welcome!
Here my solution:
step 1, add this to the button:
self.puls1.bind("<Button-1>", self.puls1Press1)
step 2, add a new variable:
self.active = True
step 3, create a new function:
def puls1Press1(self, evento):
if self.puls1["text"] == "Start":
self.puls1["text"] = "Stop"
self.active = True
else:
self.puls1["text"] = "Start"
self.active = False
step 4, modify the function that I want to stop:
def generate_notes(self):
if self.active == True:
[some code]
[some code]
else:
return
You need to save the return value of the after, so that you can use it when you cancel the loop using after_cancel(the_return_value_of_after).
def generate_notes(self):
if self.puls1['text'] == 'Start':
# Change button text to Stop, and call the original loop function
self.puls1['text'] = 'Stop'
self._generate_notes()
else:
# cancel timer
self.puls1['text'] = 'Start'
self.myRoot.after_cancel(self.timer_handle)
def _generate_notes(self):
...(old codes)..
self.timer_handle = self.myRoot.after(self.timer, self._generate_notes)
StringVar() from variable class can be used to update text as well as a looping condition. Example code:
ButtonText=StringVar()
ButtonText.set("START")
button1 = tkinter.Button(self.frame1, text=ButtonText, width=25, command= lambda: do_something(ButtonText))
Elsewhere where you are looping check for the value of the variable:
My_Loop():
if(ButtonText.get()=="STOP"):
break
else:
#some print statements
Now in function do_something(ButtonText), which will be called after each button press, change the string to "STOP" or vice versa :
do_something(ButtonText):
if(ButtonText.get()=="START): #Change text
ButtonText.set("STOP")
else:
ButtonText.set("START") #Change text and call function to loop again
My_Loop()
Hope this helps.
I really need help with some code. I don't expect you to write it for me, since it is a school project, but I am just really lost and need help.
The code I am writing is some sort of production system.
It doesn't need to actually be able to send a task anywhere, since this is just an imagined scenario.
The code has to consist of three files: data.py, model.py and gui.py.
Gui can access the two other files
Data can only access model
Model can't access either of the other two.
My teacher had written some of the code witch I have continued on. Some of the text is in danish, but most comments are in English.
The code is as follows.
data.py
from model import *
class Data(object):
def __init__(self):
self.units = []
self.finished_tasks = []
def __str__(self):
result = "These tasks have been finished: "
for i in self.finished_tasks:
result += str(i)
return result
def task_done(self, unit):
done_task = unit.task_done()
if done_task != None:
#TODO: add to list of finished tasks
pass
def add_task(self, name, amount, unit):
s = Springroll_task(name, amount)
unit.add_to_queue(s)
def read_from_database(self):#doesn't actually read from db..
self.units.append(Production_unit("maskine1"))
self.units.append(Production_unit("maskine2"))
self.add_task("Miniruller", 100, self.units[0])
self.add_task("Maxiruller", 200, self.units[0])
self.add_task("HowIRoll", 3000, self.units[0])
self.add_task("RulleMarie", 40, self.units[1])
self.add_task("Rullesten", 500, self.units[1])
self.add_task("Toiletpapirsruller", 6000, self.units[1])
model.py
class Springroll_task(object):
def __init__(self, name, amount):
self.name = name
self.amount = amount
def __str__(self):
return self.name + " " + str(self.amount)
class Production_unit(object):
def __init__(self, amount={}, name={},):
#name of the production unit
self.name = name
self.amount = amount
#the current task
self.current_task = None
#the tasks in the queue
self.springroll_queue = []
#the size of the queue
self.queue_size = 0
def __str__(self):
#TODO
return self.name + " " + str(self.amount)
def add_to_queue(self, task={}):
if self.current_task == None:
self.current_task = task
else:
self.springroll_queue.append(task)
self.queue_size += 1
#remember to update queue_size
pass
def task_done(self):
#TODO: remember the old current task.
#Set the current task to be the first in the queue (and remove from queue)
# - if there is a task in the queue.
#return the old current task.
#remember to update queue_size
self.queue_size -= 1
pass
gui.py
from tkinter import *
from model import *
from data import Data
class Application(Frame):
def __init__(self, master, unit):
self.mod = Production_unit()
super(Application, self).__init__(master)
self.grid()
self.unit = unit
self.create_widgets()
def create_widgets(self):
self.unit_name_lbl = Label(self, text = self.unit.name)
self.unit_name_lbl.grid(row = 0, column = 0, columnspan = 2, sticky = W)
self.cur_prod_lbl = Label(self, text = "produktion nu: ")
self.cur_prod_lbl.grid(row = 1, column = 0, columnspan = 2, sticky = W)
self.prod_lbl = Label(self, text = "produkt")
self.prod_lbl.grid(row = 2, column = 0, sticky = W)
self.amount_lbl = Label(self, text = "antal")
self.amount_lbl.grid(row = 2, column = 1, sticky = W)
#Label for production now
self.amount1_lbl = Label(self, text = " ", bg ="red")
self.amount1_lbl.grid(row = 3, column = 0, sticky = W)
self.amount2_lbl = Label(self, text = " ", bg ="red")
self.amount2_lbl.grid(row = 3, column = 1, sticky = W)
#Button for task finished
self.finished_but = Button(self, text = "Opgave afsluttet", bg ="pink", command=self.mod.task_done)
self.finished_but.grid(row = 3, column = 2, sticky = W)
#Label for queue
self.queue_lbl = Label(self, text = "Kø")
self.queue_lbl.grid(row = 4, column = 0, sticky = W)
#Label for production queue
for i in range(0,3):
self.name_lbl =Label(self, text = self.mod.springroll_queue, bg="red", width= 6)
self.name_lbl.grid(row = 5+i, sticky = W)
for j in range(0,3):
self.qt_lbl =Label(self, text = self.mod.springroll_queue, bg="red", width= 4)
self.qt_lbl.grid(row = 5+j, column = 1)
self.new_lbl = Label(self, text = "Ny")
self.new_lbl.grid(row = 10, column = 0, sticky = W)
#Entry for entries
self.eq1_ent = Entry(self, text = "", width=6)
self.entry_name = self.eq1_ent.get()
self.eq1_ent.grid(row = 11, sticky = W)
self.ea1_ent = Entry(self, text = "", width=4)
self.ea1_ent.grid(row = 11, column = 1, sticky = W)
#Button for add to queue
self.add_but = Button(self, text = "Tilføj til kø", bg ="pink", command=self.mod.add_to_queue(self.ea1_ent.get()))
self.add_but.grid(row = 11, column = 2, sticky = W)
def done(self):
d.task_done(self.unit)
self.redraw()
def add(self):
n = "Nyt navn" #read from gui
a = "Nyt antal" #read from gui
d.add_task(n, a, unit)
self.redraw()
def redraw(self):
#TODO
pass
# main
root = Tk()
root.title("Daloon")
root.geometry("300x300")
d = Data()
d.read_from_database()
p = d.units[0]
app = Application(root, p)
root.mainloop()
So it currently looks like this:
What I need to be able to do is to take an input in the bottom two entry widgets and put them in one of the 4 label widgets above, beginning from the top and then in the queue afterwards, this should happen when I press the button add_but, which seems to be gone currently.
After that I need the task stored in the data file when the "Opgave afsluttet" button is pressed.
I really hope someone is able to help me!
I edited it with some suggestions, and am calling the right self.eq1_ent.get() now, I think. I dont get any error any longer, now I just don't really know how to make it do what I want.
Edit 2: I am slowly getting some stuff, so i have made changes in the model.py and gui.py...
It looks like this now:
self.eq1 is not defined. you have self.q1_lbl and self.eq1_ent.
To access the label use self.q1_lbl.
To be able to set text to your label create them as following:
self.var = StringVar()
self.unit_name_lbl = Label(self, textvariable=self.var)
For example, from redraw() you can set 'text' to self.unit_name_lbl like this : self.var.set('text').
Check if you missed self in d.add_task(n, a, unit)
When you do command=mod.add_to_queue(self.ea1_ent.get()) the mod.add_to_queue function will be called directly, if you want to pass argument to this function when user press the button, you can use lambda:
command=lambda: mod.add_to_queue(self.ea1_ent.get)
I am using a mix of Tkinter and graphics.py (a wrapper on Tkinter) to create a fairly basic integrator (find the area under a graph) with a GUI. As of now, the main "control panel" for the integrator is separate from the actual graph (which is made by using graphics.py). I am using Tkinter's Radiobutton() for the choice selection of the integration type (Left Rectangular, Right Rectangular, Trapezoidal, or Simpson's Approximation).
My problem is that I am unable to get the output from the radiobuttons. I was using the example from TutorialsPoint: Tkinter Radiobutton.
Here is my code:
class FunctionInput:
def __init__(self, master, window, items):
self.window = window
self.items = items
self.runProgram = True
self.typeChoice = tk.StringVar()
self.frame = tk.Frame(master)
self.typeFrame = tk.Frame(self.frame)
self.quitButton = tk.Button(self.frame, text = 'Quit', command = self.frame.quit)
self.optLabel = tk.Label(self.frame, text = 'Type of Approximation: ')
self.optL = tk.Radiobutton(self.typeFrame, text = 'Left Rectangular', variable = self.typeChoice, value = 'l')
self.optR = tk.Radiobutton(self.typeFrame, text = 'Right Rectangular', variable = self.typeChoice, value = 'r')
self.optT = tk.Radiobutton(self.typeFrame, text = 'Trapezoidal', variable = self.typeChoice, value = 't')
self.optS = tk.Radiobutton(self.typeFrame, text = 'Simpsons Rule', variable = self.typeChoice, value = 's')
self.optL.grid(row = 1, column = 1, padx = 5, pady = 5)
self.optR.grid(row = 1, column = 2, padx = 5, pady = 5)
self.optT.grid(row = 2, column = 1, padx = 5, pady = 5)
self.optS.grid(row = 2, column = 2, padx = 5, pady = 5)
self.optLabel.grid(row = 4)
self.typeFrame.grid(row = 5)
self.quitButton.grid(row = 6)
# there were numerous other widgets and frames, but I only included the relevant ones
self.frame.grid()
def getInput(self):
type_integration = self.typeChoice.get()
self.frame.quit()
return type_integration
def main():
# some other code, win and axisLabels are defined prior to this
root = tk.Tk(className = ' Function Grapher')
app = FunctionInput(root, win, axisLabels)
root.rowconfigure(0, weight = 1)
root.columnconfigure(0, weight = 1)
root.mainloop() # there is a button to exit the mainloop in my GUI
typeIntegration = app.getInput()
print typeIntegration # trying to debug it
if __name__ == '__main__': main()
However, it doesn't not print the variable. It prints an empty string, so execution is not a problem. root.mainloop() does not get stuck in an infinite loop, because I have a button in my GUI (not shown here because it is irrelevant) that exits it. An error is not raised, so I'm guessing that the issue is with setting the option to the variable. Any help is greatly appreciated.
Also, on a side note, whenever I run the program, the 'Right Rectangular', 'Trapezoidal', and 'Simpson's Rule' radiobuttons are grayed out, like such:
This grayness goes away if I click on one of the radiobuttons, but until then, it stays. If there is some way to fix this, please let me know.
Thanks!
I haven't seen the part of the exit button, but your code does something like this:
Starts the mainloop
The event handler of the exit button calls root.quit()
In getInput, retrieves the value and calls self.frame.quit()
Calling Tkinter functions after the mainloop may lead to problems like this, so you should get the value of the StringVar first and then exit the GUI loop. This is a working example based on your code:
import Tkinter as tk
class App():
def __init__(self, master):
self.master = master
self.type_integration = None
self.typeChoice = tk.StringVar()
self.typeChoice.set(None) # This fixes the grayness of the radio buttons!
self.typeFrame = tk.Frame(master)
OPTIONS = [('Left Rectangular', 'l'),
('Right Rectangular', 'r'),
('Trapezoidal', 't'),
('Simpsons Rule', 's')]
for text, value in OPTIONS:
tk.Radiobutton(self.typeFrame, text=text, variable=self.typeChoice, value=value).pack()
tk.Button(self.typeFrame, text="Exit", command=self.exit).pack()
self.typeFrame.pack()
def exit(self):
self.type_integration = self.typeChoice.get()
self.master.destroy() # self.master.quit() freezes the GUI
def getinput(self):
return self.type_integration
master = tk.Tk()
app = App(master)
tk.mainloop()
print app.getinput()
The problem was that since I was using multiple other widgets, I had to set StringVar()s master parameter as self.typeFrame:
class FunctionInput:
def __init__(self, master, window, items):
self.window = window
self.items = items
self.runProgram = True
self.frame = tk.Frame(master)
self.typeFrame = tk.Frame(self.frame)
self.typeChoice = tk.StringVar(self.typeFrame)
self.quitButton = tk.Button(self.frame, text = 'Quit', command = self.frame.quit)
self.optLabel = tk.Label(self.frame, text = 'Type of Approximation: ')
self.optL = tk.Radiobutton(self.typeFrame, text = 'Left Rectangular', variable = self.typeChoice, value = 'l')
self.optR = tk.Radiobutton(self.typeFrame, text = 'Right Rectangular', variable = self.typeChoice, value = 'r')
self.optT = tk.Radiobutton(self.typeFrame, text = 'Trapezoidal', variable = self.typeChoice, value = 't')
self.optS = tk.Radiobutton(self.typeFrame, text = 'Simpsons Rule', variable = self.typeChoice, value = 's')
self.optL.grid(row = 1, column = 1, padx = 5, pady = 5)
self.optR.grid(row = 1, column = 2, padx = 5, pady = 5)
self.optT.grid(row = 2, column = 1, padx = 5, pady = 5)
self.optS.grid(row = 2, column = 2, padx = 5, pady = 5)
self.optLabel.grid(row = 4)
self.typeFrame.grid(row = 5)
self.quitButton.grid(row = 6)
# there were numerous other widgets and frames, but I only included the relevant ones
self.frame.grid()
def getInput(self):
type_integration = self.typeChoice.get()
self.frame.quit()
return type_integration
def main():
# some other code, win and axisLabels are defined prior to this
root = tk.Tk(className = ' Function Grapher')
app = FunctionInput(root, win, axisLabels)
root.rowconfigure(0, weight = 1)
root.columnconfigure(0, weight = 1)
root.mainloop() # there is a button to exit the mainloop in my GUI
print app.getInput()
if __name__ == '__main__': main()
Also, as #A. Rodas said, to get rid of the grayness, I did:
self.typeFrame = tk.Frame(self.frame)
self.typeChoice = tk.StringVar(self.typeFrame)
self.typeChoice.set(None)