I want my code to wait unless either of two buttons is pressed - python-3.x

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.

Related

Python - tkinter interface, using bind works only the first time (when running the program)

I'm attaching the code below.
There is an event on "focus out", the event triggers once when the code is initialized. Afterwards focusing out of the Spinbox does not trigger the event anymore. The question is, why? And, how do I fix that?
code :
import tkinter as tk
import os, time
def spinBoxValidateRange(widget_name):
print(str(widget_name.winfo_name()) + " focus out")
# Making a window, and giving it some settings
root = tk.Tk()
root.resizable(False, False)
root.winfo_toplevel().title("Test")
# creating a user GUI
default_pady = 2
default_padx = 5
sbx_max_img_width = tk.Spinbox(from_=500, to=5000, width = 4)
sbx_max_img_width.delete(0, 'end')
sbx_max_img_width.insert(0, 1000)
sbx_max_img_height = tk.Spinbox(from_=500, to=5000, width = 4)
sbx_max_img_height.delete(0, 'end')
sbx_max_img_height.insert(0, 1000)
sbx_max_img_width.grid(row = 0, column = 1, sticky = "W", pady = default_pady, padx = default_padx)
sbx_max_img_height.grid(row = 0, column = 3, sticky = "W", pady = default_pady, padx = default_padx)
sbx_max_img_width.bind("<FocusOut>", spinBoxValidateRange(sbx_max_img_width))
sbx_max_img_height.bind("<FocusOut>", spinBoxValidateRange(sbx_max_img_height))
root.mainloop()
Here is the corrected code (that works) -
import tkinter as tk
import os, time
def spinBoxValidateRange(some_widget):
print(str(some_widget.widget.winfo_name()) + " focus out")
# Making a window, and giving it some settings
root = tk.Tk()
root.resizable(False, False)
root.winfo_toplevel().title("Test")
# creating a user GUI
default_pady = 2
default_padx = 5
sbx_max_img_width = tk.Spinbox(from_=500, to=5000, width = 4)
sbx_max_img_width.delete(0, 'end')
sbx_max_img_width.insert(0, 1000)
sbx_max_img_height = tk.Spinbox(from_=500, to=5000, width = 4)
sbx_max_img_height.delete(0, 'end')
sbx_max_img_height.insert(0, 1000)
sbx_max_img_width.grid(row = 0, column = 1, sticky = "W", pady = default_pady, padx = default_padx)
sbx_max_img_height.grid(row = 0, column = 3, sticky = "W", pady = default_pady, padx = default_padx)
sbx_max_img_width.bind("<FocusOut>", lambda parameter = sbx_max_img_width: spinBoxValidateRange(parameter))
sbx_max_img_height.bind("<FocusOut>", lambda parameter = sbx_max_img_height: spinBoxValidateRange(parameter))
root.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.

Python 2 tkinter, a loan window appears when it has not been called for

