Trying to embed tkinter checkboxes in a text box, within a toplevel - text

I am working on a simple database that tracks bicycle inventory. Deep within my program I am hitting a snag that has stumped me all day. I am trying to create a list of checkboxes in a text box, (to make use of the scrollbar), all within a toplevel popup.
I can't upload my entire code, it's just too much, but here is the snippet dumbed down to get the thing working:
class Delete_bike:
def __init__(self, master):
self.master = master
top = self.top = tk.Toplevel(self.master)
text_frame = tk.Frame(self.top)
text_frame.grid(row = 0, padx = 10, pady = 10)
scb = tk.Scrollbar(text_frame)
scb.grid(row = 0, column = 1, sticky = 'ns')
d_tb = tk.Text(text_frame, height = 8, width = 40, yscrollcommand = scb.set)
d_tb.configure(font = ('Times', 10, 'bold'))
d_tb.grid(row = 0, column = 0)
scb.config(command = d_tb.yview)
test_d = {}
for i in range(10):
test_d[i] = 0
for i in test_d:
test_d[i] = tk.IntVar()
cb = tk.Checkbutton(text = i, variable = test_d[i])
d_tb.window_create(tk.END, window = cb)
d_tb.insert(tk.END, '\n')
The true version makes use of drawing from a shelved dictionary to populate the extensive list of bikes.
When I run this, I get the following exception, which I do not understand at all:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python34\lib\tkinter\__init__.py", line 1538, in __call__
return self.func(*args)
File "C:\Users\Gregory\Desktop\Bike Roster v2.0.pyw", line 115, in delete_bike
x = Delete_bike(self.master)
File "C:\Users\Gregory\Desktop\Bike Roster v2.0.pyw", line 239, in __init__
d_tb.window_create(tk.END, window = cb)
File "C:\Python34\lib\tkinter\__init__.py", line 3296, in window_create
+ self._options(cnf, kw))
_tkinter.TclError: can't embed .52341336 in .52340888.52341000.52341112
So next, I copied the snippet to a stand alone program, copied next, which works perfectly fine. So can I not achieve my desired result in a toplevel? Granted I am new at all this and have no formal training or instruction on programming, but that seems to be the only difference I can see.
import tkinter as tk
from tkinter import ttk
import tkinter.scrolledtext as tkst
class Delete_bike:
def __init__(self, master):
self.master = master
# top = self.top = tk.Toplevel(self.master)
text_frame = tk.Frame(self.master)
text_frame.grid(row = 0, padx = 10, pady = 10)
scb = tk.Scrollbar(text_frame)
scb.grid(row = 0, column = 1, sticky = 'ns')
d_tb = tk.Text(text_frame, height = 8, width = 40, yscrollcommand = scb.set)
d_tb.configure(font = ('Times', 10, 'bold'))
d_tb.grid(row = 0, column = 0)
scb.config(command = d_tb.yview)
test_d = {}
for i in range(10):
test_d[i] = 0
for i in test_d:
test_d[i] = tk.IntVar()
cb = tk.Checkbutton(text = i, variable = test_d[i])
d_tb.window_create(tk.END, window = cb)
d_tb.insert(tk.END, '\n')
root = tk.Tk()
app = Delete_bike(root)
root.mainloop()
If I remove the hash-tag to activate the toplevel line of code and place the frame inside the toplevel, it generates the same error message. Left like this, it works.
And a second quick question, if I am doing something wrong here, and this can be achieved within a toplevel, can the scrolledtext module be used in lieu of the text box and scrollbar combination?
Thanks as always!

You aren't specifying the parent for the checkbutton, so it defaults to the root window. You can't have a widget with a parent in the root, but try to display it in a toplevel.
Make the checkbutton a child of the text widget.
cb = tk.Checkbutton(d_tb, ...)
Yes, you can use scrolledtext instead of a text and a scrollbar, but I don't see any advantage in doing so.

Related

I want my code to wait unless either of two buttons is pressed

