question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Major error in ttkboostrap

See original GitHub issue

Desktop (please complete the following information):

Hi,

I use the following code to spawn the next UI, but iam getting error _tkinter.TclError: NULL main window

from tkinter import *
from ttkbootstrap import Style
from tkinter import ttk
import multiprocessing


class GuiApp(object):
    def __init__(self):
        self.style = Style(theme='litera')
        self.style.configure('lefttab.TNotebook', tabposition='wn')
        self.style.configure('TNotebook.Tab', align=LEFT)
        self.root = self.style.master
        tabone = ttk.Button(self.root, text="Campaigns")
        tabone.place(x=20, y=20)
        tabtwo = ttk.Button(self.root, text="Settings")
        tabtwo.place(x=27, y=60)
        self.root.geometry("850x550")
        self.root.resizable(False, False)
def validate():
    second.destroy()
    multiprocessing.freeze_support()
    gui = GuiApp()
    gui.root.mainloop()
def validate_lic():
   global second
   global emailentry
   global passentry
   global keyentry
   global validate_btn
   style = Style(theme='litera')
   second = style.master
   validate_btn = ttk.Button(second, text="Sign-in", command=validate)
   validate_btn.place(x=155, y=150)
   second.geometry("350x300")
   second.resizable(False, False)
   # second.iconbitmap("Icon.ico")
   second.mainloop()


if __name__ == '__main__':
    multiprocessing.freeze_support()
    validate_lic()

If i tried with same code with ttkboostrap version 0.5.1 then no issue.

Describe the bug

Getting _tkinter.TclError: NULL main window bug when it was trying to spawn other UI

To Reproduce

Just run the code and click on sign in button, you can see the bug

Expected behavior

It has to spawn the other UI, it works fine V0.5.1, but not in the current.

Screenshots

https://i.imgur.com/8zaETCY.png

Additional context

No response

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:11 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
sunny9495-devcommented, May 5, 2022

Ok, Thanks @israel-dryer

Thank you for your excellent support

0reactions
israel-dryercommented, May 5, 2022

I need to look into this further, but generally, it is not a recommended practice to use more than one tcl/tk interpreter in your application. This is what Toplevel widgets are created for. There are several ways to accomplish what you want without closing and reopening a new application window.

On solution, as I mentioned, is to use Toplevel widgets. Another solution (demonstrated below) is to use frames to control and contain your content.

import ttkbootstrap as ttk
from ttkbootstrap.constants import *

THEME = 'litera'
APP_SIZE = (850, 550)

class GuiApp(ttk.Window):

    def __init__(self):
        super().__init__(themename=THEME, size=APP_SIZE, resizable=(False, False))
        self.is_valid_license = ttk.BooleanVar(self, name='is_valid_license', value=False)
        self.is_valid_license.trace_add('write', self.on_license_validation)
        # setup frames
        self.setup_custom_styles()
        self.validation_frame = LicenseValidationFrame(self)
        self.main_frame = MainAppFrame(self)
        # show the initial validation frame
        self.show_validation_frame()

    def show_main_frame(self):
        self.main_frame.pack(fill=BOTH, expand=YES)

    def show_validation_frame(self):
        if not self.validation_frame.winfo_ismapped():
            self.validation_frame.pack(fill=BOTH, expand=YES)

    def setup_custom_styles(self):
        self.style.configure('lefttab.TNotebook', tabposition='wn')
        self.style.configure('TNotebook.Tab', align=LEFT, fill=X)
        self.style.layout('TNotebook.Tab', [])

    def on_license_validation(self, *args):
        if self.is_valid_license.get():
            self.validation_frame.pack_forget()
            self.show_main_frame()

