I'm new to tkinter and coding and I was wondering why can't I see the rest of my buttons. Can someone help me? I'm a total noob at coding.
from Tkinter import*
x=Tk()
def message():
y=Tk()
y.geometry("375x500")
label=Label(y,bg="light green")
recip=Entry(y)
recip.place(x=90, y=20, relwidth=0.7, relheight=0.04)
to=Label(y,text="To:",bg="maroon", fg="light green", )
to.place(x=15,y=20, relwidth=0.2,relheight=0.04)
chat=Entry(y)
chat.place(x=15,y=300, relwidth=0.7,relheight=0.05)
send=Button(y,text="send", bg="maroon", fg="light green")
send.place(x=275,y=300, relwidth=0.2,relheight=0.05)
q=Button(y,text="Q")
q.place(x=15,y=330)
w=Button(y,text="W")
w.place(x=35,y=330)
e=Button(y,text="E")
e.place(x=55,y=330)
r=Button(y,text="R")
r.place(x=75,y=330)
t=Button(y,text="T")
t.place(x=95,y=330)
y=Button(y,text="Y")
y.place(x=115,y=330)
u=Button(y,text="U")
u.place(x=15,y=330)
i=Button(y,text="I")
i.place(x=155,y=330)
o=Button(y,text="O")
o.place(x=175,y=330)
p=Button(y,text="P")#10
label.pack(expand=True, fill=BOTH)
y.mainloop()
button=Button(x,text="sample", command=message)
button.pack()
x.mainloop()
This is because you can't have two main windows eg. Tk(). Use Toplevel() to create another window.
Also you stick to one geometry manager eg. pack/place/grid. Change either place to pack or the other way round. Also the button p isn't placed at all. This I realise are a few side problems but they are important to fix. Look at the other two answers to fix your button.
Your problem as stated by Lafexlos, is that you are overwriting your instance of Tk() to add the buttons to.
I believe you should dynamically create your buttons instead of doing each 1 individually. And then given them a command that will return the corresponding letter.
I have used pack instead of place because I believe it suits this kind of program best for how the buttons are created. You will also need to make sure not to use grid, place and/or pack in the same Tk() instance as you'll find this causes problems for it.
import tkinter as tk
def open_message():
message = tk.Toplevel(root, bg = "light green")
message.minsize(300, 400)
keys = 'QWERTYUIOPASDFGHJKLZXCVBNM'
# frames for the keyboard
keyboard = tk.Frame(message, bg = "light green")
row1 = tk.Frame(keyboard)
row2 = tk.Frame(keyboard)
row3 = tk.Frame(keyboard)
row1.pack()
row2.pack()
row3.pack()
# Dynamically creates each button
# position of button depends on key index
# using index the button is assinged to the relative row
# this only includes letters. To add more, add to keys string
# and change the values to determine the assigned row
for idx, letter in enumerate(keys):
if idx < 10:
btn = tk.Button(row1, text=letter, command=lambda i=idx: get_letter(i))
elif idx < 19:
btn = tk.Button(row2, text=letter, command=lambda i=idx: get_letter(i))
else:
btn = tk.Button(row3, text=letter, command=lambda i=idx: get_letter(i))
btn.pack(side = tk.LEFT)
to_frame = tk.Frame(message, bg = "light green", padx = 40)
send_frame = tk.Frame(message, bg = "light green", padx = 40)
tk.Label(to_frame, text="To:", bg="maroon", fg="light green", relief = tk.RAISED).\
pack(side = tk.LEFT, ipady = 3)
recip = tk.Entry(to_frame)
recip.pack(side = tk.LEFT, fill = tk.BOTH, expand=True)
chat = tk.Entry(send_frame)
chat.pack(side = tk.LEFT, fill = tk.BOTH, expand=True)
send = tk.Button(send_frame, text="send", bg="maroon", fg="light green")
send.pack(side = tk.LEFT)
to_frame.pack(fill = tk.X, expand=True)
# I imagine your text widget would be packed here
keyboard.pack()
send_frame.pack(fill = tk.X, expand=True)
# Nested function to print values using keys
def get_letter(i):
# will print the letter depending on the button pressed
print(keys[i])
root = tk.Tk()
button = tk.Button(root,text="sample", command = open_message)
button.pack()
root.mainloop()
Related
I am a beginner trying to create a multiple choice quiz in python with Tkinter. Sorry if I created a messy code. I am using radio buttons for different answers. I would like to show the message "This is the correct answer" when selecting Option 1 and "This is the wrong answer" when selecting any other option. Currently, the message is always "This is the wrong answer" regardless of the Option that is chosen. I understood that the value has nothing to do with it but I did not find the right way to do it. Is there a way to define this kind of command? Thank you so much for any help, recommendations and answers.
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
window = Tk()
window.title("Quiz")
window.geometry("500x150")
score = 0
def inst():
t = Label(window, text="Choose the correct statement to answer the
question")
t.pack()
def start():
start_game()
greet = Label(window, text="Welcome to the Quiz")
greet.pack()
startButton = Button(window, command=start, text="Start")
startButton.pack()
instr = Button(window, text="Instructions", command=inst)
instr.pack()
end = Button(window, text="Exit", command=window.destroy)
end.pack()
def start_game():
top = Toplevel()
top.title("Question 1")
var = StringVar()
def check():
if var.get() is True:
messagebox.showinfo('Congrats', message='This is the correct
answer.Score is {}'.format(score))
else:
messagebox.showinfo('Lose', message='This answer is wrong.')
R1 = Radiobutton(top,
text="Option 1",
indicatoron=0,
width=20,
padx=20,
pady=10,
variable=var,
value=True,
command=check)
R1.pack( anchor = W )
R2 = Radiobutton(top,
text="Option 2",
indicatoron=0,
width=20,
padx=20,
pady=10,
variable=var,
value=False,
command=check)
R2.pack( anchor = W )
R3 = Radiobutton(top,
text="Option 3",
indicatoron=0,
width=20,
padx=20,
pady=10,
variable=var,
value=False,
command=check)
R3.pack( anchor = W)
label = Label(top)
label.pack()
window.mainloop()
Since you're working with boolean values, I thought it made more sense to use a BooleanVar instead.
You can simply pass the buttons to the check function and change their colours if you know which one is correct:
def check(btn1, btn2):
btn1.config(bg='green')
btn2.config(bg='red')
Then modify the radiobuttons as such (just below where you've defined them):
for btn in (R1, R2):
btn.config(command=lambda btn1=R1,btn2=R2:check(btn1,btn2))
Note, I used two buttons as R2 and R3 had the same values so they'd be grouped as one effectively.
Here is an example; it uses a button list to store all radiobuttons that were created and changes the colour of each of them depending on their text whilst also checking if the player got the right answer.
import tkinter as tk
def check_answer():
if question_answer.get() == 2: #get the value of the integer variable
print('you got it right') #if it has been set to 2 by the player, they got it right
for btn in btnlist: #check each of our radiobuttons
if int(btn['text']) == 2: #if the text of that button is equal to the correct answer
btn.config(bg='green') #make it green
else:
btn.config(bg='red') #otherwise make it red
win = tk.Tk()
question = 'What is 1+1?' #put your question here
question_answer = tk.IntVar() #we use an Integer Variable to store the value of the answer
question_answer.set(0) #we set the value of the correct answer to 0
lbl = tk.Label(win, text=question)
lbl.grid(columnspan=4)
column = 0
btnlist = []
for answer in range(4): #create radiobuttons in a for loop
btn = tk.Radiobutton(win, text=str(answer), variable=question_answer,
value=answer) #associate each button with the answer variable
#but give each button its own unique value
btnlist.append(btn)
btn.grid(row=1, column=column)
column += 1
confirm_btn = tk.Button(win, text='Confirm', command=check_answer)
confirm_btn.grid(columnspan=4)
win.mainloop()
In this example I used an IntVar as the answer is an integer, you could also use a BooleanVar or StringVar in the same manner as needed.
EDIT: As per you request in the comments:
import tkinter as tk
win = tk.Tk()
text_to_add_to_btns = ['A', 'B', 'C', 'D', 'E'] #change to whatever text you like
#with however many elements which represent each individual button
btn_list = []
Column = 0
for txt in text_to_add_to_btns:
btn = tk.Button(win, text=txt)
btn.grid(row=0, column=Column, sticky='nesw')
btn_list.append(btn)
Column += 1
win.mainloop()
We create a default list containing text to add to each button as individual list elements. We then loop over that list to create each button for every element and set the text of the button to that element and then append it to our separate button list.
I'm using python to interact with some excel spreadsheets. I have all that working and now I'm working on a UI using tkinter. I have 3 buttons one to pull the location of a data file, output file save location and I have a start button.
I'm trying to use a tkinter.Label to display the value of the first two buttons, example "c:/user/data_file". However, when ever I get the variable from the user and try to update the GUI with it, a copy of the window is created with the updated information. I need it to update directly to the current window seamlessly. I've been working to try to resolve this, but I just can't figure it out. Below is the code for my tkinter stuff.
def main():
def InputFilePrompt():
global InputFileLocation
InputFileLocation = askopenfilename()
update()
def OutputFilePrompt():
global OutputFileLocation
OutputFileLocation = filedialog.asksaveasfilename()
update()
def update():
root = Tk()
root.title("test")
root.resizable(width=TRUE,height=TRUE)
InputFile = Button(root, text = "input data", command = InputFilePrompt)
InputFile.grid(row = 0,column = 0)
InputFileValue = Label(root, text = InputFileLocation, bg = 'white')
InputFileValue.grid(row = 1,column = 0)
OutputFile = Button(root, text = "Compiled Data save loacation", command = OutputFilePrompt)
OutputFile.grid(row = 4,column = 0)
OutputFileValue = Label(root, text = "location: N/A", bg = 'white')
OutputFileValue.grid(row = 5,column = 0)
startButton = Button(root, text = "start", bg = 'light green', command = Excel)
startButton.grid(row = 7)
BlankUI = [0 for x in range(2)]
for blankspace in range(2):
BlankUI[blankspace] = Label(root, text = "")
BlankUI[0].grid(row = 2)
BlankUI[1].grid(row = 6)
root.mainloop()
update()
Error:
Here's a version that doesn't create the duplicate window. I've incorporated most of the suggestions I made in comments—except for the one about defining functions inside of other functions. The following still does this because doing so made it very easy to avoid using global variables (which are generally considered a poor programming practice).
Notice that there's no update() function. The values of the two tkinter.Labels are now being stored in two tkinter.StringVars objects instead of in regular Python strings. A StringVar is one of the tkinter so-called "Variable" classes. Their primary feature is that they will cause all widgets referencing them to automatically update themselves whenever their contents get changed. To use them in a Label, they're specified by using the textvariable= option (instead of the text= option) when the constructor is called.
Here's some documentation I found about them with more details on how they work.
import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename
def excel():
""" Undefined. """
pass
def main():
def get_input_file_location():
input_file_location.set(askopenfilename())
def get_output_file_location():
output_file_location.set(asksaveasfilename(confirmoverwrite=False))
root = tk.Tk()
root.title('test')
root.resizable(width=True, height=True)
input_file_location = tk.StringVar()
input_file_location.set('<undefined>')
output_file_location = tk.StringVar()
output_file_location.set('<undefined>')
input_file = tk.Button(root, text="Input data",
command=get_input_file_location)
input_file.grid(row=0, column=0)
input_file_value = tk.Label(root, textvariable=input_file_location,
bg='white')
input_file_value.grid(row=1, column=0)
output_file = tk.Button(root, text='Compiled data save loacation',
command=get_output_file_location)
output_file.grid(row=4, column=0)
output_file_value = tk.Label(root, textvariable=output_file_location,
bg='white')
output_file_value.grid(row=5, column=0)
startButton = tk.Button(root, text='start', bg='light green',
command=excel)
startButton.grid(row=7)
blank_ui = [tk.Label(root, text='') for _ in range(2)]
blank_ui[0].grid(row=2)
blank_ui[1].grid(row=6)
root.mainloop()
if __name__ == '__main__':
main()
I am trying to make a GUI using python tkinter.
I want to print the entry text from textbox to console after the analyzebutton is pressed.
here is my code
root = Tk()
root.title('Title')
MiddleFrame = Frame(root)
BottomFrame = Frame(root)
TopFrame.pack(side = TOP)
MiddleFrame.pack()
BottomFrame.pack(side = BOTTOM)
TextArea = Text()
ScrollBar = Scrollbar(root)
ScrollBar.config(command = TextArea.yview)
TextArea.config(height = 25, width = 70,
background = "white", yscrollcommand = ScrollBar.set)
TextArea.grid(padx = 18, pady = 18)
ScrollBar.pack(side = RIGHT, fill = Y)
padx = 10
pady = 10
TextArea.pack(padx = padx, pady = pady)
AnalyzeButton = Button(BottomFrame, text = "Analyze", fg = "white", bg = "blue", command = callback)
AnalyzeButton.pack(fill = X, padx = padx, pady = pady)
def callback():
text_input = Text.get()
print(text_input)
root.mainloop()
thanks in advance
Use get method of Text. Use the widget not the class-Text. Here is what you need to do:-
text_input = TextArea.get("1.0","end-1c")
You have several problems in your code. I will break it down so you understand what is going on here.
Fist I noticed you have tried to pack TopFrame but you have not actually defined TopFrame yet. So I added TopFrame = Frame(root) to your code.
Next we have a common mistake people encounter when trying to use grid() and pack() on the same window/frame. This is not allowed by the geometry manager. So you will need to decide on either grid() or pack() for all your needs in each window/frame. For now I changed TextArea.grid() to TextArea.pack() to get your code to work.
Next your button command was referencing a function that was after the command. This does not work outside of a class so you will need to move your callback() function above your AnalyzeButton.
Next we need to fix the indention on your callback() function. You must remember indention is very important in python and you should take care to keep your indention clean and consistent.
The last thing we needed to fix to get everything working as you were intending is to change:
text_input = Text.get()
To:
text_input = TextArea.get(1.0, END)
You were trying to call get() on the method that created the text widget and not the widget instance.
You also need to define from what part of the text widget you want to start reading data and how far you want to read through the text widget. this is done by applying 2 positions points with 1.0, END or "1.0", "end-1c" as tkinter allows for a few ways to apply these points. This will say 1.0 start at the first line at the first position on that line and END will say read until the last line of the textbox.
There may be other issues but I only fixed the problems preventing the code from working as intended. Your code modified to work below:
from tkinter import *
root = Tk()
root.title('Title')
TopFrame = Frame(root) # was missing from your code
MiddleFrame = Frame(root)
BottomFrame = Frame(root)
TopFrame.pack(side = TOP)
MiddleFrame.pack()
BottomFrame.pack(side = BOTTOM)
TextArea = Text()
ScrollBar = Scrollbar(root)
ScrollBar.config(command = TextArea.yview)
TextArea.config(height = 25, width = 70,
background = "white", yscrollcommand = ScrollBar.set)
TextArea.pack() # can't use pack and grid on the same window/frame. Changed this to pack()
ScrollBar.pack(side = RIGHT, fill = Y)
padx = 10
pady = 10
TextArea.pack(padx = padx, pady = pady)
# this function needs to be before the command that references it.
def callback():
# fixed indention
text_input = TextArea.get(1.0, END) # you need to reference that widget name not the tkinter method used to create the widget.
print(text_input)
AnalyzeButton = Button(BottomFrame, text = "Analyze", fg = "white", bg = "blue", command = callback)
AnalyzeButton.pack(fill = X, padx = padx, pady = pady)
root.mainloop()
I am having a hard time understanding the focus events for Entry and Textbox fields in Python version 3 using Tk. I eventually need to validate an Entry box on lost focus if I click a radio option or a button.
If you run the code below then (which serves only to demonstrate Focus issues not the validation i require elsewhere), place the cursor in either of the top row Entry boxes and click between the other widgets, the only time FocusIn and Focus out events occur are on the widgets that accept input ie Text/Entry boxes.
Clicking the button or the radio options, the cursor remains in the Entry or Textbox widgets. Why when i have clearly focused on a radio option or the button.
I have tried .bind FocusIn/Out events and still no joy. if anyone has an explanation I would be intrigued to know why and possibly how i can overcome it.
from tkinter import *
root = Tk()
root.title("My Widgets")
root.update_idletasks()
root.geometry("350x200+10+300")
root.attributes("-toolwindow",1)
root.resizable(width=FALSE, height=FALSE)
root.config(bg="blue")
# function below output to the console and label the focus results
def Validate(a,b,c,d,e,f,g,h):
text = g + ' on ' + h
lblOutputVar.set(text)
print(f,g,h)
return True
var = IntVar()
lblOutputVar = StringVar()
vcmd=(root.register(Validate),'%d','%i','%P','%s','%S','%v','%V','%W')
entryOne = Entry(root, name = 'entryBoxOne')
entryOne.config(validate = 'all',vcmd=vcmd)
entryOne.grid(row=1, column=1,padx=(0,0),pady=(10,10),ipady=(1), sticky=E+W)
entryTwo = Entry(root, name = 'entryBoxTwo')
entryTwo.config(validate = 'all',vcmd=vcmd)
entryTwo.grid(row=1, column=2,padx=(10,0),pady=(10,10),ipady=(1), sticky=E+W)
txtBox = Text(root, name = 'textBox', width=10, height=1, takefocus = 0)
txtBox.grid(row=5, column=1, sticky=E+W)
aButton = Button(root, text = 'Click Me!', takefocus=1)
aButton.grid(row=5, column=2)
lblOutput = Label(root, name = 'labelOutput', width=20, height=2, textvariable=lblOutputVar)
lblOutput.grid(row=10, column=1, columnspan =2, pady=(5,0), sticky=E+W)
radioOne = Radiobutton(root, anchor = 'w', text = 'One', variable = var, value = 1, takefocus = 1)
radioOne.grid(row=2, column=1, sticky=E+W)
radioTwo = Radiobutton(root, anchor = 'w', text = 'Two', variable = var, value = 2, takefocus = 1)``
radioTwo.grid(row=3, column=1, sticky=E+W)
root.mainloop()
The explanation is simply that tkinter buttons and radiobuttons aren't given focus when you click on them. If you want that to happen, you need to set up a binding to explicitly give them the focus.
Your other option is to use a ttk radiobutton which does get focus. It's unfortunate that the two different radiobuttons have different behavior.
I am making a chat program and decided to use Tkinter for the interface.
What I wanna do is a breeze in C# but Tkinter is new to me.
Basically I have a form with a Entry control and a Text control.
I want to know how to append text from the Entry control to the Text control after the user presses Enter.
Here's my code so far:
from tkinter import *
class Application:
def hello(self):
msg = tkinter.messagebox.askquestion('title','question')
def __init__(self, form):
form.resizable(0,0)
form.minsize(200, 200)
form.title('Top Level')
# Global Padding pady and padx
pad_x = 5
pad_y = 5
# create a toplevel menu
menubar = Menu(form)
#command= parameter missing.
menubar.add_command(label="Menu1")
#command= parameter missing.
menubar.add_command(label="Menu2")
#command= parameter missing.
menubar.add_command(label="Menu3")
# display the menu
form.config(menu=menubar)
# Create controls
label1 = Label(form, text="Label1")
textbox1 = Entry(form)
#command= parameter missing.
button1 = Button(form, text='Button1')
scrollbar1 = Scrollbar(form)
textarea1 = Text(form, width=20, height=10)
textarea1.config(yscrollcommand=scrollbar1.set)
scrollbar1.config(command=textarea1.yview)
textarea1.grid(row=0, column=1, padx=pad_x, pady=pad_y, sticky=W)
scrollbar1.grid(row=0, column=2, padx=pad_x, pady=pad_y, sticky=W)
textbox1.grid(row=1, column=1, padx=pad_x, pady=pad_y, sticky=W)
button1.grid(row=1, column=2, padx=pad_x, pady=pad_y, sticky=W)
form.mainloop()
root = Tk()
Application(root)
So you're using a tkinter.Text box, which supports the .insert method. Let's use it!
def __init__(self,form):
# Lots of your code is duplicated here, so I'm just highlighting the main parts
button1 = Button(form, text='Button1', command = self.addchat)
self.textbox = textbox1 # to make it accessible outside your __init__
self.textarea = textarea1 # see above
form.bind("<Return>", lambda x: self.addchat())
# this is the magic that makes your enter key do something
def addchat(self):
txt = self.textbox.get()
# gets everything in your textbox
self.textarea.insert(END,"\n"+txt)
# tosses txt into textarea on a new line after the end
self.textbox.delete(0,END) # deletes your textbox text