Tkinter: Irregular spacing for widgets in frames using grid columns - python

I am attempting to create a relatively simple survey like form in Tkinter, and I'm relatively new to the GUI framework. I'm having real issues trying to figure out why there are so many inconsistencies, especially when working with grid placement+frames+multiple widgets in same row. Especially this specific example. I'm tying together all my questions into a single frame, and it seems to work out... sort of half. Though the rows seem to cooperate nicely, the columns are where the whole thing gets erupted.
qframe1 = Frame(question, bg='black')
qframe1.grid(row=1, padx = 20, sticky = W)
q1l = Label(qframe1, text = 'Question 1: How often do you eat at Mcdonalds?', font = ('Calibri', 14), bg = 'azure')
q1l.grid(columnspan = 4, pady = 5, sticky = W)
q1 = StringVar()
q1.set('None')
q1r1 = Radiobutton(qframe1, text = 'Everyday!', font = ('Calibri', 12), bg = 'azure', variable = q1, value = 'Always')
q1r1.grid(row=1, column = 0, pady = 5, sticky = W)
q1r2 = Radiobutton(qframe1, text = 'Sometimes', font = ('Calibri', 12), bg = 'azure', variable = q1, value = 'Sometimes')
q1r2.grid(row=1, column = 1, pady = 5, sticky = W)
q1r3 = Radiobutton(qframe1, text = 'Not Frequently', font = ('Calibri', 12), bg = 'azure', variable = q1, value = 'Infrequent')
q1r3.grid(row=1, column = 2, pady = 5, sticky = W)
q1r4 = Radiobutton(qframe1, text = 'Never', font = ('Calibri', 12), bg = 'azure', variable = q1, value = 'Never')
q1r4.grid(row=1, column = 3, pady = 5, sticky = W)
This is the bare code for the section that's messing up.
Also, I have made sure that it's not the length of each radio button that is causing the issue. When I change the text of the radio buttons, they still get placed in the same irregular positions.
Here's the code for another section of the trivia.
q2l = Label(qframe1, text = 'Question 2: What meal do you normally order?', font = ('Calibri', 14), bg = 'azure')
q2l.grid(row=2, columnspan = 4, pady = 5, sticky = W)
q2 = StringVar()
q2.set('None')
q2r1 = Radiobutton(qframe1, text = 'Fries', font = ('Calibri', 12), bg = 'azure', variable = q2, value = 'Fries')
q2r1.grid(row=3, column = 0, pady = 5, sticky = W)
q2r2 = Radiobutton(qframe1, text = 'Hamburgers', font = ('Calibri', 12), bg = 'azure', variable = q2, value = 'Hamburgers')
q2r2.grid(row=3, column = 1, pady = 5, sticky = W)
q2r3 = Radiobutton(qframe1, text = 'Chicken Nuggets', font = ('Calibri', 12), bg = 'azure', variable = q2, value = 'Chicken Nuggets')
q2r3.grid(row=3, column = 2, pady = 5, sticky = W)
q2r4 = Radiobutton(qframe1, text = 'Coffee', font = ('Calibri', 12), bg = 'azure', variable = q2, value = 'Coffee')
q2r4.grid(row=3, column = 3, pady = 5, sticky = W)
This again causes an irregular spacing. But this time, the spacing is completely different from the radio buttons in question 1. And rinse and repeat with every new question set of radio buttons.
There are no issues with the buttons on the right side. Perhaps it's because they're aligned in rows and not columns which are causing the spacing issue.
bframe = Frame(question, bg='black')
bframe.grid(row=1, padx = 20, sticky = E)
audioq1 = Button(bframe, text = ' Listen to Audio', font = ('Calibri', 14), bg = 'brown1', fg = 'azure', image = sound, relief = SUNKEN, compound = LEFT, command = q1audio)
audioq1.grid(ipadx = 5, pady = 20)
audioq2 = Button(bframe, text = ' Listen to Audio', font = ('Calibri', 14), bg = 'brown1', fg = 'azure', image = sound, relief = SUNKEN, compound = LEFT, command = q2audio)
audioq2.grid(row = 1, ipadx = 5, pady = 20)
audioq3 = Button(bframe, text = ' Listen to Audio', font = ('Calibri', 14), bg = 'brown1', fg = 'azure', image = sound, relief = SUNKEN, compound = LEFT, command = q3audio)
audioq3.grid(row = 2, ipadx = 5, pady = 20)
audioq4 = Button(bframe, text = ' Listen to Audio', font = ('Calibri', 14), bg = 'brown1', fg = 'azure', image = sound, relief = SUNKEN, compound = LEFT, command = q4audio)
audioq4.grid(row = 3, ipadx = 5, pady = 20)
audioq5 = Button(bframe, text = ' Listen to Audio', font = ('Calibri', 14), bg = 'brown1', fg = 'azure', image = sound, relief = SUNKEN, compound = LEFT, command = q5audio)
audioq5.grid(row = 4, ipadx = 5, pady = 20)
Any help would be greatly appreciated!

