Python 3 Tkinter Script to Build Multiplayer People Chat Window UI Widget in GUI Desktop App Full Project For Beginners

Python 3 Tkinter Script to Build Multiplayer People Chat Window UI Widget in GUI Desktop App Full Project For Beginners

 

Welcome folks today in this blog post we will be building a multiplayer people chat window ui widget in tkinter gui desktop app in python. All the full source code of the application is given below.

 

 

Get Started

 

 

In order to get started you need to install the below library using the pip command as shown below

 

pip install tkinter

 

After installing this library you need to make an chatwindow.py file and copy paste the following code

 

chatwindow.py

 

import os

import tkinter as tk
import tkinter.ttk as ttk

from smilieselect import SmilieSelect


class ChatWindow(tk.Toplevel):
    def __init__(self, master, friend_name, friend_avatar, **kwargs):
        super().__init__(**kwargs)
        self.master = master
        self.title(friend_name)
        self.geometry('540x640')
        self.minsize(540, 640)

        self.right_frame = tk.Frame(self)
        self.left_frame = tk.Frame(self)
        self.bottom_frame = tk.Frame(self.left_frame)

        self.messages_area = tk.Text(self.left_frame, bg="white", fg="black", wrap=tk.WORD, width=30)
        self.scrollbar = ttk.Scrollbar(self.left_frame, orient='vertical', command=self.messages_area.yview)
        self.messages_area.configure(yscrollcommand=self.scrollbar.set)

        self.text_area = tk.Text(self.bottom_frame, bg="white", fg="black", height=3, width=30)
        self.text_area.smilies = []
        self.send_button = ttk.Button(self.bottom_frame, text="Send", command=self.send_message, style="send.TButton")

        self.smilies_image = tk.PhotoImage(file="smilies/mikulka-smile-cool.png")
        self.smilie_button = ttk.Button(self.bottom_frame, image=self.smilies_image, command=self.smilie_chooser, style="smilie.TButton")

        self.profile_picture = tk.PhotoImage(file="images/avatar.png")
        self.friend_profile_picture = tk.PhotoImage(file=friend_avatar)

        self.profile_picture_area = tk.Label(self.right_frame, image=self.profile_picture, relief=tk.RIDGE)
        self.friend_profile_picture_area = tk.Label(self.right_frame, image=self.friend_profile_picture, relief=tk.RIDGE)

        self.left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
        self.scrollbar.pack(side=tk.LEFT, fill=tk.Y)
        self.messages_area.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.messages_area.configure(state='disabled')

        self.right_frame.pack(side=tk.LEFT, fill=tk.Y)
        self.profile_picture_area.pack(side=tk.BOTTOM)
        self.friend_profile_picture_area.pack(side=tk.TOP)

        self.bottom_frame.pack(side=tk.BOTTOM, fill=tk.X)
        self.smilie_button.pack(side=tk.LEFT, pady=5)
        self.text_area.pack(side=tk.LEFT, fill=tk.X, expand=1, pady=5)
        self.send_button.pack(side=tk.RIGHT, pady=5)

        self.configure_styles()
        self.bind_events()

    def bind_events(self):
        self.bind("<Return>", self.send_message)
        self.text_area.bind("<Return>", self.send_message)

        self.text_area.bind('<Control-s>', self.smilie_chooser)

    def send_message(self, event=None):
        message = self.text_area.get(1.0, tk.END)

        if message.strip() or len(self.text_area.smilies):
            message = "Me: " + message
            self.messages_area.configure(state='normal')
            self.messages_area.insert(tk.END, message)

            if len(self.text_area.smilies):
                last_line_no = self.messages_area.index(tk.END)
                last_line_no = str(last_line_no).split('.')[0]
                last_line_no = str(int(last_line_no) - 2)

                for index, file in self.text_area.smilies:
                    char_index = str(index).split('.')[1]
                    char_index = str(int(char_index) + 4)
                    smilile_index = last_line_no + '.' + char_index
                    self.messages_area.image_create(smilile_index, image=file)

                self.text_area.smilies = []

            self.messages_area.configure(state='disabled')

            self.text_area.delete(1.0, tk.END)

        return "break"

    def smilie_chooser(self, event=None):
        SmilieSelect(self)

    def add_smilie(self, smilie):
        smilie_index = self.text_area.index(self.text_area.image_create(tk.END, image=smilie))
        self.text_area.smilies.append((smilie_index, smilie))

    def receive_message(self, message, smilies):
        """
        Writes message into messages_area
        :param message: message text
        :param smilies: list of tuples of (char_index, smilie_file), where char_index is the x index of the smilie's location
                        and smilie_file is the file name only (no path)
        :return: None
        """
        self.messages_area.configure(state='normal')
        self.messages_area.insert(tk.END, message)

        if len(smilies):
            last_line_no = self.messages_area.index(tk.END)
            last_line_no = str(last_line_no).split('.')[0]
            last_line_no = str(int(last_line_no) - 2)

            for index, file in smilies:
                smilie_path = os.path.join(SmilieSelect.smilies_dir, file)
                image = tk.PhotoImage(file=smilie_path)
                smilie_index = last_line_no + '.' + index
                self.messages_area.image_create(smilie_index, image=image)

        self.messages_area.configure(state='disabled')

    def configure_styles(self):
        style = ttk.Style()
        style.configure("send.TButton", background='#dddddd', foreground="black", padding=16)


