fork download
  1. # your code goes here
Success #stdin #stdout 0.08s 14076KB
stdin
import tkinter as tk
from tkinter import scrolledtext, messagebox
import socket
import threading
import sys

class ChatClient:
    def __init__(self, root):
        self.root = root
        self.root.title("局域网聊天室")
        self.root.geometry("600x450")
        self.root.resizable(False, False)

        # 连接信息
        self.socket = None
        self.nickname = ""

        # 界面组件
        self.create_widgets()

        # 先弹出连接对话框
        self.connect_to_server()

    def create_widgets(self):
        # 消息显示区域
        self.text_area = scrolledtext.ScrolledText(self.root, state='disabled', wrap=tk.WORD)
        self.text_area.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)

        # 底部框架
        bottom_frame = tk.Frame(self.root)
        bottom_frame.pack(padx=10, pady=10, fill=tk.X)

        self.entry = tk.Entry(bottom_frame)
        self.entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
        self.entry.bind("<Return>", lambda e: self.send_message())

        send_btn = tk.Button(bottom_frame, text="发送", command=self.send_message)
        send_btn.pack(side=tk.RIGHT, padx=5)

    def connect_to_server(self):
        """弹出对话框,输入服务器IP和昵称"""
        dialog = tk.Toplevel(self.root)
        dialog.title("连接设置")
        dialog.geometry("300x200")
        dialog.resizable(False, False)
        dialog.grab_set()  # 模态

        tk.Label(dialog, text="服务器IP:").pack(pady=5)
        ip_entry = tk.Entry(dialog, width=20)
        ip_entry.pack()
        ip_entry.insert(0, "127.0.0.1")  # 默认本机

        tk.Label(dialog, text="昵称:").pack(pady=5)
        name_entry = tk.Entry(dialog, width=20)
        name_entry.pack()

        def do_connect():
            ip = ip_entry.get().strip()
            nick = name_entry.get().strip()
            if not ip or not nick:
                messagebox.showerror("错误", "请填写完整信息")
                return
            self.nickname = nick
            try:
                self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self.socket.connect((ip, 12345))
                # 先发送昵称
                self.socket.send(nick.encode('utf-8'))
                # 启动接收线程
                recv_thread = threading.Thread(target=self.receive_messages, daemon=True)
                recv_thread.start()
                dialog.destroy()
            except Exception as e:
                messagebox.showerror("连接失败", f"无法连接服务器:{e}")

        tk.Button(dialog, text="连接", command=do_connect).pack(pady=15)

    def receive_messages(self):
        """持续接收服务器消息并显示"""
        while True:
            try:
                msg = self.socket.recv(1024).decode('utf-8')
                if not msg:
                    break
                self.display_message(msg)
            except:
                break
        # 断开连接后关闭窗口
        self.root.after(0, lambda: messagebox.showerror("连接断开", "与服务器失去连接"))
        self.root.after(0, self.root.destroy)

    def display_message(self, msg):
        """在文本区域添加消息(线程安全)"""
        self.text_area.config(state='normal')
        self.text_area.insert(tk.END, msg + "\n")
        self.text_area.see(tk.END)
        self.text_area.config(state='disabled')

    def send_message(self):
        text = self.entry.get().strip()
        if not text:
            return
        # 检查是否是私聊(格式:@昵称 消息内容)
        if text.startswith('@'):
            parts = text.split(' ', 1)
            if len(parts) == 2:
                target = parts[0][1:]
                content = parts[1]
                full_msg = f"[私聊{target}]{content}"
                try:
                    self.socket.send(full_msg.encode('utf-8'))
                    self.display_message(f"[你私聊{target}]: {content}")
                except:
                    self.display_message("发送失败")
            else:
                self.display_message("私聊格式错误,请用 @昵称 消息内容")
        else:
            # 普通群聊
            try:
                self.socket.send(text.encode('utf-8'))
                self.display_message(f"我: {text}")
            except:
                self.display_message("发送失败")
        self.entry.delete(0, tk.END)

if __name__ == "__main__":
    root = tk.Tk()
    app = ChatClient(root)
    root.mainloop()
stdout
Standard output is empty