IronReign
IronReign

Reputation: 107

Tkinter label writing over past text. Using lists so i cant use StringVar()

So here is my problem.. I am making a messenger application using tkinter and sockets but for my GUI I am using the label widget to display incoming and outgoing messages. What I am trying to do is have a label retrieve an item from a list like the one in the code displayed and display it on screen. I tried using string variables but it cant call items from a list. Ive been at this for what seems like ages so if anyone knows the fix or a better way to do this please let me know.

# Easy settings
allow_incoming_connections = True # Allows anyone with your ip and port to connect to you. ('True' or 'False')
con_url = "google.com"
con_ip = ""
con_port = "80" 
#Add a IP blocker. sock.deny(idktheactuaulcode)

#Dont mess with the programming... it is barely held together xD
connected = False
from random import randrange
from tkinter import ttk
from tkinter import *
import tkinter as tk, socket, sys, tkinter.messagebox as tm, random
window = Tk()
window.geometry("500x260")
window.resizable(width=FALSE, height=FALSE)
window.iconbitmap(None)#make icon later after coding is done
window.title("Private Messenger")
window.cache = ['TkMessage','- Base 64 data encryption','- /host or /join a chat','- Saving supported','','','- /help for help','','','','Please select an alias:']
window.alias = StringVar()
if con_ip == "":
    con_ip = socket.gethostbyname(con_url)
class tkframe(Frame):
    def __init__(self, master):
        super().__init__(master)
        window.bind("<Return>", self.send)
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.bind((socket.gethostbyname(socket.gethostname()), 4545))
        sock = socket.create_connection((con_ip, con_port),5)
#Variables      
        self.user_input = StringVar()
        self.updatewig()
    def updatewig(self):
        self.user_input.set("")
        input_box = Entry(self, textvariable = self.user_input, width=65).grid(row=12, column=1, sticky=W)
        input_button = ttk.Button(self, command = self.send, text="Send").grid(row=12, column=2, sticky=W)
        self.textdisp = Label(self, text = window.cache[0]).grid(row=1, column=1, sticky=W) 
        self.textdisp = Label(self, text = window.cache[1]).grid(row=2, column=1, sticky=W)
        self.textdisp = Label(self, text = window.cache[2]).grid(row=3, column=1, sticky=W)
        self.textdisp = Label(self, text = window.cache[3]).grid(row=4, column=1, sticky=W)
        self.textdisp = Label(self, text = window.cache[4]).grid(row=5, column=1, sticky=W)
        self.textdisp = Label(self, text = window.cache[5]).grid(row=6, column=1, sticky=W)
        self.textdisp = Label(self, text = window.cache[6]).grid(row=7, column=1, sticky=W)
        self.textdisp = Label(self, text = window.cache[7]).grid(row=8, column=1, sticky=W)
        self.textdisp = Label(self, text = window.cache[8]).grid(row=9, column=1, sticky=W)
        self.textdisp = Label(self, text = window.cache[9]).grid(row=10, column=1, sticky=W)
        self.textdisp = Label(self, text = window.cache[10]).grid(row=11, column=1, sticky=W)
        self.grid()
    def send(self):
        #self.textdisp.withdraw()
        try:
            self.char_check = str(self.user_input.get())[0]
        except:
            pass
        print(self.char_check)
        self.command = self.user_input.get()
        if self.char_check == "/":
            window.cache.append(self.user_input.get())
            del window.cache[0]
            self.user_input.set("")
            self.function()
        else:
            try:
                #send
                window.cache.append(("Me> "+self.user_input.get()))
                del window.cache[0]
            except:
                print("Message could not be sent")
            print(window.cache)
            self.updatewig()
    def function(self):
    # One long if statement to define all the commands 
        if self.command == "/host":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]
        elif self.command == "/join": 
            window.cache.append(("Enter IP:"))
            window.con_ip = self.user_input.get()
            del window.cache[0]
            window.cache.append(("Enter Port:"))
            window.con_port = self.user_input.get()
            del window.cache[0]
            window.cache.append(("Enter alias:"))
            window.alias = self.user_input.get()
            del window.cache[0]
        elif self.command == "/changealias":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]
        elif self.command == "/close":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]
        elif self.command == "/ban":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]
        elif self.command == "/encodeon":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]
        elif self.command == "/encodeoff":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]
        elif self.command == "/commands":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]
        elif self.command == "/mysettings":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]
        elif self.command == "/reset":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]

FRAME = tkframe(window)
window.mainloop()

Upvotes: 0

Views: 213

Answers (1)

Khristos
Khristos

Reputation: 983

You are actually creating new Label widgets (in addition to Entry and Button widgets) over the existing ones anytime you call self.updatewig instead of just changing the text. You need to use the config method to change the text on the labels.

To do that, you first need to separate label creation from placement (grid) since grid returns None and you can't use config on None type. You also need to give the widgets distinct/separate names so you can call them later.

I moved the widget creation into the __init__ method so that updatewig will only change the text of labels.

Here is the code, I hope it works the way you expected:

# Easy settings
allow_incoming_connections = True # Allows anyone with your ip and port to connect to you. ('True' or 'False')
con_url = "google.com"
con_ip = ""
con_port = "80" 
#Add a IP blocker. sock.deny(idktheactuaulcode)