if __name__ == '__main__':
    w = tk.Tk()
    c = ChatWindow(w, 'friend', 'images/avatar.png')
    c.protocol("WM_DELETE_WINDOW", w.destroy)
    w.mainloop()

 

See also  Python 3 Script to Extract Numbers & Email Addresses From String Using Regular Expression Full Project For Beginners

 

friendslist.py

 

import tkinter as tk
import tkinter.ttk as ttk

from chatwindow import ChatWindow


class FriendsList(tk.Tk):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.title('Tk Chat')
        self.geometry('700x500')

        self.menu = tk.Menu(self, bg="lightgrey", fg="black", tearoff=0)

        self.friends_menu = tk.Menu(self.menu, fg="black", bg="lightgrey", tearoff=0)
        self.friends_menu.add_command(label="Add Friend", command=self.add_friend)

        self.menu.add_cascade(label="Friends", menu=self.friends_menu)

        self.configure(menu=self.menu)

        self.canvas = tk.Canvas(self, bg="white")
        self.canvas_frame = tk.Frame(self.canvas)

        self.scrollbar = ttk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=self.scrollbar.set)

        self.scrollbar.pack(side=tk.LEFT, fill=tk.Y)
        self.canvas.pack(side=tk.LEFT, expand=1, fill=tk.BOTH)

        self.friends_area = self.canvas.create_window((0, 0), window=self.canvas_frame, anchor="nw")

        self.bind_events()

        self.load_friends()

    def bind_events(self):
        self.bind('<Configure>', self.on_frame_resized)
        self.canvas.bind('<Configure>', self.friends_width)

    def friends_width(self, event):
        canvas_width = event.width
        self.canvas.itemconfig(self.friends_area, width=canvas_width)

    def on_frame_resized(self, event=None):
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))

    def load_friends(self):
        friend_frame = ttk.Frame(self.canvas_frame)

        profile_photo = tk.PhotoImage(file="images/avatar.png")
        profile_photo_label = ttk.Label(friend_frame, image=profile_photo)
        profile_photo_label.image = profile_photo

        friend_name = ttk.Label(friend_frame, text="Jaden Corebyn", anchor=tk.W)

        message_button = ttk.Button(friend_frame, text="Chat", command=self.open_chat_window)

        profile_photo_label.pack(side=tk.LEFT)
        friend_name.pack(side=tk.LEFT)
        message_button.pack(side=tk.RIGHT)

        friend_frame.pack(fill=tk.X, expand=1)

    def add_friend(self):
        self.load_friends()

    def open_chat_window(self):
        cw = ChatWindow(self, 'Jaden Corebyn', 'images/avatar.png')

if __name__ == '__main__':
    f = FriendsList()
    f.mainloop()

 

 

smilieselect.py

 

import os

import tkinter as tk
import tkinter.ttk as ttk


class SmilieSelect(tk.Toplevel):
    smilies_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'smilies/'))

    def __init__(self, master, **kwargs):
        super().__init__(**kwargs)
        self.master = master
        self.transient(master)
        self.position_window()

        smilie_files = [file for file in os.listdir(self.smilies_dir) if file.endswith(".png")]

        self.smilie_images = []

        for file in smilie_files:
            full_path = os.path.join(self.smilies_dir, file)
            image = tk.PhotoImage(file=full_path)
            self.smilie_images.append(image)

        for index, file in enumerate(self.smilie_images):
            row, col = divmod(index, 3)
            button = ttk.Button(self, image=file, command=lambda s=file: self.insert_smilie(s))
            button.grid(row=row, column=col, sticky='nsew')

        for i in range(3):
            tk.Grid.columnconfigure(self, i, weight=1)
            tk.Grid.rowconfigure(self, i, weight=1)

    def position_window(self):
        master_pos_x = self.master.winfo_x()
        master_pos_y = self.master.winfo_y()

        master_width = self.master.winfo_width()
        master_height = self.master.winfo_height()

        my_width = 100
        my_height = 100

        pos_x = (master_pos_x + (master_width // 2)) - (my_width // 2)
        pos_y = (master_pos_y + (master_height // 2)) - (my_height // 2)

        geometry = f"{my_width}x{my_height}+{pos_x}+{pos_y}"
        self.geometry(geometry)

    def insert_smilie(self, smilie):
        self.master.add_smilie(smilie)
        self.destroy()


if __name__ == '__main__':
    w = tk.Tk()
    s = SmilieSelect(w)
    w.mainloop()

 

See also  Python 3 Tkinter BookStore List Management System Using SQLite Database GUI Desktop App Full Project For Beginners

If you execute the above python script by typing the below command

 

python chatwindow.py

 

 

 

 

FULL SOURCE CODE GITHUB REPOSITORY

Leave a Reply