bitbyte
bitbyte

Reputation: 119

Tkinter textbox widget not displaying text correctly

I am currently writing a program, which allows the user to enter a list(for example: 9,8,7,6,5,4,3,2,1) and the program should sort the list using selection sort. The sort algorithm works fine, but the program should also be able to print every new list that is created by swapping elements. However in my code these lists are printed correctly into the console, but are not correctly displayed in the textbox.

import tkinter as tk    
from tkinter import messagebox
import time


class SelectionSort:
    def __init__(self):
        self.input_list = []
        self.output_list = []
        self.time = 1000
        root.geometry("500x500")
        root.resizable(False, False)
        root.title("Selection-Sort")
        self.titel = tk.Label(root, text="Selection - Sort", font =    ("Courier", "19", "underline"), justify="center").pack()
        self.text = tk.Text(root, height=22, width=60, relief="solid")
        self.text.pack()
        self.help_string  = "Instructions:\n   1. Numbers have to be     seperated using a comma.\n" \
                   "   2. Only integers are accepted.\n   3.You can view the text again by pressing the help button"
        self.text.insert(tk.END, self.help_string)
        self.print_button = tk.Button(root, text="Sort input!", command=lambda: self.retrieve_input(), width=68,
                                  relief="groove", activebackground="dark grey").pack()
        self.delete_button = tk.Button(root, text="Delete input", command=lambda:     self.delete_text(), width=68,
                                  relief="groove", activebackground="dark grey").pack()
        self.help_button = tk.Button(root, text="Show help", command=lambda: self.show_help(), width=68,relief="groove",activebackground="dark grey").pack()

    def retrieve_input(self):
        input = self.text.get("1.0", "end-1c")
        curr_value = ""
        count = 0
        for i in input:
            try:
                curr_value += i
                if i == ",":
                    final = curr_value.replace(",", "")
                    self.input_list.append(int(final))
                    curr_value = ""
                else:
                    if curr_value == "":
                        pass
            except ValueError:
                curr_value = ""
            count += 1
        print(self.input_list)
        self.input_list.append(int(curr_value))
        print(self.input_list)
        if len(self.input_list) == 0:
            self.delete_text()
            self.text.insert(tk.END, "ERROR")
        else:
            self.text.delete("1.0", "end")
            self.text.insert(tk.END, "Input list: ")
            self.text.insert(tk.END, self.input_list)
        return self.selection_sort()

    def delete_text(self):
        self.input_list = []
        self.text.delete("1.0", "end")

    def show_help(self):
        messagebox.showinfo("Help", self.help_string )

    def selection_sort(self):

        sorted_lists = []
        A = self.input_list
        count = 1
        for i in range(len(A)):
            print(A)
            self.time += 1000
            min_idx = i
            for j in range(i + 1, len(A)):
                if A[min_idx] > A[j]:
                    min_idx = j
            A[i], A[min_idx] = A[min_idx], A[i]
            sorted_lists.append(A)
            root.after(self.time, func=lambda: 
            self.text.insert(tk.END,"\n"+str(A) + "\n"))
            count+=1
        print("Sorted array")
        for i in range(len(A)):
            print("%d" % A[i]),

root = tk.Tk()
selection_sort = SelectionSort()
root.mainloop()

Upvotes: 0

Views: 372

Answers (1)

Kevin
Kevin

Reputation: 76194

That root.after call looks suspicious to me. Any changes you make to A will be propagated to the self.text.insert call, so if you finish sorting in under a second, then your text box will only display the completely sorted form of A.

If you pass a copy of A to the lambda, and avoid the late binding gotcha while you're at it, then the text box should display the state of A as it existed inside the loop.

    for i in range(len(A)):
        print(A)
        root.after(self.time, func=lambda A=A.copy(): self.text.insert(tk.END,"\n"+str(A) + "\n"))
        self.time += 1000
        min_idx = i
        for j in range(i + 1, len(A)):
            if A[min_idx] > A[j]:
                min_idx = j
        A[i], A[min_idx] = A[min_idx], A[i]
        sorted_lists.append(A)
        count+=1

Upvotes: 1

Related Questions