I am using Tkinter in Python 3 to create a converter between hex, binary and denary - while creating my own methods for conversions instead of using the built in methods.
I've completed the denary to binary conversion through the use of my 'highestPowerOf2' method in the DenToBin class. I want to use this method in my HexToBin class, but whenever I try to, an additional blank window pops up and I receive - AttributeError: 'NoneType' object has no attribute 'title' - error.
How would I run 'highestPowerOf2' in the HexToBin class?
(also sorry for any poor programming practise)
Code:
from tkinter import *
from functools import partial
class Menu(Frame):
def __init__(self, master= None): # initialise Menu
Frame.__init__(self, master) # initialise Frame
self.master = master # what does this do
self.createWindow()
def createWindow(self):
self.pack(fill = BOTH, expand = 1)
denToBin = Button(self, text = 'Denary to Binary', command = lambda: self.changeWindow(DenToBin))
denToBin.pack(fill = X, padx = 10, pady = 10)
hexToBin = Button(self, text = 'Hex to Binary', command = lambda: self.changeWindow(HexToBin))
hexToBin.pack(fill = X, padx = 10, pady = 10)
def changeWindow(self, object):
root.withdraw()
currentFrame = object(root)
class DenToBin(Toplevel):
def __init__(self, master = None):
Toplevel.__init__(self, master)
self.master = master
self.Window()
self.denary = 0
def Window(self):
# print(self.denary) -- Why is this not recognised?????????
self.master.title('Unit Converter: Denary to Binary')
instructionDen = Label(self, text = 'Denary Value: ')
instructionDen.grid(row = 1, column = 0, padx = 10)
instructionBin = Label(self, text = 'Binary Value: ')
instructionBin.grid(row = 2, column = 0, padx = 10)
self.denaryEntry = Entry(self)
self.denaryEntry.grid(row = 1, column = 2, padx = 10, pady = 5)
convertButton = Button(self, text = 'Convert!', command = lambda: self.highestPowerOf2(10)) # as an example
convertButton.grid(row = 3, column = 1)
# finds highest power of 2 that is less than denary number - helps self.convert()
def highestPowerOf2(self,number):
print('I find the highest power of 2 that fits into the number given.')
class HexToBin(Toplevel):
def __init__(self, master = None):
Toplevel.__init__(self, master)
self.master = master
self.Window()
self.denary = 0
def Window(self):
self.master.title('Unit Converter: Hexadecimal to Binary')
instructionHex = Label(self, text = 'Hexadecimal Value: ')
instructionHex.grid(row = 1, column = 0, padx = 10)
instructionBin = Label(self, text = 'Binary Value: ')
instructionBin.grid(row = 2, column = 0, padx = 10)
self.hexadecimalEntry = Entry(self)
self.hexadecimalEntry.grid(row = 1, column = 2, padx = 10, pady = 5)
convertButton = Button(self, text = 'Convert!', command = self.convert)
convertButton.grid(row = 3, column = 1)
def convert(self):
# I need to call the 'highestPowerOf2' method here.
pass
root = Tk()
unitConverter = Menu(root) # root is master
root.mainloop()
Related
I'm using Tkinter in Python to create a planner. I'm trying to figure out how to pass variables from one window/class to another, using Tkinter buttons. For example, how do I introduce the string variable 'user_input' in 'StartPage' to the 'CalendarToday' window. The button that directs the user to the 'CalendarToday' page from the start page is 'btn_today'. Is there any way to make this button pass the user_input variable to the 'CalendarToday' class?
class SampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self._frame = None
self.switch_frame(StartPage)
def switch_frame(self, frame_class):
#variable = None
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy()
self._frame = new_frame
self._frame.pack()
class StartPage(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
master.title("My Calendar")
tk.Label(self, text="My Calendar!", font=('Helvetica', 16, "bold")).grid(row = 1, column = 2, pady = 35)
# Today's Calendar button
btn_today = tk.Button(self, text="Today's Calendar", width = 20, height = 3, command=lambda: master.switch_frame(Calendar_Today))
btn_today.grid(row = 3, column = 2, pady = 40, padx = 60)
# Entry Form
entry_form = tk.Entry(self)
entry_form.insert(0, 'Month, Year')
# user_input is the string variable holding the the user's input of month and year.
user_input = entry_form.get()
print(user_input)
entry_form.grid(row = 4, column = 2, pady = 0)
# Specify Calendar button
btn_specify = tk.Button(self, text="Specify month",width = 20, height = 3,command=lambda: master.switch_frame(PageTwo))
btn_specify.grid(row = 5, column = 2, pady = 10)
# Quit button
btn_quit = tk.Button(self, text="Quit App",width = 20, height = 3,command=master.destroy)
btn_quit.grid(row = 6, column = 2, pady = 20)
class Calendar_Today(tk.Frame):
def __init__(self, master):
month_display = month_today + " " + year_today
tk.Frame.__init__(self, master)
master.title(month_display)
lbl_display = tk.Label(self, text= month_display)
lbl_display.grid(row = 1, column = 2)
btn_date1 = tk.Button(self, text="Dates", width = 4, height = 2)
btn_date1.grid(row = 3, column = 2, padx = 10, pady = 10)
########################################
btn_next = tk.Button(self, text="Next Month")
btn_next.grid(row = 8, column = 1, padx = 10, pady = 10)
btn_previous = tk.Button(self, text="Previous Month")
btn_previous.grid(row = 8, column = 2, padx = 10, pady = 10)
btn_return = tk.Button(self, text="Return to Menu",command=lambda: master.switch_frame(StartPage))
btn_return.grid(row = 8, column = 3, padx = 10, pady = 10)
if __name__ == "__main__":
app = SampleApp()
app.title("My Calendar!")
app.mainloop()
You can modify switch_frame() to accept optional arguments and pass these arguments to page classes:
from tkinter import messagebox
...
class SampleApp(tk.Tk):
...
def switch_frame(self, frame_class, *args, **kw): # added optional arguments
if self._frame:
self._frame.destroy()
self._frame = frame_class(self, *args, **kw) # pass optional arguments to frame class
self._frame.pack()
class StartPage(tk.Frame):
def __init__(self, master):
...
# Today's Calendar button
btn_today = tk.Button(self, text="Today's Calendar", width=20, height=3,
command=self.show_calendar)
btn_today.grid(row=3, column=2, pady=40, padx=60)
...
def show_calendar(self):
user_input = self.entry_form.get().strip()
tokens = user_input.split()
# make sure month and year are specified
# need to do some other validations to make sure valid month and year are input
if len(tokens) == 2:
# pass the user input to Calendar_Today class
self.master.switch_frame(Calendar_Today, *tokens)
else:
messagebox.showerror("Error", f"Invalid input: {user_input}")
class Calendar_Today(tk.Frame):
def __init__(self, master, month_today, year_today): # added month and year arguments
...
I am creating Vocabulary, a GUI program to manage unknown words. I am getting:
/usr/bin/python3.5 /home/cali/PycharmProjects/Vocabulary/Vocabulary.py
Exception in Tkinter callback Traceback (most recent call last):
File "/usr/lib/python3.5/tkinter/init.py", line 1553, in call
return self.func(*args) File "/home/cali/PycharmProjects/Vocabulary/Vocabulary.py", line 86, in
add_item
self.listBox.insert(END, self.get_word()) AttributeError: 'Vocabulary' object has no attribute 'listBox'
Process finished with exit code 0
... when I try to add an item to the listbox.
Here is what I have done:
#!/usr/bin/env python
# Vocabulary.py
# GUI program to manage unknown words
from tkinter import *
class Word:
def __init__(self, wordorphrase, explanation, translation, example):
self.wordorphrase = wordorphrase
self.explanation = explanation
self.translation = translation
self.example = example
class Vocabulary(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.master = master
self.master.resizable(width = False, height = False)
self.master.title("Vocabulary")
self.create_widgets()
def create_widgets(self):
lblWordsOrPhrases = Label(self.master, text = 'Words or Phrases:')
lblWordsOrPhrases.grid(row = 0, column = 0)
lblWordOrPhrase = Label(self.master, text = 'Word or phrase:')
lblWordOrPhrase.grid(row = 0, column = 1, sticky = W)
listBox = Listbox(self.master,
height = 34,
width = 30)
listBox.grid(row = 1, column = 0, rowspan = 7)
txt_WordOrPhrase = Text(self.master,
height = 1,
width = 40)
txt_WordOrPhrase.grid(row = 1, column = 1, sticky = N)
lblExplanation = Label(self.master, text = 'Explanation:')
lblExplanation.grid(row = 2, column = 1, sticky = W)
txt_Explanation = Text(self.master,
height = 10,
width = 40)
txt_Explanation.grid(row = 3, column = 1, sticky = N)
lblTranslation = Label(self.master, text = 'Translation:')
lblTranslation.grid(row = 4, column = 1, sticky = W)
txt_Explanation = Text(self.master,
height = 10,
width = 40)
txt_Explanation.grid(row = 5, column = 1, sticky = N)
lblExamples = Label(self.master, text = 'Example(s):')
lblExamples.grid(row = 6, column = 1, sticky = W)
txt_Explanation = Text(self.master,
height = 10,
width = 40)
txt_Explanation.grid(row = 7, column = 1, sticky = S)
btn_Add = Button(self.master,
text = 'Add',
command = self.add_item)
btn_Add.grid(row = 8, column = 0, sticky = W)
def get_word(self):
return self.txt_WordOrPhrase.get('1.0', '1.0 lineend')
def get_explanation(self):
return self.txt_Explanation.get('1.0', '1.0 lineend')
def get_translation(self):
return self.txt_Translation.get('1.0', '1.0 lineend')
def get_example(self):
return self.txt_Example.get('1.0', '1.0 lineend')
def add_item(self):
self.listBox.insert(END, self.get_word())
def main():
root = Tk()
Vocabulary(root)
root.mainloop()
if __name__ == '__main__':
main()
I'm using Python 3.5.
You listbox is a variable local to create_widgets since it is not set with self. In order to make the variable available instance-wide, you need to contain it in self.
Change the line in create_widgets to self.listBox = Listbox(self.master, height = 34, width = 30) and change every reference to listBox to self.listBox in order to apply this change.
You might want to defined self.listBox in __init__(), as it might help keep track of instance variables.
I have a program running that is having issues when the timer runs. Every time "start" is hit, the application crashes. Any thoughts?
##-- Imports --##
import time
import openpyxl as xl
from Tkinter import *
##-- Classes --##
class App(Frame):
def startTimer(self):
self.check = True
self.now = time.strftime("%H:%M:%S")
while self.check == True:
self.timer.configure(text = self.now)
time.sleep(1)
def initUI(self):
self.parent.title("Emma's Time Manager")
self.pack(fill = BOTH, expand = 1)
def initWidget(self):
##Create button definitions##
self.buttonwidth = 12
self.quit = Button(self, text = "Quit", comman = self.quit, width = self.buttonwidth)
self.newClient = Button(self, text = "Add Client", command = lambda:self.newClientFunc(), width = self.buttonwidth)
self.timeStart = Button(self, text = "Start", command = lambda:self.startTimer(), width = self.buttonwidth)
self.timeEnd = Button(self, text = "End", command = lambda:self.endTimer(), width = self.buttonwidth)
self.saveBut = Button(self, text = "Save", command = lambda:self.saveFunc(), width = self.buttonwidth)
self.viewClient = Button(self, text = "View Client", command = lambda:self.viewCliFunc(), width = self.buttonwidth)
##Create lable definitions##
self.timer = Label(self, text = "00:00:00") ##self.timer used as display for timer##
##Create the listbox for Client Selection##
self.wb = xl.load_workbook("clients.xlsx")
self.clientNames = self.wb.get_sheet_names()
self.clivar = StringVar(self)
self.clivar.set(self.clientNames[0])
self.clilist = apply(OptionMenu, (self, self.clivar) + tuple(self.clientNames))
##Create Entry Box to describe work information##
self.info = Entry(self, width = 50)
##Create GUI for widgets##
self.clilist.grid(row = 0, column = 0)
self.timer.grid(row = 0, column = 1)
self.timeStart.grid(row = 0, column = 2)
self.timeEnd.grid(row = 0, column = 3)
self.info.grid(row = 1, column = 0, columnspan = 4)
self.newClient.grid(row = 2, column = 0)
self.viewClient.grid(row = 2, column = 1)
self.saveBut.grid(row = 2, column = 2)
self.quit.grid(row = 2, column = 3)
def __init__(self, parent):
Frame.__init__(self, parent, background = "light blue")
self.parent = parent
self.initUI()
self.initWidget()
def main():
try:
xl.load_workbook("clients.xlsx")
except:
temp = xl.Workbook()
temp.save("clients.xlsx")
temp.remove_sheet(temp.get_sheet_by_name("Sheet"))
root = Tk()
bob = App(root)
root.mainloop()
main()
Please note that most of the program is not yet finished. I just cannot seem to get this timer to run properly.
Looks like you have no way out of your while loop. You'll either need to set self.check to False, or break out of the loop.
while self.check == True:
self.timer.configure(text = self.now)
time.sleep(1)
I'm doing an assignment for a course and I'm not really sure what's up with the code but it runs without error, only displaying an empty window. I used an example given as a start and basically modified it to get this code. If needed I can provide the example code to compare.
from Tkinter import *
class App(Tk):
def __init(self):
Tk.__init__(self)
self.height()
self.weigh()
self.calculate()
self.output()
def height(self):
Label(self, text = "Enter Height, feet").grid()
self.feet = Entry(self)
self.feet.grid(row = 0, column = 1)
self.feet.insert(0, "100")
lblinches = Label(self, text = "Enter Height, inches")
lblinches.grid(row = 1, column = 0)
self.inches = Entry(self)
self.inches.grid(row = 1, column = 1)
def weigh(self):
Label(self, text = "Enter Weight").grid(row =2, column = 0)
self.weight = Entry(self)
self.weight.grid(row = 2, column = 1)
def output(self):
self.calcBMI = Button(self, text = "Calculate BMI")
self.calcBMI.grid()
self.calcBMI["command"] = self.calculate
Label(self, text = "Body Mass Index").grid(row = 4)
Label(self, text = "Status").grid(row = 5)
def calculate(self):
feet1 = int(self.feet.get())
inches1 = int(self.inches.get())
height1 = feet1 *12 + inches1
weight1 = int(self.weight.get())
bmi = (weight1 * 703) / (height1 * 2)
self.lblbmi["text"] = ".2f" % bmi
def main():
app = App()
app.mainloop()
main()
__init should be __init__. Since __init__ was not defined, none of the configuration methods were called.
I am writing a programm in which I am trying to open a n number of windows. My code is:
from tkinter import *
from tkinter import ttk
class Main_window(ttk.Frame):
"""A program"""
def __init__(self, master):
ttk.Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
"""Creates all the objects in the window"""
self.min_lbl = ttk.Label(self, text = "1").grid(row = 0, column = 0,
sticky = W)
self.max_lbl = ttk.Label(self, text = "100").grid(row = 0, column = 2,
sticky = W)
spinval = IntVar()
self.scale = ttk.Scale(self, orient = HORIZONTAL,
length = 200,
from_ = 1, to = 100,
variable = spinval,
command=self.accept_whole_number_only)
self.scale.grid(row = 0,column = 1,sticky = W)
self.spinbox = Spinbox(self, from_ = 1, to = 100,
textvariable = spinval,
command = self.update,
width = 10)
self.spinbox.grid(row = 0,column =3,sticky = W)
self.go_bttn = ttk.Button(self, text = "Go",
command = self.create_windows
).grid(row = 1, column = 1, sticky = W)
def accept_whole_number_only(self, e=None):
"""Makes the numbers from the scale whole"""
value = self.scale.get()
if int(value) != value:
self.scale.set(round(value))
def update(self):
"""Updates the scale and spinbox"""
self.scale.set(self.spinbox.get())
def create_windows(self):
"""This function will create all the new windows"""
value = self.scale.get()
window_num = value
negative_window_num = 1
while window_num != 0:
root = Tk()
root.title("This is Window "+str(window_num)[:-2]+" of "+str(value)[:-2])
root.geometry("350x200")
app = Window_creator(root)
root.mainloop()
window_num -= 1
class Window_creator(ttk.Frame):
"""makes child windows"""
def __init__(self, master):
ttk.Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
"""creates all the widgets in the window"""
def main():
"""Loops the window"""
root = Tk()
root.title("Programm")
root.geometry("350x200")
app = Main_window(root)
root.mainloop()
main()
What I want this code to do is I want to be able to set the spinbox or scale to number n and then when I click the Button i want n numbers of child windows to appear. I tried this with a while loop but it doesn't quite work like I want it to by creating a new window just after the I closed the prevoius window. You also have to close the main window first for it to work (I am going to make the button close the window automatically later). Any Ideas on how I could make this work?
Call child = Toplevel(), instead of root = Tk().
Also, you can not call mainloop more than once (since there should be only one event loop).
from tkinter import *
from tkinter import ttk
class Main_window(ttk.Frame):
"""A program"""
def __init__(self, master):
ttk.Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
"""Creates all the objects in the window"""
self.min_lbl = ttk.Label(self, text = "1").grid(row = 0, column = 0,
sticky = W)
self.max_lbl = ttk.Label(self, text = "100").grid(row = 0, column = 2,
sticky = W)
spinval = IntVar()
self.scale = ttk.Scale(self, orient = HORIZONTAL,
length = 200,
from_ = 1, to = 100,
variable = spinval,
command=self.accept_whole_number_only)
self.scale.grid(row = 0,column = 1,sticky = W)
self.spinbox = Spinbox(self, from_ = 1, to = 100,
textvariable = spinval,
command = self.update,
width = 10)
self.spinbox.grid(row = 0,column =3,sticky = W)
self.go_bttn = ttk.Button(self, text = "Go",
command = self.create_windows
).grid(row = 1, column = 1, sticky = W)
def accept_whole_number_only(self, e=None):
"""Makes the numbers from the scale whole"""
value = self.scale.get()
if int(value) != value:
self.scale.set(round(value))
def update(self):
"""Updates the scale and spinbox"""
self.scale.set(self.spinbox.get())
def create_windows(self):
"""This function will create all the new windows"""
value = self.scale.get()
window_num = value
negative_window_num = 1
for n in range(int(window_num)):
child = Toplevel()
child.title("This is Window "+str(window_num)[:-2]+" of "+str(value)[:-2])
child.geometry("350x200")
app = Window_creator(child)
class Window_creator(ttk.Frame):
"""makes child windows"""
def __init__(self, master):
ttk.Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
"""creates all the widgets in the window"""
def main():
"""Loops the window"""
root = Tk()
root.title("Programm")
root.geometry("350x200")
app = Main_window(root)
root.mainloop()
main()