NewDeveloper404
NewDeveloper404

Reputation: 45

Tkinter inserting text "live" into a textbox

Bit of a beginner here :)

So for the past couple of days I've been working on a relatively simple web scraper, but with a special goal in mind. Namely, I wanted to get better with tkinter.

So, I've made a devlog window, which is simply going to be a separate console kind of thing. But the problem is that I want to insert text "live" in to the devlog window, and the text comes from a different script in a different thread. How could I implement this feature? This devlog window is ALSO run in a thread, as well as 3 other scripts along side it. This is the code I have so far:

import Manager as AM
import tkinter as tk
from time import sleep  # For some simple timing algorithms

Width = 700
Height = 500
FrameGeometry = str(Width) + "x" + str(Height)

# COLORS
LightGrey = "#D9D9D9"
DarkGrey = "#AAAAAA"

# Global variables.
ThreadsList = list()

def CreateDevLogWindow():
    global Width
    global Height

    ThreadTemp_ = str(AM.FileManager(ReadData=2))

    devlog = tk.Tk()  # Secondary Devlog Interface.
    FrameInfo = tk.Frame(master=devlog)
    FrameText = tk.Frame(master=devlog)
    ThreadText = tk.Label(master=FrameInfo, text="Total Threads: " + ThreadTemp_, bg="white")
    ThreadTextActive = tk.Label(master=FrameInfo, text="Active Threads: " + ThreadTemp_, bg="white")
    InfoText = tk.Text(FrameText, border=1, highlightthickness=1)

    devlog.title("Devlog: YourOptimalScrapper")
    devlog.geometry(str(Width) + "x" + str(Height))
    devlog.config(bg="white")

    FrameInfo.config(bg="white")
    FrameText.config(bg="white", padx=5, pady=5)

    FrameInfo.pack(side=tk.TOP, fill=tk.BOTH)
    FrameText.pack(side=tk.BOTTOM, expand=True, fill=tk.BOTH)

    ThreadText.grid(row=0)
    ThreadTextActive.grid(row=1)

    InfoText.pack(expand=True, fill=tk.BOTH)

    while True:
        if ThreadTemp_ != AM.FileManager(ReadData=2):
            ThreadTemp_ = str(AM.FileManager(ReadData=2))
            ThreadText.config(text="Total Threads: " + ThreadTemp_)
            ThreadTextActive.config(text="Active Threads: " + ThreadTemp_)

        devlog.update()

Any and all help is appreciated, and NOTE: There is more code under this, but I don't think its particularly necessary :)

Upvotes: 1

Views: 1809

Answers (1)

Larsluph
Larsluph

Reputation: 159

First of all you can insert text in your TextBox with just a few lines.

def update_textbox(textbox, data):
    textbox.config(state=tk.NORMAL) # unlock the textbox
    textbox.insert(tk.END, "\n"+str(data)) # add newline and append the data
    textbox.config(state=tk.DISABLED) # lock back the textbox to readonly
    textbox.see(tk.END) # scroll to the bottom to see the last line

With that if your script is in a different thread, then you can create a file that will be the "carrier" of your data.

Whenever you need to write data to the textbox, simply write data to the file with your text in any thread and update the while loop in the above code to read this file and update the textbox if the file isn't empty.

EDIT: You don't need to call this function outside of this thread. Just check in your while loop whether new data has to be added to the log

...
    while True:
        with open("carrier.txt", 'r') as f:
            content = f.read() # read carrier data
            if content: # if file isn't empty
               update_textbox(InfoText, content) # update the textbox with the data in the file
        open("carrier.txt", 'w').close() # clear the file to prevent reading the data twice

        if ThreadTemp_ != AM.FileManager(ReadData=2):
            ThreadTemp_ = str(AM.FileManager(ReadData=2))
            ThreadText.config(text="Total Threads: " + ThreadTemp_)
            ThreadTextActive.config(text="Active Threads: " + ThreadTemp_)

        devlog.update()

And in your other thread

def update_log(data):
    with open("carrier.txt", 'a') as f: # append to the file
        f.write(str(data))

Upvotes: 3

Related Questions