hey guys first post and what not so hi. anyway trying to make a scientific calculator with tkinter and im not very good with it(and python its my second proper assignment). anyway most of the code will probably be wrong but im just trying to take it one step at a time in particular im concerned about the function add. im calling it via the button however i want to pass the do function a +. this in turn creating an array i can calculate from. it keeps erroring and i dont know how to fix it. its really annoying me now so if someone could help out would be much appreciated
from tkinter import*
from operator import*
class App:
def __init__(self,master):#is the master for the button widgets
frame=Frame(master)
frame.pack()
self.addition = Button(frame, text="+", command=self.add)#when clicked sends a call back for a +
self.addition.pack()
def add(Y):
do("+")
def do(X):#will hopefully colaborate all of the inputs
cont, i = True, 0
store=["+","1","+","2","3","4"]
for i in range(5):
X=store[0+i]
print(store[0+i])
cont = False
if cont == False:
print(eval_binary_expr(*(store[:].split())))
def get_operator_fn(op):#allows the array to be split to find the operators
return {
'+' : add,
'-' : sub,
'*' : mul,
'/' : truediv,
}[op]
def eval_binary_expr(op1, num1, op2, num2):
store[1],store[3] = int(num1), int(num2)
return get_operator_fn(op2)(num1, num2)
root=Tk()
app=App(root)
root.mainloop()#runs programme
Generally speaking, every method in a class should take self as its first argument. The name self is just a convention. It is not a keyword in Python. However, when you call a method such as obj.add(...), the first argument sent to the method is the instance obj. It is a convention to call that instance self in the method definition. So all your methods need to be modified to include self as the first argument:
class App:
def __init__(self, master):#is the master for the button widgets
frame=Frame(master)
frame.pack()
self.addition = Button(frame, text="+", command=self.add)#when clicked sends a call back for a +
self.addition.pack()
def add(self):
self.do("+")
def do(self, X):
...
Note that when you call self.do("+"), inside the method do, X will be bound to "+". Later on in that method I see
X=store[0+i]
which will rebind X to the value store[i]. I don't know what you are trying to do here, but be aware that doing so means you've just lost the "+" value that was just passed in.
Related
Good Day,
I'm new to this forum (and quite new to programming), so I hope my question is properly formulated.
I've been trying to create a GUI in python using tkinter, and I want to have two buttons calling methods of two different classes. One method is defining an integer, the second one is reporting content. I'd have a list of objects of the latter class, and I want to choose the right instance by the integer. Here's a MWE:
import tkinter as tk
class data:
def __init__(self, content):
self.content = content
def report(self):
print("This is reported as self.content:" + str(self.content)) #This doesnt report the correct value for some reason?
print("The Class does register the correct idx:" + str(Selector.idx))
print("Using the Dict the correct value can be returned:" + str(vocables[Selector.idx].content))
class increment:
def __init__(self):
self.idx = 0
def increase(self):
self.idx += 1
print(self.idx)
vocables[self.idx].report()
root = tk.Tk()
Selector = increment()
vocables = []
for id in range(10):
vocables.append(data(id))
# print(vocables[id].content)
CheckVocable = tk.Button(root, text="Report", command=vocables[Selector.idx].report)
CheckVocable.pack()
NextVocable = tk.Button(root, text="Increase Index", command=Selector.increase)
NextVocable.pack()
root.mainloop()
I do not understand why the print of line 8 always reports the value of the first item in the list (vocabules[0] in this instance) instead of my desired value, which is returned in all other print cases. Am I messing up the work with classes or is the button behavior confusing me?
Thanks in advance!
I'm working hard to solve this problem, can someone help me ?
There is what I mean by 'set' an argument:
from tkinter import *
window = Tk()
I=1
def add():
global I
menu1.add_command(label=I, command=lambda:Text(I))
I=I+1
def Text(I):
print(I)
menubar = Menu(window)
menu1 = Menu(menubar, tearoff=0)
menu1.add_command(label="Add", command=add)
menu1.add_separator()
menu1.add_command(label="Quit", command=window.quit)
menubar.add_cascade(label="Files", menu=menu1)
window.config(menu=menubar)
window.mainloop()
I want when we click on add and after on '1' it print '1', and when we add '2' and click on it, it print '2' but it always print the value of I, how can I set the argument by
menu1.add_command(label=I, command=lambda:Text(1))
for exemple ?
I don't know if I'm clear but I don't know how explain it !
Change your Text function to be a closure:
def Text(I):
def inner():
print(I)
return inner
Then change your add function to be this:
def add():
global I
text = Text(I)
menu1.add_command(label=I, command=text)
I=I+1
This will save the I in the text variable. The text variable is actually a function, inner, that will print I when called.
Or you could make your closure inline if you wanted to use the Text function somewhere else:
import functools
...
menu1.add_command(label=I, command=functools.partial(Text, i))
I think your problem is the lambda:Text(I). In this case, you have created a closure, but the closure knows I to be a global and is evaluating it at a later date.
You probably want to immediately evaluate Text(I) and use that as your result:
texti = Text(I) # Immediate evaluation
menu1.add_command(label=I, command=lambda:texti) # Return prior value of "I"
The idea of this code is, the user presses the first button and enters what they want, then they press the second button and it prints it out. Can someone please tell me why my return statement is not working? It says that 'variable' is not defined. Thanks in advance for taking the time to read my question.
from tkinter import*
def fun():
variable = input('Enter Here:')
return variable
def fun_2():
print(variable)
window = Tk()
button = Button(text = 'Button', command = fun )
button2 = Button(text = 'Button2', command = fun_2 )
button.pack()
button2.pack()
window.mainloop()
In python when you create a variable inside of a function, it is only defined within that function. Therefore other functions will not be able to see it.
In this case, you will probably want some shared state within an object. Something like:
class MyClass:
def fun(self):
self.variable = input('Enter Here:')
def fun_2(self):
print(self.variable)
mc = MyClass()
window = Tk()
button = Button(text = 'Button', command = mc.fun )
button2 = Button(text = 'Button2', command = mc.fun_2 )
button.pack()
button2.pack()
fun() may return a value, but Tkinter buttons don't do anything with that return value.
Note that I used the phrase return a value, not return a variable. The return statement passes back the value of an expression, not the variable variable here. As such, the variable variable is not made into a global that other functions then can access.
Here, you can make variable a global, and tell fun to set that global:
variable = 'No value set just yet'
def fun():
global variable
variable = input('Enter Here:')
Since you did use any assignment in fun2, variable there is already looked up as a global, and it'll now successfully print the value of variable since it now can find that name.
The problem is in in fun2(). It does not get variable as an input parameter.
def fun_2(variable):
print(variable)
But note that you have to call fun_2 now with the appropriate argument. Also, as the function stands right now, there is little point in having the function if you just do a print inside of it.
Take away message: variable is not global in Python, and as such you must pass it to each function that wants to use it.
I'm working on a GUI for a project in school. All the buttons that I have in my GUI are bound with functions that I have created. These functions call for already predefined functions. For some of the predefined functions, I need one or two arguments and I have solved that with entries. I type in the arguments in the right entries that are connected to the specific button and when I press the button, the function will run with the corresponding arguments.
The thing I want to do is to in some way when I press a button, the function should be saved to a list instead of being executed right away. And when I push the "run" button(a new button that I will create) everything in my list will be executed. I have been thinking about using a list box but I don't know exactly how they work or if its even possible to run a list box that contains a number of functions. Does someone have any ideas or solutions for me? Can I use the list box for this or is there something else that is better to use?
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.entry1 = IntVar()
self.entry2 = IntVar()
def do_something():
value1 = self.entry1.get()
value2 = self.entry2.get()
self.listbox.insert(END, "predefined_function(value1, value2)")
def run_listbox_contents():
pass
self.button = Button(frame, text="Move", command=lambda: do_something())
self.button.pack(side=TOP)
self.entry1.set("value1")
self.entry = Entry(frame, textvariable=self.entry1)
self.entry.pack(side=TOP)
self.entry2.set("value2")
self.entry = Entry(frame, textvariable=self.entry2)
self.entry.pack(side=TOP)
self.listbox = Listbox(master)
self.listbox.pack(side=TOP)
root = Tk()
app = App(root)
root.title("Mindstorms GUI")
root.geometry("800x1200")
root.mainloop()
root.destroy()
Just use a standard list.
something like this
def hest(txt):
print "hest: " +txt
def horse(txt):
print "horse: " + txt
funcList = []
funcList.append(hest)
funcList.append(horse)
for x in funcList:
x("Wow")
This outputs
hest: Wow
horse: Wow
Was this what you wanted?
If I were you, I wouldn't want to save functions to a list. I would suggest another solution for you.
I suppose you have heard of the principle of MVC (Model-View-Controller). In your case, the list box is a part of view, and the process that saves functions and then calls them at once is a part of controller. Separate them.
You might want to save and display any string in the list box to let the users know that the corresponding functions have been enlisted and ready to run. For example, save a string "Function1 aug1 aug2 aug3" or "Funtion2 aug1 aug2" or whatever you like as a handle of the corresponding function.
And for the controller part, write a function (let's say conductor()). It reads the handle strings from the list, parses them and calls the corresponding functions. Where you want to run the enlisted functions, there you just call conductor().
Update:
Due to your comment I understand that you are pretty new to program. Let me show you how to write a simplest parser with your given variable names.
def run_listbox():
to_do_list = #get the list of strings
for handle_string in to_do_list:
#Let's say you got
#handle_string = "Predfined_function1 value1 value2"
#by here
handle = handle_string.split(" ")
#Split the string by space, so you got
#handle = ["Predfined_function1", "value1", "value2"]
#by here
if handle[0] == "Predfined_function1":
Predfined_function1(handle[1], handle[2]) #Call Predfined_function1(value1, value2)
elif handle[0] == "Predfined_function2":
Predfined_function2(handle[1], handle[2])
#elif ...
#...
#elif ...
#...
#elif ...
#...
This is not a perfect parser, but I hope it could let you know what does a parser look like.
is there any method to count how many times a function is called in python?
I'm using checkbutton in GUI. I have written a function for that checkbutton command, i need to perform some actions based on the checkbutton status, i mean based on whether it is ticked or not. My checkbutton and button syntax are like this
All = Checkbutton (text='All', command=Get_File_Name2,padx =48, justify = LEFT)
submit = Button (text='submit', command=execute_File,padx =48, justify = LEFT)
so i thougt of countin no. of times the command function is called, and based on its value i can decide whether it is ticked or not. please help
You can write decorator that will increment special variable after function call:
from functools import wraps
def counter(func):
#wraps(func)
def tmp(*args, **kwargs):
tmp.count += 1
return func(*args, **kwargs)
tmp.count = 0
return tmp
#counter
def foo():
print 'foo'
#counter
def bar():
print 'bar'
print foo.count, bar.count # (0, 0)
foo()
print foo.count, bar.count # (1, 0)
foo()
bar()
print foo.count, bar.count # (2, 1)
If checking whether the checkbutton is ticked or not is the only thing you need, why not just do checkbutton.ticked = true?
One way to implement this is to create a sub class out of Checkbutton (or - if you can - edit the existing Checkbutton class) and just add self.ticked attribute to it.
class CheckbuttonPlus(Checkbutton):
def __init__(self, text, command, padx, justify, ticked=False):
super().__init__(text, command, padx, justify)
self.ticked = ticked
And edit your function so that it changes your CheckbuttonPlus -object's ticked to not ticked.
I don't know how your classes are constructed, but you should find the method from Checkbutton class that activates the function, and then overwrite it in CheckbuttonPlus -class (incase you cannot edit the existing Checkbutton class, in which case, you don't even need CheckbuttonPlus class at all).
Edit: If you're using Tkinter Checkbutton (looks quite like it), you might wanna check this:
Getting Tkinter Check Box State