Skip to content
Related Articles

Related Articles

GUI chat application using Tkinter in Python
  • Difficulty Level : Medium
  • Last Updated : 29 Dec, 2020

Prerequisites: Tkinter , Socket Programming and Multithreading

This is a simple GUI (Graphical User Interface) chat application where multiple users can connect with each other in a client-server architecture i.e the clients will interact with the help of the server.

Server Side Script:  This script file name is ‘client.py'(say) .
Since only the clients will interact the server script does not have a GUI

Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# import socket library
import socket
  
# import threading library
import threading
  
# Choose a port that is free
PORT = 5000
  
# An IPv4 address is obtained
# for the server.   
SERVER = socket.gethostbyname(socket.gethostname())
  
# Address is stored as a tuple
ADDRESS = (SERVER, PORT)
  
# the format in which encoding
# and decoding will occur
FORMAT = "utf-8"
  
# Lists that will contains
# all the clients connected to 
# the server and their names.
clients, names = [], []
  
# Create a new socket for
# the server 
server = socket.socket(socket.AF_INET,
                       socket.SOCK_STREAM)
  
# bind the address of the 
# server to the socket 
server.bind(ADDRESS)
  
# function to start the connection
def startChat():
    
    print("server is working on " + SERVER)
      
    # listening for connections 
    server.listen()
      
    while True:
        
        # accept connections and returns 
        # a new connection to the client
        #  and  the address bound to it 
        conn, addr =  server.accept()
        conn.send("NAME".encode(FORMAT))
          
        # 1024 represents the max amount
        # of data that can be received (bytes)
        name = conn.recv(1024).decode(FORMAT)
          
        # append the name and client
        # to the respective list
        names.append(name)
        clients.append(conn)
          
        print(f"Name is :{name}")
          
        # broadcast message
        broadcastMessage(f"{name} has joined the chat!".encode(FORMAT))
          
        conn.send('Connection successful!'.encode(FORMAT))
          
        # Start the handling thread
        thread = threading.Thread(target = handle,
                                  args = (conn, addr))
        thread.start()
          
        # no. of clients connected
        # to the server
        print(f"active connections {threading.activeCount()-1}")
  
# method to handle the 
# incoming messages 
def handle(conn, addr):
    
    print(f"new connection {addr}")
    connected = True
      
    while connected:
          # recieve message
        message = conn.recv(1024)
          
        # broadcast message
        broadcastMessage(message)
      
    # close the connection
    conn.close()
  
# method for broadcasting 
# messages to the each clients
def broadcastMessage(message):
    for client in clients:
        client.send(message)
  
# call the method to 
# begin the communication
startChat()

chevron_right


Client-Side Script: 



Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# import all the required  modules
import socket
import threading
from tkinter import *
from tkinter import font
from tkinter import ttk
  
# import all functions /
#  everthing from chat.py file
from chat import *
  
PORT = 5050
SERVER = "192.168.0.103"
ADDRESS = (SERVER, PORT)
FORMAT = "utf-8"
  
# Create a new client socket
# and connect to the server
client = socket.socket(socket.AF_INET, 
                      socket.SOCK_STREAM)
