Использование виджета входа в качестве стандартного ввода в программе асинхронного чата - PullRequest
0 голосов
/ 17 октября 2019

Я разработал программу асинхронного консольного чата. Тогда я решил разработать программу асинхронного чата с графическим интерфейсом.

На сервере работает консоль. Сервер управляет процессом связи между клиентами.

У меня есть две клиентские программы. Один из них - консоль, другой - программа с графическим интерфейсом. Когда консольная программа отправляет сообщения, они печатаются в виджете «Текст» программы с графическим интерфейсом.

Однако, когда я отправлял сообщения в программе с графическим интерфейсом, сообщения отображаются в окне консоли другой клиентской программы только после того, как клиент, работающий в консоли, записывает сообщения другому клиенту.

Функция write консольной программы выглядит следующим образом:

    async def write(self, writer):
        t = threading.Thread(
            target=lambda: writer.write(
                f"{self.nick}: {sys.stdin.readline()}".encode()
            )
        )
        t.daemon = True
        t.start()
        t.join(0.1)
        await writer.drain()

Эта функция выполняет задачу так, как я хочу.

Функция write программы с графическим интерфейсом выглядит следующим образом:

    async def write(self, writer):
        if self.data:
            data = self.data
            self.data = ""
            t = threading.Thread(
                target=lambda: writer.write(
                    f"{self.nick}: {data}\n".encode()
                )
            )
            t.daemon = True
            t.start()
            t.join(0.1)
            await writer.drain()
        else:
            await asyncio.sleep(0.1)

И эта функция работает не так, как я хочу.

self.data - это переменная, которая получает текст в поле tk.Entry. Она была определена в функции __init__ класса.

        self.entry = tk.Entry(
            master=self.bottom_frame,
            width=50
        )
        self.entry.pack()
        self.entry.bind("<Return>", lambda event: self.callback())

        self.data = ""

Функция self.callback() выглядит следующим образом:

    def callback(self):
        self.data = self.entry.get()
        self.entry.delete("0", "end")
        self.update()
        self.update_idletasks()

Итак, я пытался сделать здесь:когда я нажимаю <Return>, содержимое self.entry передается в переменную self.data. Согласно функции self.write, существует условие типа if self.data, которое используется для отправки сообщений, когда self.data не является пустым значением. Если условие не выполняется, я решил подождать эту функцию с помощью await asyncio.sleep(0.1).

. Как я уже сказал, программа gui считывает сообщения без проблем, однако не может отправлять сообщения асинхронно клиенту консоли. программа. Консольной клиентской программе необходимо отправить новое сообщение, чтобы увидеть, что сообщения поступают от клиента графического интерфейса.

Что нужно сделать для асинхронной отправки сообщений в приложении с графическим интерфейсом?

Ниже приведены полные коды:

Сервер: https://www.dropbox.com/s/q04w3et3huegrao/server.py

Клиент1: https://www.dropbox.com/s/h7seeuoylvnpezq/client1.py

Клиент2: https://www.dropbox.com/s/uz4zn3vjfcc3mrj/client2.py

1 Ответ

0 голосов
/ 17 октября 2019

Пробем решён. Асинхронная функция write изменяется следующим образом:

    async def write(self, writer):

        def inner():
            data = self.entry.get()
            self.entry.delete("0", "end")
            self.entry.unbind_all("<Return>")
            t = threading.Thread(
                target=lambda: writer.write(
                    f"{self.nick}: {data}\n".encode()
                )
            )
            t.daemon = True
            t.start()
            t.join(0.1)

        self.entry.bind("<Return>", lambda event: inner())
        await writer.drain()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...