ui.py
import tkinter as tk
sc = 0
q_txt = 'Can you please verify the pythagorous theorem using similarities of triangle.'
class Window():
var = tk.IntVar()
def __init__(self):
self.window = tk.Tk()
self.window.title('Guess if you can')
self.window.config(padx = 50, pady = 50, bg = '#130f4a')
self.window.minsize(width = 400, height = 300)
self.score = tk.Label(text = 'score: 0',fg = 'white' ,bg = "#130f4a", font = ('Ariel', 12, 'bold'))
self.score.grid(row = 0, column = 1)
self.true = tk.PhotoImage(file = '_tick.png')
self.false = tk.PhotoImage(file = '_cross.png')
self.cnvs = tk.Canvas(self.window, width = 300, height= 250, bg = 'white', highlightthickness = 0)
self.cnvs_txt = self.cnvs.create_text(300//2, 250//2, text = q_txt, font = ('Times 20 italic bold', 15), width = 200)
self.cnvs.grid(row = 1, column = 0, columnspan = 2, pady = 20)
V = tk.IntVar(0)
self.tick_btn = tk.Button(self.window, image = self.true, highlightthickness = 0, bg = 'green', command = lambda : V.set(1))
self.tick_btn.grid(row = 2, column = 0, pady = 5)
self.cross_btn = tk.Button(self.window, image = self.false, highlightthickness = 0, bg = 'red')
self.cross_btn.grid(row = 2, column = 1, pady =5)
def change_question(self, next_question):
self.cnvs.itemconfig(self.cnvs_txt, text = next_question)
def asktopress(self, V):
self.tick_btn.wait_variable(V)
self.window.mainloop()
main.py
import questions
import ui
QA = questions.que_and_ans
ob = ui.Window()
next_question = 'My name is anthony'
ob.asktopress()
ob.change_question(next_question)
questions.py
import json
with open('question_bank.txt') as file:
f = file.read()
data = json.loads(f)
que_and_ans = [(x['question'], x['correct_answer']) for x in data['results']]
Stuck at
So, basically I want to keep changing the question after either one of two buttons is pressed
Let say,
There is question#1 (boolean question True or False type only) and now the execution should have to wait unless and until tick_btn or cross_btn is pressed so depending on right or wrong it updates the score the next I think I'll be able to do but I'm stuck with bold sentence.
My search
I went through thread#1
python documentation
#1StOverflow
isClicked
The one I tried to implement
Error I'm facing
Traceback (most recent call last):
File "C:\Users\alphaowner\Desktop\#100_Days_of_Python\#34-Day\Project\main.py", line 2, in <module>
import ui
File "C:\Users\alphaowner\Desktop\#100_Days_of_Python\#34-Day\Project\ui.py", line 4, in <module>
class Window():
File "C:\Users\alphaowner\Desktop\#100_Days_of_Python\#34-Day\Project\ui.py", line 5, in Window
var = tk.IntVar()
File "C:\Users\alphaowner\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 539, in __init__
Variable.__init__(self, master, value, name)
File "C:\Users\alphaowner\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 346, in __init__
master = _get_default_root('create variable')
File "C:\Users\alphaowner\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 297, in _get_default_root
raise RuntimeError(f"Too early to {what}: no default root window")
RuntimeError: Too early to create variable: no default root window
The error you are receiving is because in ui.py, you are initializing/creating a Tkinter object/variable of IntVar() type, var = tk.IntVar(), before the tk.Tk() root is initialized, so the solution is:
class Window():
def __init__(self):
self.window = tk.Tk()
var = tk.IntVar()
self.window.title('Guess if you can')
Now, the question is what way do you want the execution of the program
to wait until tick_btn or cross_btn is pressed?
You don't need to take care of the program to wait, because it will itself wait until the user makes any move (presses cross, or presses tick, or closes the program.)
See, when the Tkinter window is in mainloop, its execution has started and now all you need to do is, change every question (as well as the score) depending upon what button user presses.
So, just call a function for both the buttons and in that function, check the answer, update the score, ask new question, and also display the result.
self.tick_btn = tk.Button(self.window, image = self.true, highlightthickness = 0, bg = 'white', command = lambda:self.check_answer(True))
self.tick_btn.grid(row = 2, column = 0, pady = 5)
self.cross_btn = tk.Button(self.window, image = self.false, highlightthickness = 0, bg = 'white', command = lambda:self.check_answer(False))
self.cross_btn.grid(row = 2, column = 1, pady =5)
self.window.mainloop()
def check_answer(self, val):
#all questions done!
if self.questionNo >= len(self.QA):
print("Done!")
else:
if (val == True and self.answer == "true") or (val == False and self.answer == "false"):
print("Correct")
self.var.set(self.var.get()+1) #works as self.var+=1
self.score["text"] = 'Score: '+str(self.var.get())
else:
#negative marking or do nothing
print("Wrong")
#Now move to next question
self.questionNo+=1
if self.questionNo < len(self.QA):
self.q_txt = self.QA[self.questionNo][0]
self.answer = self.QA[self.questionNo][1]
self.cnvs.itemconfig(self.cnvs_txt, text = self.q_txt)
else: #last question done
print("Your final score is "+str(self.var.get()))
Here is a link to my GitHub repo, I made changes to your code to create a True-False QnA program using Tkinter.

Calling variables located in a method of another class (Tkinter)

I am a beginner at this, so I appreciate your patience and understanding with regards to the problem I have got.
Background
What I am using: macOS, Python3, ATOM
I am trying to build a library that stores information on books available (Title, Author, Year, ISBN). My plan for this is to create a script for backend and frontend separately. Ultimately connecting it all on the frontend script through importing the backend script and using the functions designed there. And yes, I have used OOP before but only for building a blackjack game. tkinter's usage of class is kinda wack for me and I got lost.
Current Situation
I have the UI looking just the way I want it to and am currently creating functions to be used for commands attached to buttons. The issue is, I have the entry widget and the ScrolledText widget in two different classes representing two different frames (Top and Bottom) and while calling for the variable
title.val = tk.StringVar()
an error popped up:
Traceback (most recent call last):
/LIBfront.py", line 105, in <module>
class main():
/LIBfront.py", line 111, in main bottomleft = BottomFrame(win)
/LIBfront.py", line 52, in __init__ self.search_cmd()
/LIBfront.py", line 64, in search_cmd for row in LIBback.search_entry(TopFrame.title_val.get(), self.author_val.get(), year_val.get(), isbn_val.get()):
AttributeError: type object 'TopFrame' has no attribute 'title_val'
Here is a reduced version of the code, containing only one of the sections. EDIT: changes done based on feedback
import tkinter as tk
import tkinter.scrolledtext as tkst
import LIBback # This is just the backend script
# Creating top frame for user input
class TopFrame():
def __init__(self, win):
self.win = win
self.frame = tk.Frame(win, relief = 'groove')
self.frame.pack(fill = 'x', expand = False)
self.topwidgets()
def topwidgets(self):
self.title_val = tk.StringVar()
self.lbl1 = tk.Label(self.frame, text = 'Title:')
self.e1 = tk.Entry(self.frame, width = 25, textvariable = self.title_val)
self.lbl1.grid(row = 0, column = 0, ipadx = 10, ipady = 10)
self.e1.grid(row = 0, column = 1, sticky = 'e')
# Creating bottom frame for user interaction and results display
class BottomFrame():
def __init__(self, win):
self.win = win
self.frame1 = tk.Frame(win)
self.frame1.pack(fill = 'both', side = "left", expand = False)
self.frame2 = tk.Frame(win)
self.frame2.pack(fill = 'both', side = "left", expand = True)
self.widgets()
self.search_cmd()
def search_cmd(self):
self.txtbox.delete('1.0',tk.END) # Below this line is where the issue began
for row in LIBback.search_entry(self.title_val.get()):
self.txtbox.insert(tk.END, row)
def widgets(self):
self.button2 = tk.Button(self.frame1, text = 'Search Entry', height = 2 , width = 10, command = self.search_cmd)
self.button2.pack(side = 'top', fill = 'y', pady = 5, padx = 5)
def main():
win = tk.Tk()
win.title('Book Shop')
win.geometry("630x370")
top = TopFrame(win)
bottom = BottomFrame(top)
win.mainloop()
if __name__ == '__main__':
main()
What I have tried or tried to understand
The variable of interest is not declared as an attribute even though the method is declared and using that variable.
Accessing it through TopFrame.topwidgets.title_val.get(), in the form of [CLASS.FUNCTION.VAR.get()] did not work for me.
Mimicking other examples of OOP using tkinter whereby there is a 'master'? class, and declaring self.var = tk.StringVar() there and using a 'controller' to refer to it. Failed due to my lack of understanding in doing it that way.
My Question
How do I, in this case, call on that variable? and possibly, can you walk me through the process as to why it failed to declare it as an attribute of the class or how I failed to make them connect to each other?
Thank you very much for your help in advance! Really appreciate it!
You should pass top as an argument to BottomFrame so that title_val inside TopFrame can be accessed inside BottomFrame:
class BottomFrame():
def __init__(self, win, top):
self.win = win
self.top = top
...
def search_cmd(self):
self.txtbox.delete('1.0',tk.END)
for row in LIBback.search_entry(self.top.title_val.get()):
self.txtbox.insert(tk.END, row)
...
def main():
win = tk.Tk()
win.title('Book Shop')
win.geometry("630x370")
top = TopFrame(win)
bottom = BottomFrame(win, top) # pass top to BottomFrame
win.mainloop()

Using entry, StringVar and IntVar with Tkinter and Python3

I'm new to python and when explaining things please make it beginner friendly :).
Basically when I try to run a reddit crawler using tkinter, I get all kinds of erros that I don't understand, Thanks in advance, I really appreciate the community.
Here is some of the essential code:
def Exas():
import praw
imgcount = 0
reddit = praw.Reddit(client_id='CENSORED',
client_secret='CENSORED',
user_agent='TheBigScraper(By u/scrappermaster)',
username='scrappermaster',
password='thescrapperisscrap')
listoftitles = []
listofurls = []
# whichone = input('what subreddit do you want to access? ')
# endlimit = input('what number of pictures do you want to download? ')
whichoner = whichone
ender = int(endlimit.get())
subreddit = reddit.subreddit(whichone)
for submission in subreddit.hot(limit=int(ender)):
title = submission.title
link = submission.url
Both = title + " " + link
if '.jpg' in link :
listofurls.append(link)
listoftitles.append(title)
And around 50 lines further down:
import tkinter as tk
import colorama
root = tk.Tk()
root.title("InstagramBot")
root.geometry('320x125')
whichone = str(tk.StringVar())
endlimit = tk.StringVar()
lblWhichone = tk.Label(root, text = 'Subreddit Name:').grid(row = 0, column = 0, padx = 0, pady = 10)
entWhichone = tk.Entry(root, textvariable = whichone).grid(row = 0, column = 1)
lblIntendlimit = tk.Label(root, text = 'Number of Pictures:').grid(row = 1, column = 0, padx = 0, pady = 10)
entendlimit = tk.Entry(root, textvariable = endlimit).grid(row = 1, column = 1)
btn = tk.Button(root, text = 'Execute', command = Exas, fg='red', font='Helvetica 18 bold').grid(row = 5, column = 1)
root.mainloop()
root.title("InstagramBot")
The Weird Error Code:
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File "/Users/eucar/Documents/Testing/Compactor2000.py", line 28, in Exas
for submission in subreddit.hot(limit=int(ender)):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/praw/models/listing/generator.py", line 52, in __next__
self._next_batch()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/praw/models/listing/generator.py", line 62, in _next_batch
self._listing = self._reddit.get(self.url, params=self.params)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/praw/reddit.py", line 408, in get
data = self.request('GET', path, params=params)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/praw/reddit.py", line 534, in request
params=params)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/prawcore/sessions.py", line 185, in request
params=params, url=url)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/prawcore/sessions.py", line 130, in _request_with_retries
raise self.STATUS_EXCEPTIONS[response.status_code](response)
prawcore.exceptions.Redirect: Redirect to /subreddits/search
I've reduced Exas to a Tkinter based minimum. I've never used the praw library and don't have it installed.
def Exas():
whichoner = whichone.get()
ender = int(endlimit.get())
print(whichoner, ender)
Modifying your tkinter window for the StingVar I mentioned in the comment.
import tkinter as tk
root = tk.Tk()
root.title("InstagramBot")
root.geometry('320x125+50+50')
whichone = tk.StringVar()
endlimit = tk.StringVar()
lblWhichone = tk.Label(root, text = 'Subreddit Name:').grid(row = 0, column = 0, padx = 0, pady = 10)
entWhichone = tk.Entry(root, textvariable = whichone).grid(row = 0, column = 1)
# The grid method returns None! All these variables have the value None.
# I don't think it matters for what you're doing but may cause problems for you in the future.
# In general this is better.
# entWhichone = tk.Entry(root, textvariable = whichone)
# entWhichone.grid(row = 0, column = 1)
# entWhichone now points to a tk.Entry object.
lblIntendlimit = tk.Label(root, text = 'Number of Pictures:').grid(row = 1, column = 0, padx = 0, pady = 10)
entendlimit = tk.Entry(root, textvariable = endlimit).grid(row = 1, column = 1)
btn = tk.Button(root, text = 'Execute', command = Exas, fg='red', font='Helvetica 18 bold').grid(row = 5, column = 1)
root.mainloop()
If I type test and 42 into your window it echos Test and 42 to my console.
Your latest error message indicates that a StringVar has been passed to a praw function or method. In the Exas function you need:
whichoner = whichone.get() # Was it left at ... = whichone ?
If the above suggestions don't help, try printing whichoner and ender before anything else is called to check they return what you expect.
A style point is that in Python functions and variables are normally in lower case with underscore '_' to split, lbl_which_one instead of lblWhichone, exas for Exas. Classes are named with a capital tk.Entry creates an object of class Entry. Your code will still work just be bit more difficult for others to understand.