I have come across an issue with using the tkinter message box, when a user of my application presses the English flag and then goes to Log-out in the top right hand corner a message box appears but also another box appears with the window title 'tk', I have not made or called any such window so my theory is that the window is coming from some place with the message box or maybe its something I have mistakenly done in my code which I cant see.
here is my code below;
import tkinter
from tkinter import *
from tkinter import messagebox as box
Title_Text = 25
Title_Font = "Courier"
Font = 'Ariel'
Rest_Text = 16
Background_Colour = 'Light blue'
def EngFlag():
print('Hello world')
def LogOut1():
response = box.askquestion ('?', 'Are You Sure?')
if response == 'yes':
try:
window.destroy()
except:
Eng_window.destroy()
def back1():
Home_Screen()
def Home_Screen():
global window
window = Tk()
window.geometry('1366x768')
window.configure(background = Background_Colour)
window.title('Local Languages Learning System')
window.resizable(width=False, height=False)
try:
Eng_window.destroy()
except:
pass
Title1 = Label(window, text = 'Local Languages Home Screen', bg = Background_Colour)
Title1.config(font=("Courier", Title_Text))
Title1.pack()
Title1.place(y = 1, x = 450)
Question_Label = Label(window, text = 'Please Pick The Language You Wish To Learn', bg = Background_Colour)
Question_Label.config(font=(Font, Rest_Text))
Question_Label.pack()
Question_Label.place(y = 200, x = 495)
Log_Out = Button(window, text = 'Log-Out', height = 1, width = 8, command = LogOut1)
Log_Out.pack()
Log_Out.place(y = 5, x = 1290)
help_btn = Button(window, text = 'Help', height = 1, width = 8, command = None)
help_btn.pack()
help_btn.place(y = 45, x = 1290)
English_Flag = PhotoImage(file = 'EnglishFlag.gif')
English_Flag_btn = Button(window, image = English_Flag, command = English_Home_Screen)
English_Flag_btn.pack(side = LEFT, padx = 10)
English_Flag_btn.place(y = 350, x = 300)
Polish_Flag = PhotoImage(file = 'PolishFlag.gif')
Polish_Flag_btn = Button(window, image = Polish_Flag, command = EngFlag)
Polish_Flag_btn.pack(side = LEFT, padx = 10)
Polish_Flag_btn.place(y = 350, x = 600)
Italian_Flag = PhotoImage(file = 'ItalianFlag.gif')
Italian_Flag_btn = Button(window, image = Italian_Flag, command = None)
Italian_Flag_btn.pack(side = LEFT, padx = 10)
Italian_Flag_btn.place(y = 350, x = 900)
window.mainloop()
def English_Home_Screen():
global Eng_window
Eng_window = Tk()
Eng_window.geometry('1366x768')
Eng_window.configure(background = Background_Colour)
Eng_window.title('Local Languages Learning System')
Eng_window.resizable(width=False, height=False)
window.destroy()
Title1 = Label(Eng_window, text = 'Local Languages\nEnglish Home Screen', bg = Background_Colour)
Title1.config(font=("Courier", Title_Text))
Title1.pack()
Title1.place(y = 1, x = 450)
Log_Out = Button(Eng_window, text = 'Log-Out', height = 1, width = 8, command = LogOut1)
Log_Out.pack()
Log_Out.place(y = 5, x = 1290)
Back = Button(Eng_window, text = 'Back', height = 1, width = 8, command = back1)
Back.pack()
Back.place(y = 5, x = 1210)
help_btn = Button(Eng_window, text = 'Help', height = 1, width = 8, command = None)
help_btn.pack()
help_btn.place(y = 45, x = 1290)
Play_all = Button(Eng_window, text = 'Play All Games', height = 2, width = 20, command = None)
Play_all.pack()
Play_all.place(y = 100, x = 320)
Multiple_Choice = Button(Eng_window, text = 'Play Multiple Choice Game', height = 2, width = 20, command = None)
Multiple_Choice.pack()
Multiple_Choice.place(y = 100, x = 510)
Picture = Button(Eng_window, text = 'Play Picture Game', height = 2, width = 20, command = None)
Picture.pack()
Picture.place(y = 100, x = 700)
Memory = Button(Eng_window, text = 'Play Memory Game', height = 2, width = 20, command = None)
Memory.pack()
Memory.place(y = 100, x = 890)
LeaderBoard = Button(Eng_window, text = 'LeaderBoard', height = 2, width = 20, command = None)
LeaderBoard.pack()
LeaderBoard.place(y = 160, x = 600)
Home_Screen()
Apologies for it being so long but to actually see the problem you have to have all the code. Any help or fixies would be great.
Now there are several issues with your code and some I will address.
First off what you are trying to do is very complicated when using a Non-OOP method. I have re-written your code as OOP to provide some ease of use and readability.
For the most part you should avoid using global the easiest way to do this is to use class attributes instead. This allows for you to have a variable that can be seen by any method within the class.
Some helpful tips:
Do not import tkinter twice.
Instead of doing:
import tkinter
from tkinter import *
from tkinter import messagebox as box
Do this instead:
import tkinter as tk
from tkinter import messagebox
Your Try/Except function will not work as you expect as Eng_window.destroy() will not return an error regardless of if the window is there or not. So it will always attempt to destroy Eng_window and never window
Instead do this:
# This will check if the instance of Eng_self_window exist first.
if tk.Toplevel.winfo_exists(self.Eng_self_window):
self.Eng_self_window.destroy()
else:
self.window.destroy()
Let me know if you have any questions on the class set up.
It can be done using global's but its not as clean and harder to deal with.
Here I have moved your code into a class and rearranged some stuff.
import tkinter as tk
from tkinter import messagebox
class Home_Screen(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.Title_Text = 25
self.Title_Font = "Courier"
self.Font = 'Ariel'
self.Rest_Text = 16
self.Background_Colour = 'Light blue'
self.window = parent
self.window.geometry('1366x768')
self.window.configure(background = self.Background_Colour)
self.window.title('Local Languages Learning System')
#self.window.resizable(width=False, height=False)
Title1 = tk.Label(self.window, text = 'Local Languages Home Screen', bg = self.Background_Colour)
Title1.config(font=("Courier", self.Title_Text))
Title1.pack()
Title1.place(y = 1, x = 450)
Question_Label = tk.Label(self.window, text = 'Please Pick The Language You Wish To Learn', bg = self.Background_Colour)
Question_Label.config(font=(self.Font, self.Rest_Text))
Question_Label.pack()
Question_Label.place(y = 200, x = 495)
Log_Out = tk.Button(self.window, text = 'Log-Out', height = 1, width = 8, command = self.LogOut1)
Log_Out.pack()
Log_Out.place(y = 5, x = 1290)
help_btn = tk.Button(self.window, text = 'Help', height = 1, width = 8, command = None)
help_btn.pack()
help_btn.place(y = 45, x = 1290)
self.English_Flag = tk.PhotoImage(file = 'EnglishFlag.gif')
self.English_Flag_btn = tk.Button(self.window, image = self.English_Flag, command = self.English_Home_Screen)
self.English_Flag_btn.pack(side = tk.LEFT, padx = 10)
self.English_Flag_btn.place(y = 350, x = 300)
self.Polish_Flag = tk.PhotoImage(file = 'PolishFlag.gif')
self.Polish_Flag_btn = tk.Button(self.window, image = self.Polish_Flag, command = self.EngFlag)
self.Polish_Flag_btn.pack(side = tk.LEFT, padx = 10)
self.Polish_Flag_btn.place(y = 350, x = 600)
self.Italian_Flag = tk.PhotoImage(file = 'ItalianFlag.gif')
self.Italian_Flag_btn = tk.Button(self.window, image = self.Italian_Flag, command = None)
self.Italian_Flag_btn.pack(side = tk.LEFT, padx = 10)
self.Italian_Flag_btn.place(y = 350, x = 900)
def English_Home_Screen(self):
self.Eng_self_window = tk.Toplevel(self.window)
self.Eng_self_window.geometry('1366x768')
self.Eng_self_window.configure(background = self.Background_Colour)
self.Eng_self_window.title('Local Languages Learning System')
#Eng_self.window.resizable(width=False, height=False)
Title1 = tk.Label(self.Eng_self_window, text = 'Local Languages\nEnglish Home Screen', bg = self.Background_Colour)
Title1.config(font=("Courier", self.Title_Text))
Title1.pack()
Title1.place(y = 1, x = 450)
Log_Out = tk.Button(self.Eng_self_window, text = 'Log-Out', height = 1, width = 8, command = self.LogOut1)
Log_Out.pack()
Log_Out.place(y = 5, x = 1290)
Back = tk.Button(self.Eng_self_window, text = 'Back', height = 1, width = 8, command = self.back1)
Back.pack()
Back.place(y = 5, x = 1210)
help_btn = tk.Button(self.Eng_self_window, text = 'Help', height = 1, width = 8, command = None)
help_btn.pack()
help_btn.place(y = 45, x = 1290)
Play_all = tk.Button(self.Eng_self_window, text = 'Play All Games', height = 2, width = 20, command = None)
Play_all.pack()
Play_all.place(y = 100, x = 320)
Multiple_Choice = tk.Button(self.Eng_self_window, text = 'Play Multiple Choice Game', height = 2, width = 20, command = None)
Multiple_Choice.pack()
Multiple_Choice.place(y = 100, x = 510)
Picture = tk.Button(self.Eng_self_window, text = 'Play Picture Game', height = 2, width = 20, command = None)
Picture.pack()
Picture.place(y = 100, x = 700)
Memory = tk.Button(self.Eng_self_window, text = 'Play Memory Game', height = 2, width = 20, command = None)
Memory.pack()
Memory.place(y = 100, x = 890)
LeaderBoard = tk.Button(self.Eng_self_window, text = 'LeaderBoard', height = 2, width = 20, command = None)
LeaderBoard.pack()
LeaderBoard.place(y = 160, x = 600)
def EngFlag(self):
print('Hello world')
def LogOut1(self):
response = messagebox.askquestion ('?', 'Are You Sure?')
if response == 'yes':
if tk.Toplevel.winfo_exists(self.Eng_self_window):
self.Eng_self_window.destroy()
else:
self.window.destroy()
def back1(self):
print("Go back")
self.Eng_self_window.destroy()
root = tk.Tk()
Home_Screen(root)
root.mainloop()
Quick fix; Don't use multiple instances of Tk. Instead, use Toplevel and hide & show the root window. Add:
...
Background_Colour = 'Light blue'
root = Tk()
root.withdraw()
...
and replace:
...
if response == 'yes':
try:
window.destroy()
except:
Eng_window.destroy()
...
global window
window = Tk()
...
global Eng_window
Eng_window = Tk()
with:
...
if response == 'yes':
root.destroy()
...
global window
window = Toplevel()
...
global Eng_window
Eng_window = Toplevel()

Python 3 tkinter insert file contents into a text box

Okay so I have done about 10 days of searching and I caved in so I'm turning to the community for help.
I am using python 3.6 and tkinter as a user interface.
The basic's of what I'm trying to accomplish is that I have a file that I open and search for a word within the file and insert all the lines that word falls on.
My issue is that its only inserting the first line it finds and I need it to insert all the lines it finds. Sorry for wet coding I'll dry it up once I have functionality later
here's a sample of my code (it's not the full thing but it should give you more than enough info about what I'm trying to accomplish):
import tkinter as tk
from tkinter import ttk
# i added all my imports that this class use's in case you guys think they could pose a problem but they shouldn't be a issue
class EXAMPLEapp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.iconbitmap(self, default = "dlm64.ico")
tk.Tk.wm_title(self, "Example.")
self.FILE_MENU_BAR()
self.minsize(width = 360, height = 200)
container = tk.Frame(self)
container.grid(row=0,column=0, sticky="nsew")
container.grid_rowconfigure(0, weight = 1)
container.grid_columnconfigure(0, weight = 1)
self.frames = {}
for FRAME in (SearchPage):
frame = FRAME(container, self)
self.frames[FRAME] = frame
frame.grid(row = 0, column = 0, sticky = "nsew")
self.show_frame(SearchPage)
def FILE_MENU_BAR(self):
#File
self.menubar = tk.Menu()
self.configure(menu = self.menubar)
File_Menu = tk.Menu(self.menubar, tearoff = False)
self.menubar.add_cascade(label = "File", menu = File_Menu)
File_Menu.add_command(label = "EXIT" , command = self.File_EXIT)
# Edit Menu
Edit_Menu = tk.Menu(self.menubar, tearoff = False)
self.menubar.add_cascade(label = "Edit", menu = Edit_Menu)
Edit_Menu.add_command(label = "cut", underline = 2, command = self.Edit_Cut)
Edit_Menu.add_command(label = "copy", underline = 0, command = self.Edit_Copy)
def File_EXIT(self):
sys.exit(0)
def Edit_Cut(self):
print("CUT")
def Edit_Copy(self):
print("COPY")
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class SearchPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text = "Search Inventory", font = ("Helvetica", 20, 'bold', 'underline'))
label.grid(row = 0, column = 1, sticky = "nsew", pady = (0,0), padx = (0,0))
button0 = ttk.Button(self, text = "Inventory Search")
button0.grid(row = 0, column = 0, sticky = "nsew", pady = 0, padx = (0,10))
button1 = ttk.Button(self, text = "New Inventory", command = lambda: controller.show_frame(CreatePage))
button1.grid(row = 1, column = 0, sticky = "nsew", pady = 0, padx = (0,10))
button2 = ttk.Button(self, text = "Edit Invetory", command = lambda: controller.show_frame(EditPage))
button2.grid(row = 2, column = 0, sticky = "nsew", pady = 0, padx = (0,10))
button3 = ttk.Button(self, text = "Ship", command = lambda: controller.show_frame(ShipPage))
button3.grid(row = 3, column = 0, sticky = "nsew", pady = 0, padx = (0,10))
button4 = ttk.Button(self, text = "Graph", command = lambda: controller.show_frame(PlotPage))
button4.grid(row = 4, column = 0, sticky = "nsew", pady = 0, padx = (0,10))
DATE_VAR = tk.StringVar()
def DATE_SEARCH():
USER_TEXT = DATE_VAR.get()
with open('SAMPLE.txt', 'r') as searchfile:
for line in searchfile:
if USER_TEXT == '':
LABEL = tk.Text(self, width = 30, height = 2, wrap = tk.WORD, foreground = 'red')
LABEL.grid(row = 6, column = 3, sticky = "nsew", pady = (0,0), padx = (20,0))
LABEL.insert(1.0, "PLEASE ENTER A VALUE")
LABEL.configure(state = 'disabled')
break
elif USER_TEXT in line:
LABEL = tk.Text(self, width = 100, height = 4, wrap = tk.WORD)
LABEL.grid(row = 6, column = 3, sticky = "e", pady = (0,0), padx = (20,0))
LABEL.insert(1.0, line)
LABEL.configure(state = 'disabled')
ScrollBar = tk.Scrollbar(self)
ScrollBar.config(command = LABEL.yview)
LABEL.config(yscrollcommand = ScrollBar.set)
ScrollBar.grid(row = 6, column = 4, sticky = "e")
break
else:
LABEL = tk.Text(self, width = 30, height = 2, wrap = tk.WORD, foreground = 'red')
LABEL.grid(row = 6, column = 3, sticky = "nsew", pady = (0,0), padx = (20,0))
LABEL.insert(1.0, "INVENTORY DOES NOT EXIST")
LABEL.configure(state = 'disabled')
DATE_Search_label = tk.Label(self, text = "Search by DATE", font = ("Helvetica", 9))
DATE_Search_label.grid(row = 5, column = 1, sticky = "nsew")
DATE_Search_Entry = tk.Entry(self, textvariable = DATE_VAR)
DATE_Search_Entry.grid(row = 6, column = 1, sticky = "nsew", pady = 0, padx = 2)
DATE_SEARCH_BUTTON = ttk.Button(self, text = "Search", command = DATE_SEARCH)
DATE_SEARCH_BUTTON.grid(row = 6, column = 2, sticky = "nsew")
app = EXAMPLEapp()
app.mainloop()
EDIT:
I have made several changes to your code.
There were way too many emblems with the way you had it set up.
As I am not 100% sure how what you are trying to accomplish I have made progress with your code.
Below is the edited version of your code.
I also created a text file on my end to test with and it seams to have worked so let me know if this is getting close to what you are attempting to do.
A few notes:
1st I moved everything into one class. The way you had it set up was just not going to work without some major changes.
2nd I needed to add self. to many of your variables because they are variables that we need to interact with in the class.
3rd I changed they way you get the data from the entry box. The way you were doing it was just not working so I simplified it by adding .get() function to the entry variable.
4th but probably should have been the 1st thing I mentions. The way you had your main Tk() window starting was odd. I changed how root was created and how we pass it into the class. This seams to make more sense to me.
This is much better to use IMO.
Let me know what parts you still need explanation on and I will make updates to my answer as needed.
Update:
change the while open statement a bit. You do not need to recreate the text box and reconfigure it ever for loop this is not good and will prevent you from seeing multiple items. Also I do not believe you can have a multi line label thought I have never tried. Lets change this to a text box this should do what we need.
import tkinter as tk
from tkinter import ttk
class EXAMPLEapp(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.root = parent
self.root.wm_title("TM Duch\'e Nut CO.")
self.FILE_MENU_BAR()
self.root.minsize(width = 360, height = 200)
self.container = tk.Frame(self.root)
self.container.grid(row=0,column=0, sticky="nsew")
self.container.grid_rowconfigure(0, weight = 1)
self.container.grid_rowconfigure(6, weight = 0)
self.container.grid_columnconfigure(0, weight = 1)
self.container.grid_columnconfigure(3, weight = 0)
self.label = tk.Label(self.root, text = "Search Inventory", font = ("Helvetica", 20, 'bold', 'underline'))
self.label.grid(row = 0, column = 1, sticky = "nsew", pady = (0,0), padx = (0,0))
self.button0 = ttk.Button(self.root, text = "Inventory Search")
self.button0.grid(row = 0, column = 0, sticky = "nsew", pady = 0, padx = (0,10))
self.button1 = ttk.Button(self.root, text = "New Inventory", command = lambda: controller.show_frame(CreatePage))
self.button1.grid(row = 1, column = 0, sticky = "nsew", pady = 0, padx = (0,10))
self.button2 = ttk.Button(self.root, text = "Edit Invetory", command = lambda: controller.show_frame(EditPage))
self.button2.grid(row = 2, column = 0, sticky = "nsew", pady = 0, padx = (0,10))
self.button3 = ttk.Button(self.root, text = "Ship", command = lambda: controller.show_frame(ShipPage))
self.button3.grid(row = 3, column = 0, sticky = "nsew", pady = 0, padx = (0,10))
self.button4 = ttk.Button(self.root, text = "Graph", command = lambda: controller.show_frame(PlotPage))
self.button4.grid(row = 4, column = 0, sticky = "nsew", pady = 0, padx = (0,10))
self.DATE_Search_label = tk.Label(self.root, text = "Search by DATE", font = ("Helvetica", 9))
self.DATE_Search_label.grid(row = 5, column = 1, sticky = "nsew")
self.DATE_Search_Entry = tk.Entry(self.root)
self.DATE_Search_Entry.grid(row = 6, column = 1, sticky = "nsew", pady = 0, padx = 2)
self.DATE_SEARCH_BUTTON = ttk.Button(self.root, text = "Search", command = lambda: self.DATE_SEARCH())
self.DATE_SEARCH_BUTTON.grid(row = 6, column = 2, sticky = "nsew")
def DATE_SEARCH(self):
with open('SAMPLE.txt', 'r') as f:
search_f = f.readlines()
self.text = tk.Text(self.root, width = 30, height = 2)
self.text.grid(row = 6, column = 3, sticky = "ew", pady = (0,0), padx = (20,0))
self.ScrollBar = tk.Scrollbar(self.root)
self.ScrollBar.config(command = self.text.yview)
self.text.config(yscrollcommand = self.ScrollBar.set)
self.ScrollBar.grid(row = 6, column = 4, sticky = "ns")
self.text.delete(1.0, "end-1c")
USER_TEXT = self.DATE_Search_Entry.get()
if USER_TEXT == '':
self.text.config(foreground = 'red')
self.text.insert(tk.END, "PLEASE ENTER A VALUE")
else:
match_in_file = False
for line in search_f:
if USER_TEXT in line:
self.text.config(foreground = 'black')
self.text.insert(tk.END, "{}".format(line))
match_in_file = True
if match_in_file == False:
self.text.config(foreground = 'red')
self.text.insert(tk.END, "INVENTORY DOES NOT EXIST")
def FILE_MENU_BAR(self):
#File
self.menu = tk.Menu(self.root)
self.root.config(menu = self.menu)
self.fileMenu = tk.Menu(self.menu, tearoff = 0)
self.menu.add_cascade(label = "File", menu = self.fileMenu)
self.fileMenu.add_separator()
self.fileMenu.add_command(label = "Exit", command = lambda: self.root.destroy())
# Edit Menu
self.Edit_Menu = tk.Menu(self.menu)
self.menu.add_cascade(label = "Edit", menu = self.Edit_Menu)
self.Edit_Menu.add_command(label = "cut", underline = 2, command = self.Edit_Cut)
self.Edit_Menu.add_command(label = "copy", underline = 0, command = self.Edit_Copy)
def File_EXIT(self):
sys.exit(0)
def Edit_Cut(self):
print("CUT")
def Edit_Copy(self):
print("COPY")
root = tk.Tk()
app = EXAMPLEapp(root)
app.mainloop()

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

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.

Resources