client.connect(ADDRESS)
  
  
# GUI class for the chat
class GUI:
    # constructor method
    def __init__(self):
        
        # chat window which is currently hidden
        self.Window = Tk()
        self.Window.withdraw()
          
        # login window
        self.login = Toplevel()
        # set the title
        self.login.title("Login")
        self.login.resizable(width = False
                             height = False)
        self.login.configure(width = 400,
                             height = 300)
        # create a Label
        self.pls = Label(self.login, 
                       text = "Please login to continue",
                       justify = CENTER, 
                       font = "Helvetica 14 bold")
          
        self.pls.place(relheight = 0.15,
                       relx = 0.2
                       rely = 0.07)
        # create a Label
        self.labelName = Label(self.login,
                               text = "Name: ",
                               font = "Helvetica 12")
          
        self.labelName.place(relheight = 0.2,
                             relx = 0.1
                             rely = 0.2)
          
        # create a entry box for 
        # tyoing the message
        self.entryName = Entry(self.login, 
                             font = "Helvetica 14")
          
        self.entryName.place(relwidth = 0.4
                             relheight = 0.12,
                             relx = 0.35,
                             rely = 0.2)
          
        # set the focus of the curser
        self.entryName.focus()
          
        # create a Continue Button 
        # along with action
        self.go = Button(self.login,
                         text = "CONTINUE"
                         font = "Helvetica 14 bold"
                         command = lambda: self.goAhead(self.entryName.get()))
          
        self.go.place(relx = 0.4,
                      rely = 0.55)
        self.Window.mainloop()
  
    def goAhead(self, name):
        self.login.destroy()
        self.layout(name)
          
        # the thread to receive messages
        rcv = threading.Thread(target=self.receive)
        rcv.start()
  
    # The main layout of the chat
    def layout(self,name):
        
        self.name = name
        # to show chat window
        self.Window.deiconify()
        self.Window.title("CHATROOM")
        self.Window.resizable(width = False,
                              height = False)
        self.Window.configure(width = 470,
                              height = 550,
                              bg = "#17202A")
        self.labelHead = Label(self.Window,
                             bg = "#17202A"
                              fg = "#EAECEE",
                              text = self.name ,
                               font = "Helvetica 13 bold",
                               pady = 5)
          
        self.labelHead.place(relwidth = 1)
        self.line = Label(self.Window,
                          width = 450,
                          bg = "#ABB2B9")
          
        self.line.place(relwidth = 1,
                        rely = 0.07,
                        relheight = 0.012)
          
        self.textCons = Text(self.Window,
                             width = 20
                             height = 2,
                             bg = "#17202A",
                             fg = "#EAECEE",
                             font = "Helvetica 14"
                             padx = 5,
                             pady = 5)
          
        self.textCons.place(relheight = 0.745,
                            relwidth = 1
                            rely = 0.08)
          
        self.labelBottom = Label(self.Window,
                                 bg = "#ABB2B9",
                                 height = 80)
          
        self.labelBottom.place(relwidth = 1,
                               rely = 0.825)
          
        self.entryMsg = Entry(self.labelBottom,
                              bg = "#2C3E50",
                              fg = "#EAECEE",
                              font = "Helvetica 13")
          
        # place the given widget
        # into the gui window
        self.entryMsg.place(relwidth = 0.74,
                            relheight = 0.06,
                            rely = 0.008,
                            relx = 0.011)
          
        self.entryMsg.focus()
          
        # create a Send Button
        self.buttonMsg = Button(self.labelBottom,
                                text = "Send",
                                font = "Helvetica 10 bold"
                                width = 20,
                                bg = "#ABB2B9",
                                command = lambda : self.sendButton(self.entryMsg.get()))
          
        self.buttonMsg.place(relx = 0.77,
                             rely = 0.008,
                             relheight = 0.06
                             relwidth = 0.22)
          
        self.textCons.config(cursor = "arrow")
          
        # create a scroll bar
        scrollbar = Scrollbar(self.textCons)
          
        # place the scroll bar 
        # into the gui window
        scrollbar.place(relheight = 1,
                        relx = 0.974)
          
        scrollbar.config(command = self.textCons.yview)
          
        self.textCons.config(state = DISABLED)
  
    # function to basically start the thread for sending messages
    def sendButton(self, msg):
        self.textCons.config(state = DISABLED)
        self.msg=msg
        self.entryMsg.delete(0, END)
        snd= threading.Thread(target = self.sendMessage)
        snd.start()
  
    # function to receive messages
    def receive(self):
        while True:
            try:
                message = client.recv(1024).decode(FORMAT)
                  
                # if the messages from the server is NAME send the client's name
                if message == 'NAME':
                    client.send(self.name.encode(FORMAT))
                else:
                    # insert messages to text box
                    self.textCons.config(state = NORMAL)
                    self.textCons.insert(END,
                                         message+"\n\n")
                      
                    self.textCons.config(state = DISABLED)
                    self.textCons.see(END)
            except:
                # an error will be printed on the command line or console if there's an error
                print("An error occured!")
                client.close()
                break 
          
    # function to send messages 
    def sendMessage(self):
        self.textCons.config(state=DISABLED)
        while True:
            message = (f"{self.name}: {self.msg}")
            client.send(message.encode(FORMAT))    
            break    
  
# create a GUI class object
g = GUI()

chevron_right


OUTPUT : 
 

Login Window : 

CLIENT 1 : 

CLIENT 2 :



 
CLIENT 3 :

 
SERVER :

 

Attention geek! Strengthen your foundations with the Python Programming Foundation Course and learn the basics.

To begin with, your interview preparations Enhance your Data Structures concepts with the Python DS Course.

My Personal Notes arrow_drop_up
Recommended Articles
Page :