If, as mentioned in the comments, "weight isn't necessarily the problem", the placement of the radiobuttons can be realized using pack instead of grid.
This gives something like this (on a mac):
If you want a more evenly placed buttons to fill the available width, you can achieve this with grid:
I also rewrote a portion of the code to make it easier to add questions to the form. Each question is now in its own frame, allowing for more flexibility.
import tkinter as tk
class QFrame(tk.Frame):
id = 1
def __init__(self, master, question):
self.master = master
super().__init__(self.master)
self.id = QFrame.id
QFrame.id += 1
self.q = tk.StringVar()
self.q.set('None')
self.question, self.choices = question
self.q_label = tk.Label(self, text=f'Question {self.id}: {self.question}')
self.q_label.pack(expand=True, anchor=tk.W)
self.choose = []
for idx, choice in enumerate(self.choices):
txt, value = choice
qr = tk.Radiobutton(self, text=txt, variable=self.q, value=value)
self.choose.append(qr)
qr.pack(side=tk.LEFT)
class App(tk.Tk):
def __init__(self, questions):
self.questions = questions
super().__init__()
for question in questions:
self.qframe = QFrame(self, question)
self.qframe.pack(fill=tk.X)
q1 = ['How often do you eat at Mcdonalds?',
(('Everyday!', 'Always'),
('Sometimes', 'Sometimes'),
('Not Frequently', 'Infrequent'),
('Never', 'Never'))]
q2 = ['What meal do you normally order?',
(('Fries!', 'Fries'),
('Hamburgers', 'Hamburgers'),
('Chicken Nuggets', 'Chicken Nuggets'),
('Coffee', 'Coffee'))]
q3 = ['how large is your usual party?',
(('alone!', 'alone'),
('two', 'two'),
('less than 5', 'less than 5'),
('5 or more', '5 or more'))]
questions = [q1, q2, q3]
app = App(questions)
app.mainloop()
The code for grid geometry manager:
class QFrame(tk.Frame):
id = 1
def __init__(self, master, question):
self.master = master
super().__init__(self.master)
self.id = QFrame.id
QFrame.id += 1
self.q = tk.StringVar()
self.q.set('None')
self.question, self.choices = question
self.grid_rowconfigure(0, weight=1)
for idx in range(4):
self.grid_columnconfigure(idx, weight=1)
self.q_label = tk.Label(self, text=f'Question {self.id}: {self.question}')
self.q_label.grid(row=0, column=0, columnspan=4, sticky="w")
self.choose = []
for idx, choice in enumerate(self.choices):
txt, value = choice
qr = tk.Radiobutton(self, text=txt, variable=self.q, value=value)
self.choose.append(qr)
qr.grid(row=1, column=idx, columnspan=1, sticky="ew")

Related

best way to make a text box that will show text