Code using Tkinter works in IDLE but not in terminal

This is (part of) my very first program. It uses Tkinter to output text in a scrolled textbox. I used Python 3.6.4 and IDLE and it works perfectly, but when I run it from terminal/Atom once I click ok after selecting the options from the dropdown menus it just closes without errors, while in IDLE it correctly outputs all the text in the textbox.
I want to use Py2app to make a standalone, but for this the code needs to execute properly from terminal.
Here are the main snippets from the code. I'm just coding for a few months so any detailed help would be much appreciated.
from tkinter import *
from collections import OrderedDict
from tkinter.scrolledtext import *
from collections import Counter
master = Tk()
master.title("App")
master.geometry("600x665")
master.lift()
master.attributes('-topmost', True)
mvar = IntVar()
mvar1 = IntVar()
var = StringVar(master)
var.set("Asc")
var1 = StringVar(master)
var1.set("Ar")
x = OptionMenu(master, var, "Ar", "Ta", "Ge","Can","Le","Vi","Li","Sc","Sa","Cap","Aq","Pi")
x.grid(column =2,row =1)
x1 = OptionMenu(master, var1, "Ar", "Ta", "Ge","Can","Le","Vi","Li","Sc","Sa","Cap","Aq","Pi")
x1.grid(column =2,row =2)
def redirector(inputStr):
txt.insert(INSERT, inputStr)
sys.stdout.write = redirector
def ok():
redirector("Thanks for using the app")
master.quit()
label1 = Label(text=" Welcome to the app",bg="#C2DFFF",font=("Times New Roman",18))
label1.grid(column=0,row=0)
label2 = Label(text="Ma: ",bg="#C2DFFF")
label2.grid(column=0,row=2)
txt = ScrolledText(master, bg="#C2DFFF", width = 97, height= 25, font = "Arial 11")
txt.grid(column = 0, row = 14, columnspan=3)
button = Button(master, text="OK", default ='active',command=ok).grid(column=2,row=11)
button = Button(master, text="Reset", default ='active',command=reset).grid(column=2,row=12)
button = Button(master, text ="Cancel",command = cancel).grid(column=0,row=11)
C1 = Checkbutton(master, state = ACTIVE, variable = mvar)
C1.grid(column = 1, row=2)
C2 = Checkbutton(master, state = ACTIVE, variable = mvar1)
C2.grid(column = 1, row=3)
master.mainloop()
This is how the GUI looks like
You cannot generally reassign sys.stdout.write - it is normally a read-only attribute of a built-in file object. The proper way to do output redirection is to assign a new object to sys.stdout, that has a write() method.
Your code works in IDLE only because IDLE has already replaced the built-in sys.stdout with its own redirection object, which is fully modifiable.