class MainAppFrame(ttk.Frame):

    def __init__(self, master, **kwargs):
        super().__init__(master, **kwargs)

        # setup buttons
        self.lframe = ttk.Frame(self, padding=(10, 10, 0, 10))
        self.lframe.pack(side=LEFT, fill=Y)
        self.tab1_btn = ttk.Button(self.lframe, text='Campaigns')
        self.tab2_btn = ttk.Button(self.lframe, text='Settings')
        self.tab3_btn = ttk.Button(self.lframe, text='Reports')
        self.tab1_btn.pack(side=TOP, fill=X)
        self.tab2_btn.pack(side=TOP, fill=X)
        self.tab3_btn.pack(side=TOP, fill=X)

        # setup notebook & tabs
        self.rframe = ttk.Frame(self)
        self.rframe.pack(side=RIGHT, fill=BOTH)
        self.notebook = ttk.Notebook(self.rframe, style='lefttab.TNotebook')
        self.notebook.pack(fill=BOTH, expand=YES, padx=10, pady=10)

        tab_cnf = {'width': 700, 'height': 500}
        # tab 1 setup
        self.tab1 = CampaignTab(self.notebook)
        self.tab2 = ttk.Frame(self.notebook, **tab_cnf)
        self.tab3 = ttk.Frame(self.notebook, **tab_cnf)
        self.tab4 = ttk.Frame(self.notebook, **tab_cnf)
        self.tab5 = ttk.Frame(self.notebook, **tab_cnf)
        self.tab6 = ttk.Frame(self.notebook, **tab_cnf)
        self.notebook.add(self.tab1, text='Campaigns')
        self.notebook.add(self.tab2, text='Settings')
        self.notebook.add(self.tab3, text='Reports')
        self.notebook.add(self.tab4, text='Add New Campaign')
        self.notebook.add(self.tab5, text='Camp Reports')
        self.notebook.add(self.tab6, text='Log Reports')


class CampaignTab(ttk.Frame):
    def __init__(self, master, **kwargs):
        super().__init__(master, width=700, height=500, **kwargs)
        # create tab elements
        self.camp_lbl = ttk.Label(self, text='Campaigns', bootstyle=INFO, font='Helvetica 14 bold')
        self.add_camp = ttk.Button(self, text='Add New Campaign', bootstyle=PRIMARY)
        self.search_lbl = ttk.Label(self, text='Search', bootstyle=INFO, font='Arial 11')
        self.search_entry = ttk.Entry(self)
        # set layout
        self.camp_lbl.pack(pady=10)
        self.add_camp.pack(pady=10)
        self.search_entry.pack(pady=10)


class LicenseValidationFrame(ttk.Frame):

    def __init__(self, master, **kwargs):
        super().__init__(master, **kwargs)
        btn = ttk.Button(self, text='Sign-in', command=self.validate)
        btn.place(anchor=CENTER, relx=0.5, rely=0.5)

    def validate(self):
        """perform some function to validate the license then update
        the is_valid_license variable"""
        is_valid_license = ttk.BooleanVar(name='is_valid_license')
        is_valid_license.set(True)


if __name__ == '__main__':
    app = GuiApp()
    app.mainloop()

In fact, since you are creating your own notebook buttons, you really do not need to use the notebook widget at all, just use the pack_forget method to remove the frame from the window as I did for the license frame above, and then pack the tab you want to show. The result will be the same except you won’t need to do a lot of customizations on the notebook widget.

One other tip, I would avoid using place with x & y coordinates. If someone has a high resolution screen, the placement of widgets will be very different than you expect. If you need to use the place geometry manager, prefer to use relx or rely to make relative position placements.

python_wu3zt5czNH python_5bbkg3bhhV

here’s with just the tabs python_n1WsOmIs86

Read more comments on GitHub >

github_iconTop Results From Across the Web

ttkbootstrap not working with pyinstaller - Stack Overflow
json over to the folder, which required me to bring over Symbola.ttf as well. Once done, run pyinstaller main.spec on elevated command prompt....
Read more >
I can't executable with ttkbootstrap library · Issue #43 - GitHub
try running using the command python main.py . All reactions.
Read more >
Reference — ttkbootstrap documentation - Read the Docs
class ttkbootstrap. ... This class is an iterator, so you can iterate over the main style color labels ... It is an error...
Read more >
ttkbootstrap - PyPI
A supercharged theme extension for tkinter that enables on-demand modern flat style themes inspired by Bootstrap. Check out the documentation.
Read more >
Ttkbootstrap installation and list of available styles ... - YouTube
00:00 Sample application demo using Ttkbootstrap 00:50 PIP installation of ttkbootstrap01:05 Blank window using ttkboostrap02:06 Placing ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found