0

I have the GUI class shown below for the user to write and receive a message. I use tkinder in the GUI and it's returning the error when passing the receive function:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Python39\lib\threading.py", line 954, in _bootstrap_inner
    self.run()
  File "C:\Python39\lib\threading.py", line 892, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Users\Matheus William\Documents\Desenvolvimento\python\trabalho-redes\client.py", line 71, in receive
    self.chat_transcript_area.insert('end', '\n{}'.format(message))
AttributeError: 'NoneType' object has no attribute 'insert'

And yes I know there are similar issues here on StackOverflow, but I haven't found anything that can help me. Who can help me I appreciate it?

The code:

import socket
import threading
import sys
import time
from tkinter import *
from tkinter import messagebox

class Principal:
    # Verifica se o nome e os argumentos foram corretamente entrados
    if(len(sys.argv) < 3):
        print('\n\nUso: python client.py SERVER-IP PORT\n\n')
        sys.exit()

    host = sys.argv[1]
    # Verifica se a porta é um numero inteiro
    try:
        port = int(sys.argv[2])
    except:
        print('\n\nForneça a porta do servidor.\n\n')
        sys.exit()

    # verifica se é possivel conectar com o servidor
    try:
        # inicia o socket
        client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # conecta o usuario ao servidor
        client.connect((host, port))
    except:
        print('\n\nErro ao conectar com o servidor\n\n')
        sys.exit()

    def __init__(self):
        self.chat_transcript_area = None
        self.enter_text_widget = None
        self.main_account_screen()

    def login_verify(self):
        global nickname, senha
        nickname = self.username_verify.get()
        senha = self.password_verify.get()
        self.username_login_entry.delete(0, END)
        self.password_login_entry.delete(0, END)
        if nickname == '' and senha == '':
            messagebox.showerror("Erro", "Os campos não pode ficar vazios.")
        else:
            # recebendo varias mensagens
            receive_thread = threading.Thread(target=self.receive)
            receive_thread.start()

            # valida se os dados de login estão corretos ou
            # se o usuario já está logado
            id = self.client.recv(4096).decode('utf-8')
            if id == str(-1) or id == str(-2):
                if id == str(-1):
                    messagebox.showerror("Erro", "Dados de login invalidos.")
                else:
                    messagebox.showerror("Erro", "Usuario já logado.")
                self.client.close()
                sys.exit(0)
            else:
                self.login_screen.destroy()
                self.write()
            self.login_screen.destroy()

    # fazendo uma conexão valida
    def receive(self):
        while True:
            try:
                message = self.client.recv(4096).decode('utf-8')
                if message == 'NICKNAME':
                    self.client.send(nickname.encode('utf-8'))
                    self.client.send(senha.encode('utf-8'))
                else:
                    self.chat_transcript_area.insert(
                        'end', '\n{}'.format(message))
                    self.chat_transcript_area.yview(END)
            except AssertionError as error:
                print("\n\n"+error)
                print("Bye bye!")
                sys.stderr.write()
                break

    def on_enter_key_pressed(self, event):
        self.sendChat()
        self.clear_text()

    def clear_text(self):
        self.enter_text_widget.delete(1.0, 'end')

    def sendChat(self):
        data = self.enter_text_widget.get(1.0, 'end').strip()
        if data != None:
            message = '{}: {}'.format(nickname, data)
            self.client.send(message.encode('utf-8'))

    # layout da mensagem
    def write(self):
        self.root = Tk()
        self.root.title("Chat")
        self.root.protocol("WM_DELETE_WINDOW", self.on_closing_chat)
        self.frame = Frame(self.root)
        Label(self.frame, text='Chat Box:',
              font=("Serif", 12)).pack(side='top')
        self.chat_transcript_area = Text(
            self.frame, width=60, height=10, font=("Serif", 12))
        self.chat_transcript_area.config(state='disabled')
        self.scrollbar = Scrollbar(
            self.frame, command=self.chat_transcript_area.yview, orient=VERTICAL)
        self.chat_transcript_area.config(yscrollcommand=self.scrollbar.set)
        self.chat_transcript_area.pack(side='left', padx=10)
        self.scrollbar.pack(side='right', fill='y')
        self.frame.pack(side='top')
        Label(self.root, text='Enter message:',
              font=("Serif", 12)).pack(side='top')
        self.enter_text_widget = Text(
            self.root, width=60, height=1, font=("Serif", 12))
        self.enter_text_widget.pack(side='bottom', pady=1)
        self.enter_text_widget.bind('<Return>', self.on_enter_key_pressed)

        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        x_cordinate = int((screen_width/2) - (400/2))
        y_cordinate = int((screen_height/2) - (270/2))

        self.root.geometry(
            "{}x{}+{}+{}".format(400, 270, x_cordinate, y_cordinate))
        self.root.mainloop()

    def on_closing_chat(self):
        if messagebox.askokcancel("Sair", "Deseja sair do chat?"):
            self.root.destroy()
            self.client.close()
            exit(0)

    def on_closing(self):
        if messagebox.askokcancel("Sair", "Deseja sair do login?"):
            self.login_screen.destroy()
            self.client.close()
            exit(0)

    # Designing Main(first) window
    def main_account_screen(self):
        self.login_screen = Tk()
        # This code helps to disable windows from resizing
        self.login_screen.resizable(False, False)
        self.login_screen.protocol("WM_DELETE_WINDOW", self.on_closing)
        self.login_screen.title("Login")
        Label(self.login_screen, text="Faça o login para usar o chat").pack()
        Label(self.login_screen, text="").pack()

        self.username_verify = StringVar()
        self.password_verify = StringVar()

        Label(self.login_screen, text="Username * ").pack()
        self.username_login_entry = Entry(
            self.login_screen, textvariable=self.username_verify)
        self.username_login_entry.pack()
        Label(self.login_screen, text="").pack()
        Label(self.login_screen, text="Password * ").pack()
        self.password_login_entry = Entry(
            self.login_screen, textvariable=self.password_verify, show='*')
        self.password_login_entry.pack()
        Label(self.login_screen, text="").pack()
        Button(self.login_screen, text="Login", width=10,
               height=1, command=self.login_verify).pack()

        screen_width = self.login_screen.winfo_screenwidth()
        screen_height = self.login_screen.winfo_screenheight()

        x_cordinate = int((screen_width/2) - (300/2))
        y_cordinate = int((screen_height/2) - (210/2))

        self.login_screen.geometry(
            "{}x{}+{}+{}".format(300, 210, x_cordinate, y_cordinate))

        self.login_screen.mainloop()    
Principal()
1
  • 1
    The error seems pretty self-explanatory: self.chat_transcript is None when you're assuming it has been initialized to a widget. Commented Jul 10, 2021 at 5:16

1 Answer 1

1

-> receive_thread = threading.Thread(target=self.receive)

You call the self.receive function before calling self.write.

...
receive_thread = threading.Thread(target=self.receive)
...
else:
    self.login_screen.destroy()
    self.write()
...

self.chat_transcript_area is still None at this stage.

The Text widget must be created before you try to write anything to it.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.