I am very new to Tkinter ( I find it very difficult to learn). I have a python script working based on user input. I would like to wrap a GUI around it and eventually put it on web. In any case for user input I would like to get this from the GUI with a combination of Entry widgets and some buttons. First thing is I was reading and some people mentioned to use a class so I have the following. I have a few questions
I would like to check to see if indeed the users entered a value before he hits the GO button. How do I do this?
I would like the value entered to be made accessible by the rest of the program in the main body. How do I do this?
Thanks,
from Tkinter import *
class MainWindow():
def get_fc(self):
a = self.fc_gui.get()
return a
def __init__(self, master):
self.master = master
self.master.title('TEST')
self.fc_gui = DoubleVar(self.master, value = 500.00)
self.fclabel1 = Label(self.master, text = 'Please Enter a value', fg = 'black', bg = 'yellow')
self.fclabel1.grid(row = 0, column = 0)
self.fcedit1 = Entry(self.master, textvariable = self.fc_gui, bd = 5 )
self.fcedit1.grid(row = 1, column = 0)
fcbutton1 = Button(self.master, text='GO', command = self.get_fc)
fcbutton1.grid(row = 1, column = 1)
master = Tk()
MainWindow(master)
master.mainloop()
It doesn't make sense to return to a Button. The Button can't do anything with the value. Instead, save the value as an instance variable.
You don't have a mainloop().
You can't really check if the user entered a value before they hit "Go" - at the start of the program, of course they haven't entered anything yet. If you needed to track the contents of this field, there are ways to do that, but it's not necessary for a simple validation. Just check the value when they hit the button.
from Tkinter import *
class MainWindow():
def get_fc(self):
a = self.fc_gui.get()
if a: # this block will execute if a has content
self.a = a # save it for future use
def __init__(self, master):
self.master = master
self.master.title('TEST')
self.fc_gui = DoubleVar(self.master, value = 500.00)
self.fclabel1 = Label(self.master, text='Please Enter a value',
fg = 'black', bg = 'yellow')
self.fclabel1.grid(row = 0, column = 0)
self.fcedit1 = Entry(self.master, textvariable = self.fc_gui, bd = 5 )
self.fcedit1.grid(row = 1, column = 0)
fcbutton1 = Button(self.master, text='GO', command = self.get_fc)
fcbutton1.grid(row = 1, column = 1)
master = Tk()
MainWindow(master)
master.mainloop() # don't forget mainloop()
Related
im using tkinter with class abd im having trouble with adding a product
class Add_Page():
def __init__(self, child):
self.child = child
child.title = "Ajouter"
self.l1=Label(child,text="Ajouter produit :",bg="blue").grid(row=0,columnspan=2)
self.l2=Label(child,text="Matricule").grid(row=1,column=0)
self.vlrm = StringVar()
self.en2 = Entry(child, textvariable=self.vlrm, width=30).grid(row=1,column=1)
self.l3=Label(child,text="Nom").grid(row=2,column=0)
self.vlrn = StringVar()
self.en3 = Entry(child, textvariable=self.vlrn, width=30).grid(row=2,column=1)
self.l4=Label(child,text="Prix").grid(row=3,column=0)
self.vlrp = IntVar()
self.en4 = Entry(child, textvariable=self.vlrp, width=30).grid(row=3,column=1)
self.b2=Button(child,text="Valider",command=self.add_p).grid(row=4,columnspan=2)
#Add product function
def add_p(self):
print(self.vlrm.get())
print(self.vlrp.get())
the results are anempty chaine and 0
i dont seem to find the problem especially that i used the get method in users class and its working just fine
Heelp
You don't need create a variable to entry, only make this for radiobutton or checkbutton. And you can change your create of tkinter object, like that
change this
self.l1=Label(child,text="Ajouter produit :",bg="blue").grid(row=0,columnspan=2)
for this
self.l1 = Label(child, text = "Ajouter produit :", bg = "blue")
self.l1.grid(row = 0, columnspan = 2) # remove all variables StringVar() and IntVar()
if you need make some future change using .config or .get() you don't can make that in the first example. You can continue using variable, but i don't recommend that, if you make this change .get() will work now.
I maked a easy way to draw in tkinter, you can use or make change, is for python 2
from Tkinter import *
class Draw_tk():
Row, Column, List = 0, 0, []
def __init__(self, child):
self.child = child
child.title = "Ajouter"
def labelAndEntry(self, text): # def to create a entry and a label
self.l = Label(self.child, text = text) # create label
self.l.grid(row = Draw_tk.Row, column = Draw_tk.Column) # place label
Draw_tk.Column += 1 # add 1 in Column to place the entry
self.e = Entry(self.child, width = 30) # create entry
self.e.grid(row = Draw_tk.Row, column = Draw_tk.Column) # place entry
Draw_tk.List.append(self.e) # add the entry in a list
Draw_tk.Row, Draw_tk.Column = Draw_tk.Row + 1, 0
def label(self, text):
self.l = Label(self.child, text = text, bg = "blue") # def to create a simple label
self.l.grid(row = Draw_tk.Row, columnspan=2) # place the label
Draw_tk.Row += 1
def button(self, text, var): # create a simple button
self.b = Button(self.child, text = text, command = var) # create button
self.b.grid(row = Draw_tk.Row, column = Draw_tk.Column) # place the button
def valid():
for item in Draw_tk.List: # run a variable in your values list
print item.get() # get the value and print
root = Tk()
controller = Draw_tk(root) # create object Draw_tk
controller.label('Ajouter produit')
controller.labelAndEntry('Matricule')
controller.labelAndEntry('Nom')
controller.labelAndEntry('Prix')
controller.button('Valider', valid)
root.mainloop()
I am new to tkinter and I would like to create a tkinter interface with "entries" , a canvas with a picture , and a button. I expected only one tk window but there is a second small empty tk window when I run my code. I guess it is because of the class I use but I'm not sure..
Here is my code :
from tkinter import*
import tkinter as tk
import time
class Application(Tk):
def __init__(self,transfo,nb_itération):
Tk.__init__(self)
self.transfo = transfo
self.nb_itération = nb_itération
def affichage_graphique(self):
self.matrix_hex = extraction_rgb(tk.PhotoImage(file='obama_128.gif'))
self.width , self.height = len(self.matrix_hex[0]) , len(self.matrix_hex)
self.WIDTH, self.HEIGHT = 8*self.width+6, 8*self.height+6
self.cnv = Canvas(self, width=self.WIDTH, height=self.HEIGHT, bg='white',highlightthickness=0)
self.cnv.grid(row = 2 , columnspan = 3)
self.txt1 = Label(self, text = 'Transformation :').grid(row = 0 , sticky = E)
self.txt2 = Label(self, text = 'Nombre d\'itérations : ').grid(row = 1 , sticky = E)
self.entr1 = Entry(self)
self.entr2 = Entry(self)
self.entr1.grid(row = 0, column = 1, sticky = W)
self.entr2.grid(row = 1, column = 1, sticky = W)
Button(self, text="Quitter", command=self.destroy).grid(row = 0 , column = 2)
if self.transfo == photomaton or self.transfo == boulanger:
print("valeur par défaut mauvaise")
self.cnv.delete(ALL)
self.img01 = self.PhotoImage(width=self.width*4, height=self.height*4)
self.img = self.PhotoImage(width=self.width*4, height=self.height*4)
self.matrix_hex4 = [[x for x in range(self.width*4)] for y in range(self.height*4)]
self.matrix_4 = [[x for x in range(self.width*4)] for y in range(self.height*4)]
self.img.put(data=self.matrix_4 , to=(0,0))
self.cnv.create_image(0, 0, image=self.img, anchor=tk.NW)
self.img01.put(data=self.matrix_hex4, to=(0,0))
self.cnv.create_image(self.WIDTH, 0, image=self.img01, anchor=tk.NE)
self.cnv.bind('<Button-1>',self.click_handler)
else:
self.img = tk.PhotoImage(width=self.width*4, height=self.height*4)
self.img.put(data=self.matrix_4 , to=(0,0))
self.cnv.create_image(0, 0, image=self.img, anchor=tk.NW)
self.entr1.insert(0,"photomaton")
self.entr2.insert(0,"1")
self.entr2.bind("<Return>",Programme().Enter)
class Programme(Application):
def __init__(self,transfo = 0, nb_itération = 0 ,orbites =[],période = []):
self.choice = 0
self.orbites = orbites
self.période = période
self.transfo = transfo
self.nb_itération = nb_itération
Application.__init__(self, self.transfo , self.nb_itération)
def Enter(self,event):
self.choix_transfo = self.entr1.get()
self.nb_itération = self.entr2.get()
return self.choix_transfo , self.nb_itération
def start(self):
self.affichage_graphique()
prog = Programme()
prog.start()
prog.mainloop()
The problem seems to be on this line:
self.entr2.bind("<Return>",Programme().Enter)
This line has multiple problems:
it will create a second Program() instance (assuming that this is a typo), thus creating a second Tk window (because Program extends Tk)
it will do so immediately, not only when the button is clicked, and bind the method of that new instance to the button
Instead, you probably want to use
self.entr2.bind("<Return>", self.Enter)
to call the Enter method of the current Program instance, or
self.entr2.bind("<Return>", lambda: Program().Enter)
if you actually want to create a second Program window when the button is clicked; however, in this case you will also have to call the gui method in order to initialize the widgets.
Note that there are a few other problems in your code, as discussed in comments, but I assume that those don't exist in your actual code, otherwise you would not get that behaviour.
You are creating a new window in two places. First, with this:
prog = Programme()
The second is here:
self.entr2.bind("<Return>",Programme().Enter)
Why? The above code is functionally identical to this:
p = Programme()
self.entr2.bind("<Return>", p.Enter)
The normal way to call functions defined in your program class is to use the existing reference. Since your code is being run in a method belonging to the Programme class, you can do this:
self.entr2.bind("<Return>", self.Enter)
I'm trying to create an entry box for a user to manually input a variable that doesn't exist in a list of a optionmenu widget. is this possible?
from Tkinter import *
import Tkinter as tk
class Demo1:
def __init__(self, master):
self.master = master
self.frame = tk.Frame(self.master)
x = (master.winfo_screenwidth() - master.winfo_reqwidth()) / 2
y = (master.winfo_screenheight() - master.winfo_reqheight()) / 2
master.geometry("+%d+%d" % (x, y))
master.deiconify()
self.subtests = StringVar()
self.subtests.set("Enter Test Type")
choices = ['Potato','Tomato','Onion','Other']
self.testnumber = OptionMenu(master, self.subtests, *choices).grid(row = 2, column = 3)
self.confirmbutton = Button (master, text="Confirm Test", width=20, command =lambda: self.confirmsubtest(master))
self.confirmbutton.grid(row = 5, sticky = E)
def main():
root = tk.Tk()
app = Demo1(root)
root.mainloop()
if __name__ == '__main__':
main()
As mentioned, if the user needs to select a variable that is not on the list. Is it possible to allow the user to manually enter the variable through an entry box in the same window (ex: Selecting "Other" in the list that generates an entry/widget/something)?
If anyone searches for the same thing. The process is to add the command variable to the optionmenu and disable the entry widget once the desired highlighted choice is on. This is done by configuring the button/widget/anything with a .config(state=NORMAL) or .config(state=DISABLED).
self.testnumber = OptionMenu(master, self.subtests, *choices, command = self.optupdate).grid(row = 2, column = 3)
self.testnumber.grid(row = 4, column = 1)
def optupdate(self,value):
if value == "Other":
self.otherEntry.config(state=NORMAL)
else:
self.otherEntry.config(state=DISABLED)
return
Why isn't this working. This is straight from the text book. I'm getting an Attribute error saying self._area does not exist.
from Tkinter import *
import math
class CircleArea(Frame):
def __init__(self):
"""Sets up a window and widgets."""
Frame.__init__(self)
self.master.title("Circle Area")
self.grid()
#Label and field for radius
self._radiusLabel = Label(self, text = "Radius")
self._radiusLabel.grid(row = 0, column = 0)
self._radiusVar = DoubleVar()
self._radiusEntry = Entry(self, textvariable = self._radiusVar)
self._radiusEntry.grid(row = 0, column = 1)
#Label and field for the area
self._areaLabel = Label(self, text = "Area")
self._areaLabel.grid(row = 1, column = 0)
self._areaVar = DoubleVar()
self._areaEntry = Entry(self, textvariable = self._areaVar)
self._areaEntry.grid(row = 1, column = 1)
# The command button
self._button = Button(self, text = "Compute", command = self._area)
self._button.grid(row = 2, column = 0, columnspan = 2)
def _area(self):
"""Event handler for button."""
radius = self._radiusVar.get()
area = radius ** 2 * math.pi
self._areaVar.set(area)
def main():
CircleArea(). mainloop()
run = CircleArea()
run.main()
Is it because the _area method is declared after it is called? That doesn't make sense why it wouldn't work using a down up programming technique. I'm really new to GUI just started learning. First chapter on GUI for class.
edit*: I'm expecting a window to pop up and have one Entry field for input for the radius of the circle. With a label Radius. And an output entry field for the results of the area of the circle based on the radius. and a compute button at the bottom which computes it.
And I just wanted to get used to typing the different commands and such. I haven't even been in the lecture for this yet. I was just seeing what this code would do and what it would look like. I typed it all out by hand if that makes you feel better.:P Instead of copy and pasting.
The problem is that your indenting is wrong. _area and main are defined within __init__, which you don't want. Correct indenting is below (you don't need a main function).
from Tkinter import *
import math
class CircleArea(Frame):
def __init__(self):
"""Sets up a window and widgets."""
Frame.__init__(self)
self.master.title("Circle Area")
self.grid()
#Label and field for radius
self._radiusLabel = Label(self, text = "Radius")
self._radiusLabel.grid(row = 0, column = 0)
self._radiusVar = DoubleVar()
self._radiusEntry = Entry(self, textvariable = self._radiusVar)
self._radiusEntry.grid(row = 0, column = 1)
#Label and field for the area
self._areaLabel = Label(self, text = "Area")
self._areaLabel.grid(row = 1, column = 0)
self._areaVar = DoubleVar()
self._areaEntry = Entry(self, textvariable = self._areaVar)
self._areaEntry.grid(row = 1, column = 1)
# The command button
self._button = Button(self, text = "Compute", command = self._area)
self._button.grid(row = 2, column = 0, columnspan = 2)
def _area(self):
"""Event handler for button."""
radius = self._radiusVar.get()
area = radius ** 2 * math.pi
self._areaVar.set(area)
run = CircleArea()
run.mainloop()
Actually I think you miss an argument in your main method,you define a class CircleArea , but in python you know that, each method defined in class must have an default argument named 'self',so just try this
def main(self):
CircleArea(). mainloop()
I think it will work as you wish :)
I am programming a simple game using tkinter and want an option at the end to be able to replay the game, but I am not sure how I would go about doing it. I would like to be able to go back to the beginning where i define init. Also is there a way I could do this and not have to quit it so I could save scores as the player keeps playing.
from tkinter import *
import random
class App:
def __init__(self, master):
player_dice = []
for i in range(1,6):
x = random.randint(1,6)
player_dice.append(x)
self.label = Label(master, text = x , fg = "red").grid(row =0, column =i+1)
self.label = Label(master, text = "Dice:" , fg = "red").grid(row =0, column =1)
self.hi_one = Button(master, text="one", command= lambda: say_one(player_dice)).grid(row = 1, column = 1)
self.hi_two = Button(master, text="two", command= lambda: say_two(player_dice)).grid(row = 1, column = 2)
Here is where I would like to add a button to loop back to init.
def num(var, die, dlist):
new_window = Toplevel(root)
if die == 1:
if guess == total:
result = Message(new_window, text = "You Win").grid(row = 1, column = 1)
else:
result = Message(new_window, text = "You Lose").grid(row = 1, column = 1)
restart = Button(new_window, text = "Play Again", command = ?????).grid(row=1, column = 2)
Easiest way:
Just add a function resetBoard that resets your game.
Obviously there are various parts of the UI that don't need to be re-set, so those can go into __init__, the rest can go into resetBoard() and you can (possibly) call resetBoard() from within __init__.
Correct way:
Implement an MVC or MVP pattern: Separate your data and logic from your UI. Your view (UI) should reflect whatever is in your model, then reseting the game is just a question of reseting the model and firing the correct events so the view is updated (highly simplistic, but the very useful model-view-XXX patterns cannot be properly explained in just a few words.)