I am new to Python and am using Tkinter to create a basic GUI for a game.
I have got some buttons an image and numerous labels to work, but I am wondering..
What is the best way to get a large, initially blank text box on the GUI, and how would I go about having the text box update on the press of a "next" button.
I need it to scroll through text with each press, showing the next relevant line.
The text that is shown will depend on the choice(s) that are made, so variables like current location etc are necessary.
The aim is to make a simple game that allows you to read through the text with the Next button, then make choices etc, a mostly text-based adventure game.
I'll post what I have already below. Yes I know it's terrible, this is my first try so don't judge too harshly on my mistakes.
Any tips, advice or methods are much appreciated.
Some things to note:
My quit button isn't working yet, not too sure why.
I would love to figure out how to store variables based on what the user inputs, via an input box that can be prompted when an input is required from the user.
Also, happy to start from scratch if it's easier.
# Widgets:
import sys #Imports the system commands which makes it possible to terminate the program
import time #Imports the time module to allow delays in script
import os #Imports os to make it possible to play music/sound
import random #Imports random variable to allow for random number generation
import pickle #allows the game state to be saved.
from tkinter import * # imports tkinter
import tkinter as tk
from tkinter import *
from tkinter import messagebox
from textwrap import wrap # imports text wrap
#base variables for testing
character_Gold = 1
character_Health = 100
character_base_Health = 100
character_Strength = 10
character_Dexterity = 10
character_Constitution = 10
character_Intelligence = 10
character_Wisdom = 10
character_Charisma = 10
character_base_Perception = 10
#Text Boxes
#Base Geometry and image
window = Tk()
TitleScreen = PhotoImage( file = 'test.gif' )
window.geometry("1100x600")
#defines
def close():
#win.destroy()
window.quit()
imgLbl = Label( window, image = TitleScreen )
label1 = Label( window, relief = 'groove', width = 4)
label2 = Label( window, relief = 'groove', width = 4)
label3 = Label( window, relief = 'groove', width = 4)
label4 = Label( window, relief = 'groove', width = 4)
label5 = Label( window, relief = 'groove', width = 4)
label6 = Label( window, relief = 'groove', width = 4)
label7 = Label( window, relief = 'groove', width = 4)
label8 = Label( window, relief = 'groove', width = 4)
label9 = Label( window, relief = 'groove' , width = 3)
label10 = Label( window, relief = 'groove' , width = 3)
label11 = Label( window, relief = 'groove' , width = 3)
label12 = Label( window, relief = 'groove' , width = 3)
label13 = Label( window, relief = 'groove' , width = 3)
label14 = Label( window, relief = 'groove' , width = 3)
label15 = Label( window, relief = 'groove' , width = 3)
label16 = Label( window, relief = 'groove' , width = 3)
TextLabel = Label( window, relief = 'groove', width = 50)
LocationLabel = Label( window, relief = 'groove', width = 18)
LocationBase = Label( window, relief = 'groove', width = 13)
NextBtn = Button( window )
MainText = Label( window, relief = 'groove', width = 40, height = 8)
QuitButton = Button(window, text="Quit",command=close)
# Geometry:
imgLbl.grid( row = 1, column = 1 , rowspan = 24 ) # Change Rowspan here to increase number of Rows and shrink gaps
label1.grid( row = 1, column = 2, padx = 10 )
label2.grid( row = 1, column = 4, padx = 10 )
label3.grid( row = 1, column = 5, padx = 10 )
label4.grid( row = 1, column = 6, padx = 10 )
label5.grid( row = 1, column = 7, padx = 10 )
label6.grid( row = 1, column = 8, padx = 10)
label7.grid( row = 1, column = 9, padx = 10)
label8.grid( row = 1, column = 10, padx = 5)
label9.grid( row = 2, column = 2, padx = (1, 10)) #Health
label10.grid(row = 2, column = 4, padx = 10) #STR
label11.grid(row = 2, column = 5, padx = 10) # DEX
label12.grid(row = 2, column = 6, padx = 10) # CON
label13.grid(row = 2, column = 7, padx = 10) #INT
label14.grid(row = 2, column = 8, padx = 10) #WIS
label15.grid(row = 2, column = 9, padx = 10) # CHA
label16.grid(row = 2, column = 10, padx= 10) # gold
TextLabel.grid( row = 26, column = 1, padx = 10) # instruction label
LocationLabel.grid( row = 2, column = 11, padx = 10) # dynamic location label, changes
LocationBase.grid( row = 1, column = 11, padx = 10) # location text only not dynamic
MainText.grid( row = 30, column = 1, padx = 10) # main text box
QuitButton.grid(row = 34, column = 14 , padx = 10) #Quit Button
NextBtn.grid( row = 26, column = 2, columnspan = 4 )
# Static Properties
window.title( ' The Adventure ')
NextBtn.configure( text = 'Next')
Current_Location = "Title Screen"
#DynamicProperties. BD is button facelift level, bg is colour.
label1.configure( text = 'HP:', bg = 'Red' )
label1.configure( bd = 8, relief=RAISED)
label2.configure( text = 'STR:', bg = 'Orange')
label2.configure( bd = 8, relief=RAISED)
label3.configure( text = 'DEX:', bg = 'Purple')
label3.configure( bd = 8, relief=RAISED)
label4.configure( text = 'CON:', bg = 'Green')
label4.configure( bd = 8, relief=RAISED)
label5.configure( text = 'INT:', bg = 'light green')
label5.configure( bd = 8, relief=RAISED)
label6.configure( text = 'WIS:', bg = 'white')
label6.configure( bd = 8, relief=RAISED)
label7.configure( text = 'CHA:', bg = 'light blue')
label7.configure( bd = 8, relief=RAISED)
label8.configure( text = 'GP:', bg = 'yellow')
label8.configure( bd = 8, relief=RAISED)
label9.configure( text = character_Health)
label9.configure( bd = 6, relief=RAISED)
label10.configure( text = character_Strength)
label10.configure( bd = 6, relief=RAISED)
label11.configure( text = character_Dexterity)
label11.configure( bd = 6, relief=RAISED)
label12.configure( text = character_Constitution)
label12.configure( bd = 6, relief=RAISED)
label13.configure( text = character_Intelligence)
label13.configure( bd = 6, relief=RAISED)
label14.configure( text = character_Wisdom)
label14.configure( bd = 6, relief=RAISED)
label15.configure( text = character_Charisma)
label15.configure( bd = 6, relief=RAISED)
label16.configure( text = character_Gold)
LocationLabel.configure( text = Current_Location, fg = 'White', bg = 'Black')
LocationLabel.configure( bd = 8, relief=RAISED) # raises the button up to look 3d
LocationBase.configure( text = "Your Location:", fg = "black", bg = "White") #"location" text above tab that changes actual location
LocationBase.configure( bd = 8, relief=RAISED)
TextLabel.configure( text = "Welcome To The Adventure. Click 'Next' to begin!") # instruction label
TextLabel.configure( bd = 2, relief=RAISED)
MainText.configure( text = '''This is the large box where \n the main game text should go.''', fg = "Black", bg = "White") # use \n for a NEWLINE
MainText.configure( bd = 10, relief=RAISED)
NextBtn.configure( bd = 8, relief=RAISED) # raises next button
QuitButton.configure( bd = 2, relief=RAISED, text="Quit",command=close)
#Sustain Window:
window.mainloop()