Cell formatting in Grid Geometry manager

I have this code:
from tkinter import *
from tkinter import ttk
class Application:
def __init__(self, master):#Change to game class when combining code
self.master = master#remove when combining code
self.frame_Canvas = ttk.Frame(self.master, width = 600, height = 600)
self.frame_Canvas.pack(side = 'left')
self.frame_Canvas.pack_propagate(False)
self.frame_Canvas.grid_propagate(False)
self.hangman = Canvas(self.frame_Canvas, width = 600, height = 600,
background = 'white').pack()
self.FullName = ttk.Label(self.frame_Canvas, text = "Full Name", background = 'white')#full name will be entered here
self.FullName.config(font=("TkDefaultFont", 20))
self.FullName.place(x = 10, y = 10)
self.frame_Interact = ttk.Frame(self.master, width = 200, height = 600)
self.frame_Interact.pack(side = 'right')
self.frame_Interact.pack_propagate(False)
self.frame_Interact.grid_propagate(False)
self.QuestionLabel = ttk.Label(self.frame_Interact, text = "Question:")
self.QuestionLabel.config(font=("TkDefaultFont", 20))
self.QuestionLabel.grid(column = 0, row = 0)
self.QuestionShow = Text(self.frame_Interact, height=1, width=8)#input question here
self.QuestionShow.config(font=("TkDefaultFont", 20))
self.QuestionShow.grid(column = 0, row = 1)#FIX THE FORMATTING OF QUESTION, GRID CELL TO LEFT, NOT BIG ENOUGTH?
self.AnswerEntry = ttk.Entry(self.frame_Interact, width = 10)#do later
def main():
root = Tk()
root.wm_title("Hangman")
Menu = Application(root)
root.resizable(width=False, height=False)
root.iconbitmap("windowicon.ico")
root.mainloop()
if __name__ == "__main__": main()
I dont know why, but the Answer box and label on the right side of my tkinter GUI is on the left side of its frame. I want it in the center. Does anyone know a way to frix it, or any improvements for the code so far. Thanks :)
There are two ways you can do this, first way will to be to use .pack() instead of .grid() since pack is very easy to use and does the aligning for you automatically.
So you can just replace:
self.QuestionLabel.grid(column = 0, row = 0)
# and
self.QuestionShow.grid(column = 0, row = 1)
With:
self.QuestionLabel.pack()
# and
self.QuestionLShow.pack()
This way isn't recommended for your situation whatsoever, since that will involve mixing pack and grid together which could cause future errors in your code.
As Bryan Oakley said:
it will cause errors immediately, if the widgets share the same parent. It won't ever cause problems if the widgets have different parents.
You should instead do this:
from tkinter import *
from tkinter import ttk
class Application:
def __init__(self, master):#Change to game class when combining code
self.master = master#remove when combining code
self.frame_Canvas = ttk.Frame(self.master, width = 600, height = 600)
self.frame_Canvas.pack(side = 'left')
self.frame_Canvas.pack_propagate(False)
self.frame_Canvas.grid_propagate(False)
self.hangman = Canvas(self.frame_Canvas, width = 600, height = 600,
background = 'white').pack()
self.FullName = ttk.Label(self.frame_Canvas, text = "Full Name", background = 'white')#full name will be entered here
self.FullName.config(font=("TkDefaultFont", 20))
self.FullName.place(x = 10, y = 10)
self.frame_Interact = ttk.Frame(self.master, width = 200, height = 600)
self.frame_Interact.pack(side = 'right')
self.frame_Interact.pack_propagate(False)
self.frame_Interact.grid_propagate(False)
Grid.columnconfigure(self.frame_Interact, 0, weight=1) # NOTE, THIS CHANGED
self.QuestionLabel = ttk.Label(self.frame_Interact, text = "Question:")
self.QuestionLabel.config(font=("TkDefaultFont", 20))
self.QuestionLabel.grid(column = 0, row = 0)
self.QuestionShow = Text(self.frame_Interact, height=1, width=8)
self.QuestionShow.config(font=("TkDefaultFont", 20))
self.QuestionShow.grid(column = 0, row = 1)
def main():
root = Tk()
root.wm_title("Hangman")
Menu = Application(root)
root.resizable(width=False, height=False)
root.iconbitmap("windowicon.ico")
root.mainloop()
if __name__ == "__main__":
main()
By adding Grid.columnconfigure(self.frame_Interact, 0, weight=1) it will help grid know how to allocate extra space. so that the label will try to take up the whole column. The same goes for rows if you're wondering, you can add Grid.rowconfigure(self.frame_Interact, 0, weight=1) to make the widgets fill the whole row.
And for some improvements to your code, you should change this line:
self.hangman = Canvas(self.frame_Canvas, width = 600, height = 600,
background = 'white').pack()
# to
self.hangman = Canvas(self.frame_Canvas, width = 600, height = 600, background = 'white')
self.hangman.pack()
Or else self.hangman will be None, as it is in your code.

Resources