I am writing a python program with tkinter but I ran into some complications where I don't know how I should deal with.
UPDATE: functional code to demonstrate the problem
import tkinter as tk
class MainApp(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.label = tk.Label(self, text='Schedule')
self.label.pack()
self.mtp_enter = False
self.enter_small_shifts = False
self.Button_Frame = Button_Frame(self)
self.widgets = self.Button_Frame.New()
self.Button_Frame.pack()
def toggle_enter_small_shifts():
if self.enter_small_shifts == False:
if self.mtp_enter == True:
self.toggle_mtp_enter()
self.label.configure(text='MTP')
self.enter_small_shifts = True
else:
self.label.configure(text='schedule')
self.enter_small_shifts = False
def toggle_mtp_enter():
if self.mtp_enter == False:
if self.enter_small_shifts == True:
self.toggle_enter_small_shifts()
self.label.configure(text='MTP')
self.mtp_enter = True
else:
self.label.configure(text='schedule')
self.mtp_enter = False
if __name__ == "__main__":
root= tk.Tk()
root.wm_title("Shelter Schedule Maker")
app = MainApp(root)
app.pack()
root.mainloop()
class Button_Frame(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.parent = parent
def New(self):
widgets = {}
toggle_enter_mtp = tk.Button(self, text='Enter MTP\'s', command=app.toggle_mtp_enter, width=15)
widgets['enter mtp'] = toggle_enter_mtp
toggle_enter_mtp.pack()
toggle_enter_small_shifts = tk.Button(self, text='Enter small shift\'s', command=app.toggle_enter_small_shifts, width=15)
widgets['enter small shifts'] = toggle_enter_small_shifts
toggle_enter_small_shifts.pack()
return widgets
In conclusion: before MainApp I need to define Button_Frame, before Button_Frame I need the MainApp instance, before the Mainapp instance I need the MainApp class. There is a full circle.
How should I restruture this to work?
You should define all methods in the class to be instance methods, and use self within the class and app outside the class:
class MainApp(tk.Frame):
...
def toggle_mtp_enter(self):
if self.enter_mtp == False:
if self.enter_small_shifts == True:
self.toggle_enter_small_shifts()
self.shift_buttons_widgets = self.shift_buttons.Activate_mtp()
...
app = MainApp(...)
...
toggle_enter_mtp = tk.Button(self, text='Enter MTP\'s', command=app.toggle_mtp_enter, width=15)
...
Ideally, Button_Frame shouldn't rely on a global variable app. You're already passing in an instance of the app when you create Button_frame (as parent), so you can do something like this:
class Button_Frame(tk.Frame):
...
def New(self):
...
toggle_enter_mtp = tk.Button(..., command=self.parent.toggle_mtp_enter, ...)
...
toggle_enter_small_shifts = tk.Button(..., command=self.parent.toggle_enter_small_shifts, ...)
...
You also need to define all of your classes before creating the app:
class MainApp(...):
...
class Button_Frame(...):
...
if __name__ == "__main__":
...
Related
I am trying to create a terminal GUI using python tkinter module and I already managed to access the tk.Label from TextFrame class.
class TextFrame(tk.Frame):
def __init__(self, container):
super().__init__()
self.container = container
self['bg']='black'
self.pack(fill='both', expand=True)
self.label = tk.Label(self)
Now the problem is that, I can't change the row everytime I call show() function inside Instances class.
class Instances(Window):
def __init__(self):
super().__init__()
self.string = tk.StringVar()
self.index_row = 0
self.text_frame = TextFrame(self)
self.text_frame.pack()
self.entry_frame = EntryFrame(self)
self.entry_frame.pack(side='bottom',fill='both')
def show(self, e):
textvar = self.string.get()
self.entry_frame.entry.delete(0, 'end')
self.text_frame.label.config(text=textvar)
self.text_frame.label.grid(column=0, row=self.index_row, sticky="w")
self.index_row += 1
Here is the full code of my problem:
import tkinter as tk
class Window(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.geometry('800x600')
self.title('Terminal')
class Instances(Window):
def __init__(self):
super().__init__()
self.string = tk.StringVar()
self.index_row = 0
self.text_frame = TextFrame(self)
self.text_frame.pack()
self.entry_frame = EntryFrame(self)
self.entry_frame.pack(side='bottom',fill='both')
def show(self, e):
textvar = self.string.get()
self.entry_frame.entry.delete(0, 'end')
self.text_frame.label.config(text=textvar)
self.text_frame.label.grid(column=0, row=self.index_row, sticky="w")
self.index_row += 1
class TextFrame(tk.Frame):
def __init__(self, container):
super().__init__()
self.container = container
self['bg']='black'
self.pack(fill='both', expand=True)
self.label = tk.Label(self)
class EntryFrame(tk.Frame):
def __init__(self, container):
super().__init__()
self.entry = tk.Entry(self, textvariable=container.string)
self.entry.pack(fill='both')
self.entry.bind('<Return>', container.show)
if __name__ == '__main__':
window = Instances()
window.mainloop()
Any help would be appreciated.
Problem Solved
I added 1 line of code on show() function
def show(self, e):
textvar = self.string.get()
self.entry_frame.entry.delete(0, 'end')
self.text_frame.label = tk.Label(self.text_frame, fg='green', bg='black')
self.text_frame.label.config(text=textvar)
if len(textvar) > 0 :
self.text_frame.label.grid(column=0, row=self.index_row, sticky="w")
self.index_row += 1
I am trying to make a tkinter desktop application (Notepad) using classes but I found an Attribute Error in my code. I made three files "menu_option.py", "textarea.py" and "window_frame.py". Run the "menu_option.py" file so that you found the error. I am using python (3.9). Also is there any another way to connect "new_file" function to menu item.
Here is my code below:
menu_option.py
from tkinter import *
from textarea import TextArea
from window_frame import Window
class Menu_Option(TextArea):
file = None
def __init__(self, master, newfile=None):
super().__init__(root)
self.Menubar = 'MenuBar'
self.Filemenu = 'FileMenu'
self.root = self.root
self.master = self.master
self.newfile = newfile
def launch(self):
self.Menubar = Menu(self.root)
self.Filemenu = Menu(master=self.Menubar, tearoff=0)
self.Filemenu.add_command(label='New File...', command=self.newfile)
self.Menubar.add_cascade(label='File', menu=self.Filemenu)
self.root.config(menu=self.Menubar)
class Features(Menu_Option):
def __init__(self, master):
super().__init__(master, newfile=self.new_file)
def new_file(self):
global file
self.root.title(self.title)
file = None
self.textarea.delete(1.0, END)
if __name__ == '__main__':
root = Tk()
Window(root).launch()
TextArea(root).launch()
Menu_Option(root).launch()
Features(root).launch()
root.mainloop()
textarea.py
from tkinter import *
from window_frame import Window
from tkinter.scrolledtext import ScrolledText
class TextArea(Window):
def __init__(self, name):
super().__init__(name)
self.name = self.root
self.master = 'root'
self.textarea = 'text_area'
self.font = 'courier 14 normal'
def launch(self):
self.textarea = ScrolledText(self.root, font=self.font)
self.textarea.pack(expand=True, fill=BOTH)
if __name__ == '__main__':
root = Tk()
Window(root).launch()
TextArea(root).launch()
root.mainloop()
window_frame.py
from tkinter import *
class Window:
def __init__(self, root):
self.root = root
self.geometry = '1000x550+100+100'
self.title = 'Untitled - ProBook'
def launch(self):
self.root.geometry(self.geometry)
self.root.title(self.title)
if __name__ == '__main__':
root = Tk()
Window(root).launch()
root.mainloop()
Error:
Exception in Tkinter callback
Traceback (most recent call last):
File "D:\Installed Programs\Python\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "C:\Users\vaish\OneDrive\ProBook\menu_option.py", line 35, in new_file
self.textarea.delete(1.0, END)
AttributeError: 'str' object has no attribute 'delete'
Since Menu_Option() has override launch() function, therefore TextArea.launch() will not be executed and so instance variable textarea is still a string.
If child class wants to inherit parent class launch() functionality, you need to call the parent class launch() in its launch() function:
textarea.py
class TextArea(Window):
...
def launch(self):
super().launch() # call parent class launch()
self.textarea = ScrolledText(self.root, font=self.font)
self.textarea.pack(expand=True, fill=BOTH)
menu_option.py
class Menu_Option(TextArea):
...
def launch(self):
super().launch() # execute parent class launch()
...
...
if __name__ == "__main__":
root = Tk()
#Window(root).launch() # <- no need to execute
#TextArea(root).launch() # <- no need to execute
#Menu_Option(root).launch() # <- no need to execute
Features(root).launch()
root.mainloop()
Note that Window(root).launch(), TextArea(root).launch() and Menu_Option(root).launch() are not required.
You have initialized self.textarea="text_area" in textarea.py . But when you import it in menu_option.py, you are overwriting the function launch, which is supposed to set the value of self.textarea to a ScrolledText and pack it. To solve this you have to include the code in launch function of textarea.py in the function launch of Menu_Option class.
from tkinter import *
from tkinter.scrolledtext import ScrolledText
from textarea import TextArea
from window_frame import Window
class Menu_Option(TextArea):
file = None
def __init__(self, master, newfile=None):
super().__init__(root)
self.Menubar = 'MenuBar'
self.Filemenu = 'FileMenu'
self.root = self.root
self.master = self.master
self.newfile = newfile
def launch(self):
self.Menubar = Menu(self.root)
#You have to include these 2 lines of code which were overwritten
self.textarea = ScrolledText(self.root, font=self.font)
self.textarea.pack(expand=True, fill=BOTH)
self.Filemenu = Menu(master=self.Menubar, tearoff=0)
self.Filemenu.add_command(label='New File...', command=self.newfile)
self.Menubar.add_cascade(label='File', menu=self.Filemenu)
self.root.config(menu=self.Menubar)
I want to create a GUI in a class that can create pages using another class that creates frames and widgets. The pages are set using a class for them. I want to be able to GUI to be able to switch between the different set of pages. I can't create a button for the class of the Login_page that with switch the Login_page with the class of the Sign_page.
from tkinter import *
import random
class maingui:
def __init__(self,title, geometry,):
self.root = Tk()
self.root.title(title)
self.root.geometry(geometry)
self.pageshow = Login_Page(self.root)
self.root.mainloop()
def changepage(self, page):
self.page = page
if self.page == 0:
self.pageshow = Login_Page(self.root)
if self.page == 1:
self.pageshow = Sign_Page(self.root)
self.root.mainloop()
class createWindow:
def __init__(self,root, title, geometry,):
self.root = root
self.root.title(title)
self.root.geometry(geometry)
self.root.mainloop()
class createFrame:
def __init__(self,window):
self.window = window
self.frame = Frame(self.window)
self.frame.pack()
print('c')
def clear(self):
pass
def createlabel(self,message,postion = None):
self.message =message
self.postion = postion
self.label= Label(self.frame, text =self.message)
if self.postion == None:
self.label.pack()
print('a')
else:
print('b')
def createbutton(self, text, command):
self.text = text
self.command = command
self.button = Button(self.frame, text = self.text, command =self.command)
class Login_Page():
def __init__(self,window):
self.window = window
self.frame = createFrame(self.window)
self.frame.createlabel("Hello World")
self.frame.createbutton("1",maingui.changepage(self.window,1))
class Sign_Page():
def __init__(self,window):
self.window = window
self.frame = createFrame(self.window)
self.frame.createlabel("Hello ")
maingui = maingui("Rpg", "400x400")
Edit: Exception has occurred: AttributeError
'_tkinter.tkapp' object has no attribute 'root'
On line
if self.page == 1:
self.pageshow = Sign_Page(self.root)
On this line
self.frame.createbutton("1",maingui.changepage(self.window,1))
I try to create a button using a class and the command is from a different class.
Since you pass self.root (instance of Tk()) of maingui class to Login_Page and assign it to self.window. Then self.window is used in maingui.changepage(self.window, 1) inside Login_Page class. Since you use class name to access changepage(), self.window will be treat as the self argument of changepage() and used in Sign_Page(self.root). That means you want to access the attribute root of self (instance of Tk()) but Tk does not have attribute root.
Suggest to make maingui interit from Tk instead of creating it inside __init__().
Below is an updated example based on yours:
from tkinter import *
#import random
class maingui(Tk):
def __init__(self, title, geometry):
super().__init__()
self.title(title)
self.geometry(geometry)
self.pageshow = Login_Page(self)
def changepage(self, page):
self.page = page
if self.page == 0:
self.pageshow = Login_Page(self)
if self.page == 1:
self.pageshow = Sign_Page(self)
class createFrame:
def __init__(self,window):
self.window = window
self.frame = Frame(self.window)
self.frame.pack()
print('c')
def clear(self):
pass
def createlabel(self,message,postion = None):
self.message =message
self.postion = postion
self.label= Label(self.frame, text =self.message)
if self.postion == None:
self.label.pack()
print('a')
else:
print('b')
def createbutton(self, text, command):
self.text = text
self.command = command
self.button = Button(self.frame, text = self.text, command =self.command)
self.button.pack() ###
class Login_Page():
def __init__(self,window):
self.window = window
self.frame = createFrame(self.window)
self.frame.createlabel("Hello World")
###self.frame.createbutton("1", maingui.changepage(self.window, 1)) ###
self.frame.createbutton("1", lambda: self.window.changepage(1)) ###
class Sign_Page():
def __init__(self,window):
self.window = window
self.frame = createFrame(self.window)
self.frame.createlabel("Hello ")
maingui = maingui("Rpg", "400x400")
maingui.mainloop()
Here is a working code, I would also suggest you read and practice classes before moving further.
(Note: I have not defined your clear method or added any new method, I have just corrected your existing code and rectified your error. you may further if you want, define your clear method and destroy your widgets).
from tkinter import *
import random
class maingui:
def __init__(self, root, title, geometry):
self.root = root
self.root.title(title)
self.root.geometry(geometry)
self.pageshow = Login_Page(self, self.root)
def changepage(self, page):
self.page = page
if self.page == 0:
self.pageshow = Login_Page(self, self.root)
if self.page == 1:
self.pageshow = Sign_Page(self, self.root)
class createWindow:
def __init__(self,root, title, geometry):
self.root = root
self.root.title(title)
self.root.geometry(geometry)
class createFrame:
def __init__(self, parent, window):
self.window = window
self.frame = Frame(self.window)
self.frame.pack()
self.label = Label(self.frame)
self.button = Button(self.frame)
self.parent = parent
def clear(self):
pass
def createlabel(self,message,postion = None):
self.message =message
self.postion = postion
self.label.config(text=self.message)
if self.postion == None:
self.label.pack()
else:
pass
def createbutton(self, text='Login', cmd=0):
self.text = text
self.button.configure(text=self.text, command=lambda :self.parent.changepage(cmd))
self.button.pack()
class Login_Page():
def __init__(self, parent, window):
self.window = window
self.frame = createFrame(parent, self.window)
self.frame.createlabel("Hello World bye")
self.frame.createbutton("Welcome", 1)
class Sign_Page():
def __init__(self, parent, window):
self.window = window
self.frame = createFrame(parent, self.window)
self.frame.createlabel("Hello ")
def main():
root = Tk()
maingui(root, "Rpg", "400x400")
root.mainloop()
if __name__ =='__main__':
main()
update: here is a way you can switch between pages(in my case you can switch between the sign-up and login page). click on login it will direct you to sign-up and vice-versa.
from tkinter import *
import random
class maingui:
def __init__(self, root, title, geometry):
self.root = root
self.root.title(title)
self.root.geometry(geometry)
self.pageshow = Login_Page(self, self.root)
def changepage(self, page):
self.page = page
if self.page == 0:
#del self.pageshow
self.pageshow = Login_Page(self, self.root)
if self.page == 1:
#del self.pageshow
self.pageshow = Sign_Page(self, self.root)
class Login_Page:
def __init__(self, parent, window):
self.parent = parent
self.frame = Frame(window)
self.frame.pack()
self.welcm_lbl = Label(self.frame, text='welcome')
self.welcm_lbl.grid(row=0, column=1)
self.name_lbl = Label(self.frame, text='name:')
self.name_lbl.grid(row=1, column=0)
self.name_entry = Entry(self.frame)
self.name_entry.grid(row=1, column=1)
self.sbt = Button(self.frame, text='login', command=self.clicked)
self.sbt.grid(row=2, column=1)
def clicked(self):
self.frame.destroy()
self.parent.changepage(1)
class Sign_Page():
def __init__(self, parent, window):
self.parent = parent
self.frame = Frame(window)
self.frame.pack()
self.welcm_lbl = Label(self.frame, text='welcome sign-up')
self.welcm_lbl.grid(row=0, column=1)
self.name_lbl = Label(self.frame, text='name:')
self.name_lbl.grid(row=1, column=0)
self.name_entry = Entry(self.frame)
self.name_entry.grid(row=1, column=1)
self.sbt = Button(self.frame, text='sign-up', command=self.clicked)
self.sbt.grid(row=2, column=1)
def clicked(self):
self.frame.destroy()
self.parent.changepage(0)
def main():
root = Tk()
maingui(root, "Rpg", "400x400")
root.mainloop()
if __name__ =='__main__':
main()
I wonder how to pass return value from one class to another class in tkinter.
In my program I have DataChosenForm class where I want to choose option in Combobox and pass this result to another class ReturnData to set a variable in a Label.
import tkinter as tk
from tkinter import ttk
class DataChosenForm(tk.Frame):
def __init__(self, parent):
super().__init__(parent)
chosen = tk.LabelFrame(self, text="wybór")
chosen.grid(row=0)
self.combo = ttk.Combobox(chosen)
self.combo['values'] = ('wizz', 'ryanair', 'lot')
self.combo.grid(row=0, column=2, padx=80, pady=10)
self.combo.bind("<<ComboboxSelected>>", self.callback)
def callback(self, event=None):
if event.widget.get() == 'wizz':
print('wizz')
return 'wizz'
elif event.widget.get() == 'ryanair':
print('ryanair')
return 'ryanair'
elif event.widget.get() == 'lot':
print('lot')
return 'lot'
class ReturnData(tk.Frame):
def __init__(self, parent):
super().__init__(parent)
var = tk.StringVar()
message_box = tk.LabelFrame(self, text="wynik")
message_box.grid(row=1)
mb = tk.Label(message_box, textvariable=var,anchor='nw')
mb.pack(padx=120, pady=30)
class Application(tk.Tk):
def __init__(self):
super().__init__()
self.title("program do wyszukiwania cen lotów")
self.geometry('300x200')
self.resizable(width=False, height=False)
DataChosenForm(self).grid(row=0, column=0)
ReturnData(self).grid(row=1)
if __name__ == "__main__":
app = Application()
app.mainloop()
You could first display the combobox DataChosenForm(self).grid(row=0, column=0) without calling the ReturnData in the Application class.
Then, in the callback() method collect the choice choice = event.widget.get() and pass it to ReturnData. This would mean, however, that the LabelFrame is displayed only after a choice is made.
import tkinter as tk
from tkinter import ttk
class DataChosenForm(tk.Frame):
def __init__(self, parent):
super().__init__(parent)
chosen = tk.LabelFrame(self, text="wybór")
chosen.grid(row=0)
self.combo = ttk.Combobox(chosen)
self.combo['values'] = ('wizz', 'ryanair', 'lot')
self.combo.grid(row=0, column=2, padx=80, pady=10)
self.combo.bind("<<ComboboxSelected>>", self.callback)
def callback(self, event=None):
choice = event.widget.get()
print(choice)
ReturnData(self, choice).grid(row=1)
class ReturnData(tk.Frame):
def __init__(self, parent, choice):
super().__init__(parent)
message_box = tk.LabelFrame(self, text="wynik")
message_box.grid(row=1)
mb = tk.Label(message_box, text=choice, anchor='nw')
mb.pack(padx=120, pady=30)
class Application(tk.Tk):
def __init__(self):
super().__init__()
self.title("program do wyszukiwania cen lotów")
self.geometry('300x200')
self.resizable(width=False, height=False)
DataChosenForm(self).grid(row=0, column=0)
if __name__ == "__main__":
app = Application()
app.mainloop()
I think #Julia has the basically the right architecture for your tkinter application, but her answer could be improved by using a tkinter Variable — because all widgets associated with one will automatically update their displayed value whenever the Variable is changed (by one of them or something else).
Here's a little documentation on Variable Classes. Note that since ttk.Combobox with have all the methods of a tk.Entry widgets, here's a bit of documentation about them (which also happens to illustrate the "pattern" of using of a StringVar in conjunction with one so it also applies to a ttk.Comboboxs).
Generally, you can tell a widget to use a tkinter Variable by specifying an instance of one as the option textvariable= keyword argument when the widget is created. You can also set the option using the partial dictionary interface most widgets support, so assignments like widget['textvariable'] = variable are another way to make use of them — the code below makes use of both of these ways.
Here's Julia's code modified to use a tk.StringVar. Note the Combobox doesn't need a callback function to bind the <<ComboboxSelected>> event to it, so all that complexity has been eliminated.
import tkinter as tk
from tkinter import ttk
class DataChosenForm(tk.Frame):
def __init__(self, parent):
super().__init__(parent)
choice = tk.LabelFrame(self, text="wybór")
choice.grid(row=0)
self.combo = ttk.Combobox(choice)
self.combo['textvariable'] = parent.var # Use shared variable.
self.combo['values'] = ('wizzair', 'ryanair', 'lot')
self.combo.grid(row=0, column=2, padx=80, pady=10)
class ReturnData(tk.Frame):
def __init__(self, parent):
super().__init__(parent)
message_box = tk.LabelFrame(self, text="wynik")
message_box.grid(row=1)
mb = tk.Label(message_box, textvariable=parent.var, # Use shared variable.
anchor='nw', width=20)
mb.pack(padx=120, pady=30)
class Application(tk.Tk):
def __init__(self):
super().__init__()
self.title("program do wyszukiwania cen lotów")
self.geometry('300x200')
self.resizable(width=False, height=False)
self.var = tk.StringVar(value='Dokonać wyboru') # Create shared variable.
DataChosenForm(self).grid(row=0, column=0)
ReturnData(self).grid(row=1)
if __name__ == "__main__":
app = Application()
app.mainloop()
You can just pass other class or it's field to __init__ of the DataChosenForm, and to callback function from there, where then you can change class/field directly. Here's what I mean, but I use TreeView:
import tkinter as tk
from tkinter import ttk
class ConnectedClass:
def __init__(self):
self.received = "will be changed"
class TreeViewWrapper(ttk.Treeview):
def __init__(self, master, connected_class, **kw):
super().__init__(master, **kw)
parents = []
for i in range(10):
parent = self.insert("", "end", text="Item %s" % i, tags=str(i))
for i in range(3):
self.insert(parent, "end", text="Item %s" % i, tags=str(i))
self.bind("<Control-r>", lambda e: self.pass_to_other(e, connected_class))
def pass_to_other(self, _, connected_class):
items = self.selection()
connected_class.received = items
class App:
def __init__(self):
self.root = tk.Tk()
self.con_class = ConnectedClass()
self.tree = TreeViewWrapper(self.root,self.con_class)
self.tree.pack()
self.root.bind("<Control-p>",lambda e:print(self.con_class.received))
self.root.mainloop()
if __name__ == "__main__":
app = App()
I need to subclass a Label widget, so that the browser can open a link while the mouse clicks on it.
Here is the code snippet of what I've done so far.
from tkinter import *
import webbrowser
class HyperLinkLabel(Label):
def __init__(self, link, *args, **kwargs):
Label.__init__(self, *args, **kwargs)
self.link = link
self.bind("<Button-1>", self.click_callback)
def click_callback(self):
webbrowser.open_new(self.link)
if __name__ == '__main__':
master = Tk()
root = Frame(master)
label1 = HyperLinkLabel(root, link='https://www.google.com')
label1.config(text='hello')
label1.pack()
root.master.minsize(100, 50)
root.mainloop()
You should declare master (or parent) parameter and pass it to Label constructor. (root from the perspect of caller)
event handle should have event parameter even though you don't use it. Otherwise TypeError exception is thrown.
Pack frame so that widgets inside it is visible.
from tkinter import *
import webbrowser
class HyperLinkLabel(Label):
def __init__(self, master, link, *args, **kwargs): # <-- pass master parameter
Label.__init__(self, master, *args, **kwargs) # <-- pass master parameter
self.link = link
self.bind("<Button-1>", self.click_callback)
def click_callback(self, event): # <--- missed event parameter
webbrowser.open_new(self.link)
if __name__ == '__main__':
master = Tk()
root = Frame(master)
label1 = HyperLinkLabel(root, link='https://www.google.com')
label1.config(text='hello')
label1.pack()
root.pack() # <-- should pack frame; otherwise link widget is not visible
root.master.minsize(100, 50)
root.mainloop()