Adding scrollbar widget to Tkinter GUI results in errors

I have written the following code to get the user input. But I am not able to add a scrollbar to it. I want to place a vertical scrollbar because I am not able to view all the input labels on my screen.
I first tried:
v = Scrollbar(root, orient='vertical')
v.config(command=root.yview)
It gave me the following error:
File "/Users/aaditya/Desktop/Blender_software/Blender_algo_exp/testing.py", line 235, in <module>
label1.grid(row = 1, column = 0, padx = 10, pady = 10)
File "/opt/anaconda3/envs/blender_env/lib/python3.9/tkinter/__init__.py", line 2486, in grid_configure
self.tk.call(
_tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack
After that I tried the following:
myscroll = Scrollbar(root)
myscroll.pack(side = RIGHT, fill = Y)
Which resulted in the following error:
AttributeError: '_tkinter.tkapp' object has no attribute 'yview'
How can I fix this?
This is my entire code:
# Driver code
if __name__ == "__main__" :
root = Tk()
# v = Scrollbar(root, orient='vertical')
# v.config(command=root.yview)
# myscroll = Scrollbar(root)
# myscroll.pack(side = RIGHT, fill = Y)
root.configure(background = 'light gray')
root.geometry("700x700")
root.title("Blender Software")
label1 = Label(root, text = "Total Quantity: ",
fg = 'black', bg = 'white')
label2 = Label(root, text = "Percentage of Solid Scrap : ",
fg = 'black', bg = 'white')
label3 = Label(root, text = "Cr min : ",
fg = 'black', bg = 'white')
label4 = Label(root, text = "Cr max : ",
fg = 'black', bg = 'white')
label1.grid(row = 1, column = 0, padx = 10, pady = 10)
label2.grid(row = 2, column = 0, padx = 10, pady = 10)
label3.grid(row = 3, column = 0, padx = 10, pady = 10)
label4.grid(row = 4, column = 0, padx = 10, pady = 10)
# Create a entry box
# for filling or typing the information.
total_quantity = Entry(root)
per_solid_scrap = Entry(root)
Cr_min_input = Entry(root)
Cr_max_input = Entry(root)
# grid method is used for placing
# the widgets at respective positions
# in table like structure .
total_quantity.grid(row = 1, column = 1, padx = 10, pady = 10)
per_solid_scrap.grid(row = 2, column = 1, padx = 10, pady = 10)
Cr_min_input.grid(row = 3, column = 1, padx = 10, pady = 10)
Cr_max_input.grid(row = 4, column = 1, padx = 10, pady = 10)
button1 = Button(root, text = "Submit", bg = "red",
fg = "black", command = calculate_op)
button1.grid(row = 21, column = 1, pady = 10)
# Start the GUI
root.mainloop()
Pack and grid cannot be used at the same time. So since you called the pack for the scrollbar, you cannot manage the following widgets by grid anymore. An easy fix is to place the scrollbar with grid function instead. Apart from that, try using a function or class to make your code less lengthy because now it seems hard to read and purposeless.

Why does the entry widget not work in this case i put it in a frame, tkinter-python

So this is a basic clock and alarm that i am creating, and in the process i want the user to type in what hour and minute they want to set for the alarm. But the entry widget here is not responding.
import time
import tkinter as tk
current_date, current_time = 0, 0
def current_info(timeinfo): #function to get the current time and date
global current_date, current_time
# current time
current_time = time.strftime('%H:%M:%S')
current_date = time.strftime(r'%m/%d/%Y')
clock.after(200, timeinfo)
#Initialise the window
clock = tk.Tk()
clock.title('Easy CLock')
clock.configure(bg='#121212')
clock.columnconfigure(0, weight = 1)
clock.columnconfigure(1, weight = 1)
clock.columnconfigure(2, weight = 1)
clock.columnconfigure(3, weight = 1)
border_effects = {
"flat": tk.FLAT,
"sunken": tk.SUNKEN,
"raised": tk.RAISED,
"groove": tk.GROOVE,
"ridge": tk.RIDGE,
}
#Logo will be under the main parent
logo = tk.PhotoImage(file = r'C:\Users\User\VSC\Alarm\Logo1.png')
logo_size = logo.subsample(5)
#Time and Date function
def time_date():
current_info(time_date)
#Displays the time
c_time = tk.Label(f_time, text = current_time, fg='white', bg='#121212', font=('Verdana', 30))
c_date = tk.Label(f_time, text = current_date, font=('Verdana', 10), fg='white', bg='#121212')
c_time.grid(column=0, row=0)
c_date.grid(column=0, row=1)
#alarm button command
def alarm_func():
current_info(alarm_func)
c_time = tk.Label(f_alarm, text = current_time, fg='white', bg='#121212', font=('Verdana', 10))
c_date = tk.Label(f_alarm, text = current_date, font=('Verdana', 10), fg='white', bg='#121212')
def pressed_enter(): #Command for the enter button
set_label = tk.Label(f_alarm, text = f'Alarm has been set for {time_set}', fg ='white', bg = '#121212', borderwidth = 1, relief = border_effects['sunken'])
set_label.grid(column = 4, row = 0, sticky = 'W')
# Set the time and date for the alarm
set_time = tk.StringVar()
alarm_entry = tk.Entry(clock, textvariable = set_time)
set_time.set('H : M')
time_set = alarm_entry.get()
#label and entry to set alarm / Enter Button
c_label = tk.Label(f_alarm, text = 'Set Alarm: ', font = ('Verdana', 10), fg= 'white', bg ='#121212' )
alarm_enter = tk.Button(f_alarm, text = 'Enter', font = ('Verdana', 7), width = 5, command = pressed_enter)
#Pack the widgets
c_time.grid(row = 0, column = 0)
c_date.grid(column = 1 , row = 0)
alarm_enter.grid(row = 2, column = 3)
c_label.grid(row = 2, sticky = 'W')
alarm_entry.grid(row = 2, column = 1)
#configure the empty columns
f_alarm.columnconfigure(2, minsize = 10)
def recall_frame(event):
if event == f_alarm:
event.grid_forget()
f_time.grid(column=0, row =1, columnspan = 4, sticky = 'N')
elif event == f_time:
event.grid_forget()
f_alarm.grid(column=0, row=1, columnspan = 4, sticky = 'W')
def back_func():
pass
#Creating Frames
f_time = tk.Frame(clock) #Clock Button
f_alarm = tk.Frame(clock) #Alarm Buttton
#configure the frames
f_time.configure(bg = '#121212')
f_alarm.configure(bg = '#121212')
#Setting label in the frame
f_lbl = tk.Label(clock, text= ' Simplistic Clock', image = logo_size, font=('Verdana', 30), fg='white', bg='#121212', compound = tk.LEFT, padx = 35)
time_but = tk.Button(clock, text='Clock', command= lambda :[time_date(), recall_frame(f_alarm)], bg='#f39c12', relief = border_effects['ridge'], pady = 7)
alarm_but = tk.Button(clock, text = 'Alarm', command = lambda :[alarm_func(), recall_frame(f_time)], bg='#f39c12', relief = border_effects['ridge'], pady = 7)
quit_but = tk.Button(clock, text='Exit', command = clock.quit, bg='#f39c12', relief = border_effects['ridge'], pady = 7)
back_but = tk.Button(clock, text = 'Back ', command = back_func, bg='#f39c12', relief = border_effects['ridge'], pady = 7)
f_lbl.config(borderwidth = 4, relief = border_effects['sunken'])
#Putting it on the frames
f_lbl.grid(column = 0, row = 0, columnspan = 5, sticky = 'EW')
time_but.grid(column = 0, row = 3, sticky = 'EW')
alarm_but.grid(column = 1, row = 3, sticky = 'EW')
quit_but.grid(column = 3, row = 3, sticky = 'EW')
back_but.grid(column = 2, row = 3, sticky = 'EW')
clock.mainloop()
i tried testing an entry widget outside the frame and the entry widget was able to work, is it because the frame f_alarm is not looping constantly in the background?
When someone clicks on your button which activates the pressed_enter() function, it will call that function again every time which will set the time to H:M and it will get that value as the set_time.get() is called immediately after.
You're also creating a new Entry every time the button is being clicked because you put alarm_entry = tk.Entry(clock, textvariable=set_time)
in there as well. You should only put the set_time.get inside of that button so that it gets the value that is currently filled in into the Entry. The other things like
set_time = tk.StringVar()
alarm_entry = tk.Entry(clock, textvariable=set_time)
set_time.set('H : M')
Should be put outside of that function so they don't get called every time someone clicks on the button.

The code is giving me syntax error even though I couldn't find any [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I am getting a syntax error that I cant find. Just a while ago it was working totally fine but then it suddenly started giving me error even though I never changed anything in that line of code. Can you take a look plz.
from tkinter import*
root = Tk()
# Variables
HEIGHT = 320
WIDTH = 500
# Functions:
def calculation():
global last
lst = []
e1 = En1.get()
e2 = En2.get()
e3 = En3.get()
e4 = En4.get()
e5 = En5.get()
lst.extend([e1,e2,e3,e4,e5])
print (list)
# Window:
canvas = Canvas(root, height = HEIGHT, width = WIDTH)
canvas.pack()
frame = Frame(root)
frame.place(relx = 0.1, rely = 0.1, relheight = 0.8, relwidth = 0.8)
# Widgets:
button = Button(frame, text='Calculate', padx = 50, pady = 3, command=calculation()
# Entries:
En1 = Entry(frame, bg = 'white')
En2 = Entry(frame, bg = 'white')
En3 = Entry(frame, bg = 'white')
En4 = Entry(frame, bg = 'white')
En5 = Entry(frame, bg = 'white')
# Label:
lb1 = Label(frame, text='How much does person A weight:', padx = 10, pady = 5, anchor = 'w')
lb2 = Label(frame, text='How much does person B weight:', padx = 10, pady = 5, anchor = 'w')
lb3 = Label(frame, text='How long is the chair:', padx = 10, pady = 5, anchor = 'w')
lb4 = Label(frame, text='How far is person A sitting from left side', padx = 10, pady = 5)
lb5 = Label(frame, text='How far is person B sitting from right side', padx = 10, pady = 5)
# Widget's position:
button.grid(row = 1, column = 1)
# Entries:
En1.grid(row = 1, column = 0)
En2.grid(row = 3, column = 0)
En3.grid(row = 5, column = 0)
En4.grid(row = 7, column = 0)
En5.grid(row = 9, column = 0)
# Labels:
lb1.grid(row = 0, column = 0)
lb2.grid(row = 2, column = 0)
lb3.grid(row = 4, column = 0)
lb4.grid(row = 6, column = 0)
lb5.grid(row = 8, column = 0)
# Result:
result = Label(frame, bg = 'white')
result.grid(row = 2, column = 1, rowspan=3)
root.mainloop()
If I run this code it gives me the following error.
File ".\Second.py", line 32
En1 = Entry(frame, bg = 'white')
^
SyntaxError: invalid syntax
By the way, it is not only line 32 that gives me this error. I tried to comment out the lines with error and it seems like Every single widget in the code gives me the same syntax error. I tried to find it but I coulndn't.
I am a newbie in python so quiet possibly I have done some dumb mistake I am unaware of.
button = Button(frame, text='Calculate', padx = 50, pady = 3, command=calculation()
There doesn't seem to be a closing parenthesis here. Could that be the issue?

Linking multiple interfaces in python using tkinter

Thank you for reading. I am new to coding and have googled this problem and consulted text resources without success. I do not have access to a teacher. I did my best to create a version of the problem in as simple a way as I could. I greatly appreciate your time and effort in helping me to solve this problem.
I am working in Python using IDLE and tkinter.
I am trying to link two interfaces using tkinter. I designed the first interface to ask for two entries, (defined as factor1 and factor2). I also put a button on the first interface. I am trying to create a command for the button to open the second interface.
Once, the second interface is open, the second interface is designed to use the user inputs into the two entries from the first interface (defined as factor1 and factor2) as labels.
#First Interface
from tkinter import *
from tkinter.messagebox import *
master = Tk()
master.title('Getting Started')
label1 = Label(master, text = 'what is factor 1:', relief = 'groove', width = 19)
label2 = Label(master, text = 'what is factor 2:', relief = 'groove', width = 19)
factor1 = Entry(master, relief = 'groove', width = 12)
factor2 = Entry(master, relief = 'groove', width = 12)
button2 = Button(master, text = 'Go', relief = 'groove', width = 25)
label1.grid( row = 1, column = 1, padx = 10 )
label2.grid( row = 2, column = 1, padx = 10 )
factor1.grid( row = 1, column = 2, padx = 10 )
factor2.grid( row = 2, column = 2, padx = 10 )
button2.grid( row = 3, column = 1, columnspan = 2)
#Second Interface
from tkinter import *
from tkinter.messagebox import *
mydict = {'good':0.75, 'outstanding': 1}
master = Tk()
label1 = Label(master, text = 'proposal', relief = 'groove', width = 19)
label2 = Label(master, text = factor1, relief = 'groove', width = 19)
label3 = Label(master, text = factor2, relief = 'groove', width = 19)
label4 = Label(master, text = 'Proposal Score', relief = 'groove', width = 19)
label5 = Label(master, text = '1', relief = 'groove', width = 12)
entry1 = Entry(master, relief = 'groove', width = 12)
entry2 = Entry(master, relief = 'groove', width = 12)
blank1 = Entry(master, relief = 'groove', width = 12)
def show_answer():
c = float( mydict[entry1.get()]) *float( mydict[entry2.get()])
blank1.insert(0, c)
button1 = Button(master, text = 'Calculate Proposal Scores', relief = 'groove', width = 25, command = show_answer)
label1.grid( row = 1, column = 1, padx = 10 )
label2.grid( row = 1, column = 2, padx = 10 )
label3.grid( row = 1, column = 3, padx = 10 )
label4.grid( row = 1, column = 4, padx = 10 )
label5.grid( row = 2, column = 1, padx = 10 )
entry1.grid( row = 2, column = 2, padx = 10 )
entry2.grid( row = 2, column = 3, padx = 10 )
blank1.grid( row = 2, column = 4, padx = 10 )
button1.grid( row = 3, column = 2, columnspan = 2)
Right now, both interfaces are in one IDLE document. However, I am unsure whether they should be kept in separate files.
My questions are:
Should I use one IDLE file or two?
If one, how do I make two separate interfaces in one idle file?
If two, how do I link the information, so that the second interface can use the inputs entered in the first interface?
How do I create a command so that the button is able to signal to close interface one and open interface two?
I understand this question may be complicated. If you have any additional books or resources to recommend I would greatly appreciate it. Additionally, if you have any suggestions on how I could make this question better, I would greatly appreciate it. Thank you!
Whether you use one file or two is completely up to you. If the code was very long, I'd recommend splitting into two files, but it's short enough that there's nothing wrong with keeping it all in the same file.
What you should do, however, is to separate the code into two functions. One function will open the first window and ask the user to input the two factors. Then when the button is pressed, it will take the two factors and use them as arguments for the second function (which opens the 2nd window). The code looks like this:
from tkinter import *
from tkinter.messagebox import *
def first_interface():
master = Tk()
master.title('Getting Started')
label1 = Label(master, text = 'what is factor 1:', relief = 'groove', width = 19)
label2 = Label(master, text = 'what is factor 2:', relief = 'groove', width = 19)
factor1 = Entry(master, relief = 'groove', width = 12)
factor2 = Entry(master, relief = 'groove', width = 12)
def start_second_interface():
f1 = float(factor1.get())
f2 = float(factor2.get())
second_interface(f1, f2)
button2 = Button(master, text = 'Go', relief = 'groove', width = 25, command=start_second_interface)
label1.grid( row = 1, column = 1, padx = 10 )
label2.grid( row = 2, column = 1, padx = 10 )
factor1.grid( row = 1, column = 2, padx = 10 )
factor2.grid( row = 2, column = 2, padx = 10 )
button2.grid( row = 3, column = 1, columnspan = 2)
def second_interface(factor1, factor2):
mydict = {'good':0.75, 'outstanding': 1}
master = Toplevel()
label1 = Label(master, text = 'proposal', relief = 'groove', width = 19)
label2 = Label(master, text = factor1, relief = 'groove', width = 19)
label3 = Label(master, text = factor2, relief = 'groove', width = 19)
label4 = Label(master, text = 'Proposal Score', relief = 'groove', width = 19)
label5 = Label(master, text = '1', relief = 'groove', width = 12)
entry1 = Entry(master, relief = 'groove', width = 12)
entry2 = Entry(master, relief = 'groove', width = 12)
blank1 = Entry(master, relief = 'groove', width = 12)
def show_answer():
c = float( mydict[entry1.get()]) *float( mydict[entry2.get()])
blank1.insert(0, c)
button1 = Button(master, text = 'Calculate Proposal Scores', relief = 'groove', width = 25, command = show_answer)
label1.grid( row = 1, column = 1, padx = 10 )
label2.grid( row = 1, column = 2, padx = 10 )
label3.grid( row = 1, column = 3, padx = 10 )
label4.grid( row = 1, column = 4, padx = 10 )
label5.grid( row = 2, column = 1, padx = 10 )
entry1.grid( row = 2, column = 2, padx = 10 )
entry2.grid( row = 2, column = 3, padx = 10 )
blank1.grid( row = 2, column = 4, padx = 10 )
button1.grid( row = 3, column = 2, columnspan = 2)
first_interface()
This has solved all your problems in a single simple step: The code is neatly organized, and you can easily pass the two factors to the second window.
(P.S. I've used a tk.TopLevel instead of a tk.Tk for the second window. There should be exactly one tk.Tk instance in each program. If you use more than one, you're going to run into problems.)

Categories