Окно tkinter не отображается при наличии соединения с другим устройством

#python-3.x #sockets #tkinter #window

#python-3.x #сокеты #tkinter #окно

Вопрос:

  • Я хотел бы подключить 2 компьютера, чтобы создать своего рода мессенджер, но я хотел бы использовать tkinter , чтобы иметь окна, и использовать кнопки и другие виджеты для создания интерфейса.
  • Итак, у меня есть 2 программы, одна из которых является клиентом, а другая — сервером.
    • Для клиента это работает: отображается окно, и я могу отправить сообщение.
    • Для сервера окно не отображается.

клиентская программа:

 import socket
from tkinter import *

def envoyer_msg():
    s.send(msg.get().encode())

fenetre=Tk()
fenetre.geometry("{}x{} {} {}".format(200,200,200,200))

texte=Label(fenetre,text="CLIENT",font=25)
texte.pack()

msg=StringVar()
saisie=Entry(fenetre,textvariable=msg,font=25)
saisie.pack()

bouton_envoyer=Button(fenetre,text="Envoyer",font=25,command=envoyer_msg)
bouton_envoyer.pack()

s = socket.socket()
s.connect(('127.0.0.1',12345))
  

и здесь серверная программа :

 import socket
from tkinter import *

def envoyer_msg():
    c.send(msg.encode())

fenetre=Tk()
fenetre.geometry("{}x{} {} {}".format(200,200,200,200))

texte=Label(fenetre,text="SERVEUR",font=25)
texte.pack()

msg=StringVar()
saisie=Entry(fenetre,textvariable=msg,font=25)
saisie.pack()

bouton_envoyer=Button(fenetre,text="Envoyer",font=25,command=envoyer_msg)
bouton_envoyer.pack()

print("1")

s = socket.socket()
port = 12345
s.bind(('', port))
s.listen(5)
c, addr = s.accept()
print ("Socket Up and running with a connection from",addr)

print("2")

while True:
    rcvdData = c.recv(1024).decode()
    print ("S:",rcvdData)

    print("3")
  

Ответ №1:

Сначала вы должны вызвать mainloop() явно, даже если вы используете IDE, созданную с tkinter помощью Python IDLE. В противном случае графический интерфейс не будет отображаться при выполнении скрипта в терминале.


Графический интерфейс сервера не отображается, потому что while цикл блокирует mainloop() . Вам нужно поместить задачу обработки клиентского соединения в поток:

 # server code
import socket
import threading
from tkinter import *

def envoyer_msg():
    c.send(msg.get().encode())

fenetre=Tk()
fenetre.geometry("{}x{} {} {}".format(200,200,200,200))

texte=Label(fenetre,text="SERVEUR",font=25)
texte.pack()

msg=StringVar()
saisie=Entry(fenetre,textvariable=msg,font=25)
saisie.pack()

bouton_envoyer=Button(fenetre,text="Envoyer",font=25,command=envoyer_msg)
bouton_envoyer.pack()

def server_task():
    global c

    s = socket.socket()
    port = 12345
    s.bind(('', port))
    s.listen(5)

    while True:
        print('waiting connection ...')
        c, addr = s.accept()
        print ("Socket Up and running with a connection from", addr)

        while True:
            try:
                rcvdData = c.recv(1024).decode()
                print ("Client:", rcvdData)
            except ConnectionResetError:
                print('Client disconnected')
                break

# start the client connection handling thread
threading.Thread(target=server_task, daemon=True).start()
fenetre.mainloop()

  

То же самое относится и к стороне клиента:

 # client code
import socket
import threading
from tkinter import *

def envoyer_msg():
    s.send(msg.get().encode())

fenetre=Tk()
fenetre.geometry("{}x{} {} {}".format(200,200,400,200))

texte=Label(fenetre,text="CLIENT",font=25)
texte.pack()

msg=StringVar()
saisie=Entry(fenetre,textvariable=msg,font=25)
saisie.pack()

bouton_envoyer=Button(fenetre,text="Envoyer",font=25,command=envoyer_msg)
bouton_envoyer.pack()

def client_task():
    global s
    s = socket.socket()
    s.connect(('127.0.0.1',12345))
    while True:
        try:
            rcvdData = s.recv(1024).decode()
            print('Server:', rcvdData)
        except ConnectionResetError:
            print('Server disconnected')
            fenetre.destroy()

# start the server connection thread
threading.Thread(target=client_task, daemon=True).start()
fenetre.mainloop()
  

Поскольку вы хотите использовать графический интерфейс, лучше использовать Text виджет для хранения одноранговых сообщений вместо использования print() .