Simple GUI buttons and inputs - python

I am currently in an intro cs class and have a question about simple GUI and more specifically how to take a number (ex 6,7,8) input and when a button is pressed take the input number and determine if it is even or odd so far below is what I have and I get the error message that states: "button_handler() takes exactly 1 arguments (0 given)" Can someone explain to me what I am doing wrong?
import simplegui
global text_input
frame = simplegui.create_frame('Testing', 250, 250)
label = frame.add_label('Divisable by 6?')
def input_handler(text_input):
print "You entered,", text_input
def button_handler(num):
if float(num) / 6 == 0:
print "divisable by six"
else:
print "Not divisable by 6"
button1 = frame.add_button('divisable by 6?', button_handler)
inp = frame.add_input('Please insert number', input_handler, 50)
frame.start()
(BTW the formatting is weird when copied and pasted from code skulptor)

I am familiar with with tkinter and have not used simplegui, but from the error message, I can guess the problem.
button_handler is a callback that is called without any arguments when the button is clicked. But you define it with a parameter number. You have to re-write button_handler to get the number from the input some other way. I know how to do that with tkinter, but not for simplegui. Perhapsinput_handlershould write a global thatbutton_handler` can access.

In this line here:
button1 = frame.add_button('divisable by 6?', button_handler)
you are not feeding anything to button_handler. In other words, it has no arguments. But elsewhere in your code you mandate that button_handler has exactly one argument. So, you need to update your reference to button_handler in the line above to account for that fact.
(That's the fundamental bit, anyway: I don't want to comment on the rest of your code, since you say it is under construction.)

From the CodeSculptor documentation for frame.add_button():
The handler should be defined with no parameters
You can grab the content of an input field with get_text(). Here is a simple example that prints the content of an input field when a button is pressed:
import simplegui
def input_handler(text_input):
pass
def button_handler():
print inp.get_text()
frame = simplegui.create_frame("Demonstration of input and button", 300, 300)
inp = frame.add_input("Input:", input_handler, 100)
frame.add_button("Print", button_handler, 100)
frame.start()

Related

is it possible to get a variable out of a function, into another function, if the first one doesn't trigger by the second one?

def NewNote(x, y):
print("something")
text = input()
return (text)
def Delete(x, y):
text = GetText()
pen.write(text, align="left", font=("arial", TextSize))
print(text)
**text = BlackSquare.onrelease(NewNote)**
**text = VerLine.onrelease(NewNote)**
**text = HorzLine.onrelease(NewNote)**
color = turtle.onscreenclick(settings)
WhiteeraserSquare.onrelease(Delete)
BlackeraserSquare.onrelease(Delete)
def GetText():
textA = text
return textA
< so basically the NewNote function gets triggered by one of the starred triggers, takes an input from the user, and from there i want to get that input to the delete function. so i tried to return it to the trigger, save it again as a variable, than put it into another function that would send it back up to the
delete function, but i clearly don't understand how the whole return thing works, because the delete function keeps printing "none".
(i am using the Turtle graphics module, so.. the triggers, and the pen.write are from there).
ps: this is my first time asking a question in stack overflow, so if i did something wrong, forgive me.
You're misunderstanding turtle event handlers and need to (re)read about them:
def NewNote(x, y):
print("something")
text = input()
return (text)
text = BlackSquare.onrelease(NewNote)
The onrelease() method doesn't return anything (returns None) so assigning its result into the text variable does nothing.
The NewNote() event handler's caller doesn't care about its return value so the return (text) is basically ignored.
Here's a simple example that I hope will help you understand how these functions are used. It puts up two turtle buttons, a green and red square. Click on the green one and it will prompt you for input and write in the center of the screen. Click on the red one and it will erase that text:
from turtle import Screen, Turtle
def delete_text(x, y):
pen.clear()
def write_text(x, y):
text = screen.textinput("Text Input", "Enter some text")
pen.clear()
pen.write(text, align='center', font=('Arial', 18, 'bold'))
screen = Screen()
write = Turtle()
write.shape('square')
write.color('green')
write.penup()
write.onrelease(write_text)
write.backward(200)
erase = Turtle()
erase.shape('square')
erase.color('red')
erase.penup()
erase.onrelease(delete_text)
erase.forward(200)
pen = Turtle()
pen.hideturtle()
screen.mainloop()
To pass information between write_text() and delete_text() requires some sort of global entity through which to pass this information. It can be as simple as a global variable or something more complex like an object that's passed as an extra argument to the handers via a lambda expression.

using a string variable to control a textbox property

I have various textboxes on a form to enter numbers and want to have a single function which can check the entry and highight the box in red if incorrect rather than repeating the same code for each textbox.
Is it possible to set the name of the textbox (_FreqTextBox) as a variable so I can make this a generic function for each textbox. An example function is below. I've tried to find examples of this but no luck so far. Newish to Python so apologies if this is obvious.
def FreqTextBoxTextChanged(self, sender, e):
self._FreqTextBox.BackColor = System.Drawing.SystemColors.Window
IsNumber,text_value = self.CheckNumber(self._FreqTextBox.Text)
if (IsNumber == False):
self._FreqTextBox.BackColor = System.Drawing.Color.Red
return
IsNumber = self.NegativeValueMsg(text_value)
if (IsNumber == True):
self._FreqTextBox.BackColor = System.Drawing.Color.Red
return

How to make Tkinter checkbuttons work individually and default as checked

I am trying to have a series of checkboxes which can be selected or not selected - then when the user presses the button, the letters allocated to the checkboxes should be added to an inputted string and then printed.
I am having 2 major problems;
The when the user presses a checkbox, all of the checkboxes are selected.
I would like to have the default being that all of them as checked, but I cannot find how to do this. If this cannot be answered, it is less important than the 1st problem, and hence doesn't matter as much.
This is my code so far;
import Tkinter
class MENU():
def __init__(self,NewData):
self.SCREEN = Tkinter.Tk()
self.NewData = NewData
self.Selection = {"A":1,"B":1,"C":1,"D":1}
self.A = Tkinter.Checkbutton(self.SCREEN,text="A",variable=self.Selection["A"]).pack()
self.B = Tkinter.Checkbutton(self.SCREEN,text="B",variable=self.Selection["B"]).pack()
self.C = Tkinter.Checkbutton(self.SCREEN,text="C",variable=self.Selection["C"]).pack()
self.D = Tkinter.Checkbutton(self.SCREEN,text="D",variable=self.Selection["D"]).pack()
self.BtnFinish = Tkinter.Button(self.SCREEN,text="Finish selection",command=self.FinishSelection)
self.BtnFinish.pack()
self.SCREEN.mainloop()
def FinishSelection(self):
SelectionString = ""
for n in self.Selection:
if self.Selection[n]:
SelectionString+=n
self.NewData+="\nQuestions\n"+SelectionString+"\n"
print self.NewData
MENU("")
If it matters at all, this is for Python 2.7.3. Additionally, my thanks, and also apologies to those of you who likely have to point out something incredibly obvious/basic, which, as a beginner for Tkinter, I have not realised.
You must use one of the Tkinter objects StrintVar, IntVar, BooleanVar or DoubleVar normally (StringVar) as the value of the variable argument. You can't use a normal python variable. You'll have to create an individual variable for each.
For example:
self.Selection = {"A": Tkinter.BoolVar(), "B": Tkinter.BoolVar(), ...}
self.Selection["A"].set(True)
...
Then, to get the value you'll need to use the get method:
value = self.Selection["A"].get()

Tkinter, saving functions to a list and then running them

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.

tkinter button press to function call

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.

Categories