0

I am using the after method of ttk (tkinter) to update/create some labels in realtime. I have adapted my code from this SO question but i noticed after a while the screen stops responding. I am not sure how long but when I launch the program everything seems to work fine. When I slept off without closing the UI, on return it freezes and unfreezes after few seconds allowing me to interact a few seconds before freezing.

I am unaware of what causes this behaviour but my suspicion is where i make sqlite query to display total records in database. Or maybe I am doing too much label update in one function. Please see update_lbl method below.

For preview of what am trying to achieve see the image

class ReptoUI(ttk.Notebook):
    def __init__(self, parent):
        ttk.Notebook.__init__(self, parent)
        self.parent = parent

        self.parent.title("Repto Mail Checker")

        self.frame1 = ttk.Frame(self.parent, borderwidth=2, relief='groove')  # first page,
        self.frame1.grid(column=0, row=0, sticky=(N, S, E, W))

        self.con()  # configure columns
        self.frame2 = ttk.Frame(self.parent, borderwidth=2, relief='raised')  # second page,
        self.frame2.grid(column=9, row=11, columnspan=11, rowspan=11)
        self.add(self.frame1, text="Checker")
        self.add(self.frame2, text="Sender")

        self.mail_server = StringVar()
        self.mail_port = IntVar()
        self.protocol = StringVar()
        self.folder = StringVar()
        self.mail_type = StringVar()

        self.username = StringVar()
        self.password = StringVar()
        self.log_checker = BooleanVar()
        self.interval = IntVar()

        self.initUI()
        self.centerWindow()

    def con(self):
        for i in range(11):
            self.frame1.grid_columnconfigure(i, weight=1)
            # self.frame1.grid_rowconfigure(i, weight=1)


    def update_lbl(self):
        session = setup_db()
        total = session.query(Contact).count() # my guess is here
        allcountlbl = ttk.Label(self.frame1, text=total)
        allcountlbl.grid(column=7, row=4)

        if not self.username.get():
            username = ''
        else:
            username = self.username.get()

        # if isinstance(username, StringVar):
        #     username = ""

        if not self.folder.get():
            folder = self.folder
        else:
            folder = self.folder.get()
        print type(username)

        addrlbl = ttk.Label(self.frame1, text=username)
        addrlbl.grid(column=2, row=4)

        dirlbl = ttk.Label(self.frame1, text=folder)
        dirlbl.grid(column=4, row=4, sticky=W)
        self.frame1.after(1000, self.update_lbl)
    def statusUI(self):

        workinglbl = ttk.Label(self.frame1, text="Working on:")
        workinglbl.grid(column=1, row=4)
        self.update_lbl()

        boxlbl = ttk.Label(self.frame1, text="Folder:")
        boxlbl.grid(column=3, row=4)
    def initUI(self):
        # First page design tab/frame f1
        self.serverUI()
        self.mailUI()
        self.startUI()
        self.statusUI()

Edit: This is what happens when setup_db is called. Am not sure here if sqlalchemy handles connection closing as there are different variation i could do session.close() or engine.dispose()

def setup_db():
    engine = create_engine('sqlite:///records.db')
    Base.metadata.bind = engine
    DBSession = sessionmaker(bind=engine)
    session = DBSession()
    return session
Community
  • 1
  • 1
Jide Koso
  • 415
  • 5
  • 17
  • 1
    in `update_lbl` you could change text in existing labels instead of creating new labels. Now you have thousands unused labels in memory. – furas Jan 06 '16 at 08:49
  • what `setup_db()` is doing ? Does it create new connection ? Then you have thousands unused connections. – furas Jan 06 '16 at 08:57
  • try to use `session_db()` only once. And create `allcountlbl/addrlbl/dirlbl` only once and then use `allcountlbl.config(text=total)` – furas Jan 06 '16 at 09:37

1 Answers1

1

While maybe not the only thing contributing to the problem, you have a memory leak of sorts. Every second you are creating three new labels. That means after only 10 minutes you will have created 1,800 label widgets. While I think tkinter can handle a few thousand widgets ok, you're creating more than 10,000 per hour.

You should create the labels only once, and then only change their text attribute in the function that gets called every second.

You probably should also move session = setup_db() out of the loop as well. I doubt it's necessary to create a new session every second. Create one session that lives for the life of the program as a whole.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685