#Dont mess with the programming... it is barely held together xD
connected = False
from random import randrange
from tkinter import ttk
from tkinter import *
import tkinter as tk, socket, sys, tkinter.messagebox as tm, random
window = Tk()
window.geometry("500x260")
window.resizable(width=FALSE, height=FALSE)
window.iconbitmap(None)#make icon later after coding is done
window.title("Private Messenger")
window.cache = ['TkMessage','- Base 64 data encryption','- /host or /join a chat','- Saving supported','','','- /help for help','','','','Please select an alias:']
window.alias = StringVar()
if con_ip == "":
    con_ip = socket.gethostbyname(con_url)
class tkframe(Frame):
    def __init__(self, master):
        super().__init__(master)
        window.bind("<Return>", self.send)
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.bind((socket.gethostbyname(socket.gethostname()), 4545))
        sock = socket.create_connection((con_ip, con_port),5)

    #Variables      
        self.user_input = StringVar()

        ## Create widgets (input, button, labels) only once
        input_box = Entry(self, textvariable = self.user_input, width=65).grid(row=12, column=1, sticky=W)
        input_button = ttk.Button(self, command = self.send, text="Send").grid(row=12, column=2, sticky=W)

        ## Seperate label creation from grid (because grid will return 'None')
        ## Give labels different names
        self.textdisp00 = Label(self, text = "")
        self.textdisp01 = Label(self, text = "")
        self.textdisp02 = Label(self, text = "")
        self.textdisp03 = Label(self, text = "")
        self.textdisp04 = Label(self, text = "")
        self.textdisp05 = Label(self, text = "")
        self.textdisp06 = Label(self, text = "")
        self.textdisp07 = Label(self, text = "")
        self.textdisp08 = Label(self, text = "")
        self.textdisp09 = Label(self, text = "")
        self.textdisp10 = Label(self, text = "")

        ## Grid the labels
        self.textdisp00.grid(row=1, column=1, sticky=W) 
        self.textdisp01.grid(row=2, column=1, sticky=W)
        self.textdisp02.grid(row=3, column=1, sticky=W)
        self.textdisp03.grid(row=4, column=1, sticky=W)
        self.textdisp04.grid(row=5, column=1, sticky=W)
        self.textdisp05.grid(row=6, column=1, sticky=W)
        self.textdisp06.grid(row=7, column=1, sticky=W)
        self.textdisp07.grid(row=8, column=1, sticky=W)
        self.textdisp08.grid(row=9, column=1, sticky=W)
        self.textdisp09.grid(row=10, column=1, sticky=W)
        self.textdisp10.grid(row=11, column=1, sticky=W)


        self.updatewig()

    def updatewig(self):
        ## Change content of the labels using 'config'
        self.user_input.set("")
        self.textdisp00.config(text = window.cache[0]) 
        self.textdisp01.config(text = window.cache[1]) 
        self.textdisp02.config(text = window.cache[2]) 
        self.textdisp03.config(text = window.cache[3]) 
        self.textdisp04.config(text = window.cache[4]) 
        self.textdisp05.config(text = window.cache[5]) 
        self.textdisp06.config(text = window.cache[6]) 
        self.textdisp07.config(text = window.cache[7]) 
        self.textdisp08.config(text = window.cache[8]) 
        self.textdisp09.config(text = window.cache[9]) 
        self.textdisp10.config(text = window.cache[10]) 
        self.grid()

    def send(self, *args): ## Pressing the return key throws an error, so added '*args' to make it work
        #self.textdisp.withdraw()
        try:
            self.char_check = str(self.user_input.get())[0]
        except:
            pass
        print(self.char_check)
        self.command = self.user_input.get()
        if self.char_check == "/":
            window.cache.append(self.user_input.get())
            del window.cache[0]
            self.user_input.set("")
            self.function()
        else:
            try:
                #send
                window.cache.append(("Me> "+self.user_input.get()))
                del window.cache[0]
            except:
                print("Message could not be sent")
            print(window.cache)
            self.updatewig()
    def function(self):
    # One long if statement to define all the commands 
        if self.command == "/host":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]
        elif self.command == "/join": 
            window.cache.append(("Enter IP:"))
            window.con_ip = self.user_input.get()
            del window.cache[0]
            window.cache.append(("Enter Port:"))
            window.con_port = self.user_input.get()
            del window.cache[0]
            window.cache.append(("Enter alias:"))
            window.alias = self.user_input.get()
            del window.cache[0]
        elif self.command == "/changealias":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]
        elif self.command == "/close":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]
        elif self.command == "/ban":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]
        elif self.command == "/encodeon":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]
        elif self.command == "/encodeoff":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]
        elif self.command == "/commands":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]
        elif self.command == "/mysettings":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]
        elif self.command == "/reset":
            window.cache.append(("This command is not yet available."))
            del window.cache[0]

FRAME = tkframe(window)
window.mainloop()

Note

  1. The send method was throwing an error about extra argument when the Return key is pressed so I added *args as a parameter. Now it should work for both the Return key and the 'Send' button.
  2. It will probably be easier (and better?) to use a single Text widget with Normal and Disable states in place of the Labels. I did not use it in my answer because I don't know the reason for which you're using labels.

Upvotes: 1

Related Questions