Как создать индикатор ввода с помощью tkinter? - PullRequest
0 голосов
/ 06 марта 2019

Я создал настоящий чат в Python с tkinter.

Я хочу знать, как создать индикатор ввода без использования firebase.Под этим я подразумеваю, что, скажем, одно из имен пользователя - bob, и если Боб печатает сообщение, я хочу, чтобы оно сообщило другим пользователям, что bob is typing..., и я хочу, чтобы оно, если возможно, появилосьповерх окна сообщения типа.

Редактировать:

Я добавил это в:

def var_changed(self):
   self.label.config(text=msg+"is typing")

my_msg = tkinter.StringVar()
my_msg.trace = ("w", var_changed)
entry_field = tkinter.Entry(top, textvariable=my_msg)
entry_field.pack()

, но все, что он делает, это копирует то, что я пишу, вместо того, чтобы говоритьпользователь набирает сообщение

Server.py

import socket, threading

host = socket.gethostname()
port = 4000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen()
clients = {}
addresses = {}
print(host)
print("Server is ready...")
serverRunning = True

def handle_client(conn):
    try:
        data = conn.recv(1024).decode('utf8')
        welcome = 'Welcome %s! If you ever want to quit, type {quit} to exit.' % data
        conn.send(bytes(welcome, "utf8"))
        msg = "%s has joined the chat" % data
        broadcast(bytes(msg, "utf8"))
        clients[conn] = data
        while True:
            found = False
            response = 'Number of People Online\n'
            msg1 = conn.recv(1024)

            if msg1 != bytes("{quit}", "utf8"):
                broadcast(msg1, data+": ")
            else:
                conn.send(bytes("{quit}", "utf8"))
                conn.close()
                del clients[conn]
                broadcast(bytes("%s has left the chat." % data, "utf8"))
                break
    except:
        print("%s has left the chat." % data)

def broadcast(msg, prefix=""):
    for sock in clients:
        sock.send(bytes(prefix, "utf8")+msg)

while True:
    conn,addr = s.accept()
    conn.send("Enter username: ".encode("utf8"))
    print("%s:%s has connected." % addr)
    addresses[conn] = addr
    threading.Thread(target = handle_client, args = (conn,)).start()

Client.py

import socket,threading,tkinter

host = input("Enter server name: ")
port = 4000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
address = (host,port)

def echo_data(sock):
   while True:
      try:
         msg = sock.recv(1024).decode('utf8')
         msg_list.insert(tkinter.END, msg)
      except OSError:
         break

def send(event=None):
   msg = my_msg.get()
   my_msg.set("")
   s.send(bytes(msg, "utf8"))
   if msg == "{quit}":
      s.close()
      top.quit()

def on_closing(event=None):
    my_msg.set("{quit}")
    send()

top = tkinter.Tk()
top.title("Chat Room")

messages_frame = tkinter.Frame(top)
my_msg = tkinter.StringVar()
my_msg.set("Type your messages here.")
scrollbar = tkinter.Scrollbar(messages_frame)
msg_list = tkinter.Listbox(messages_frame, height=15, width=100, yscrollcommand=scrollbar.set)
scrollbar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
msg_list.pack(side=tkinter.LEFT, fill=tkinter.BOTH)
msg_list.pack()
messages_frame.pack()

entry_field = tkinter.Entry(top, textvariable=my_msg)
entry_field.bind("<Return>", send)
entry_field.pack()
send_button = tkinter.Button(top, text="Send", command=send)
send_button.pack()

top.protocol("WM_DELETE_WINDOW", on_closing)

address = (host,port)
s.connect(address)

threading.Thread(target=echo_data, args = (s,)).start()

tkinter.mainloop()

1 Ответ

2 голосов
/ 07 марта 2019

Вопрос : создать индикатор набора текста для tkinter.Entry виджет

  1. Определить класс приложения, унаследованный от tk.Tk, только для демонстрации.

    import tkinter as tk
    
    class App(tk.Tk):
    
        def __init__(self):
            super().__init__()
    
  2. Инициируйте флаг .is_typing, чтобы узнать, что печатание было обнаружено

            self.is_typing = False
    
  3. Создать Entry как общее

            self.my_msg = tk.StringVar()
            entry_field = tk.Entry(self, textvariable=self.my_msg)
            entry_field.grid(row=0, column=0)
    
  4. Привязать событие '<KeyRelease>' к экземпляру Entry, который для каждого события отпускания ключа вызывает функцию self.typing(...

            entry_field.bind('<KeyRelease>', self.typing)
    
  5. Создание Label и Button только для демонстрационных целей

            self.label = tk.Label(self)
            self.label.grid(row=1, column=0)
    
            btn = tk.Button(self, text='Send', command=self.send_msg)
            btn.grid(row=2, column=0)
    
  6. Сбросьте флажок .is_typing и очистите текст Label при отправке сообщения, только для демонстрации.

        def send_msg(self):
            self.is_typing = False
            self.label.config(text="")
    
  7. Функция def typing(..., которая вызывается при каждом событии отпускания ключа.
    Возврат без дальнейших действий, если установлен флаг .is_typing.
    Если флаг не установлен, это первый вызов:

    • Установить флаг
    • Выполните действие, для нее только установите текст Label на "is typing".

      def typing(self, *args):
          if self.is_typing:
              return
      
          self.is_typing = True
          self.label.config(text="is typing")
      
  8. Запустить демонстрационное приложение

    if __name__ == "__main__":
        App().mainloop()
    

Протестировано на Python: 3,5

...