Реализация интрефейса

Анастасия

Новичок
Пользователь
Окт 4, 2020
3
0
1
Здравствуйте, я реализую интерфейс, который после кнопки пуск, ожидает сообщения от другого программного модуля(передача по UDP протоколу) при этом пока он ждет сообщение, он, естественно не работает, а ждет только следующего сообщения, то есть нажать кнопку стоп я не могу, как и передвинуть окно. Вот код, подскажите как можно ожидать сообщения, (как только приходят, сразу выводить) и при этом интерфейс продолжает работать.
Python:
Python
from tkinter import *
from tkinter.ttk import *
import time

from tkinter import messagebox as mb
import socket
import struct

INTERFACE = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
INTERFACE.sendto(bytes("INTERFACE", 'utf-8'), ('127.0.0.1', 25000))
time.sleep(1)

class interface(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent
        self.param_h=0
        self.param_l=0
        self.param_b=0
        self.rab=True
        self.initUI()


    def initUI(self):
        self.parent.title("ROBOT 2.0")
        self.pack(fill=BOTH, expand=True)

        frame = Frame(self)
        frame.pack(fill=X, side=TOP, expand=True)

        lbl2 = Label(frame, text="Координаты найденных объектов", width=31)
        lbl2.pack(side=TOP, padx=5, pady=5)

        frame1 = Frame(self)
        frame1.pack(fill=X, side=TOP, expand=True)

        self.tex=Text(frame1, bg='white')
        self.tex.pack(fill=Y, side=LEFT, pady=5, padx=5, expand=True)

        frame2 = Frame(self)
        frame2.pack(fill=X, side=TOP, expand=True)

        lbl5 = Label(frame2, text="Ширина поля:", width=13)
        lbl5.pack(side=LEFT)

        self.entry2 = Entry(frame2)
        self.entry2.pack(side=LEFT, padx=5, pady=10)

        lbl6 = Label(frame2, text="Высота:", width=8)
        lbl6.pack(side=LEFT)

        self.entry3 = Entry(frame2)
        self.entry3.pack(side=LEFT, padx=5, pady=10)

        frame3 = Frame(self)
        frame3.pack(fill=X, side=TOP, expand=True)

        lbl5 = Label(frame3, text="   Длина поля:", width=13)
        lbl5.pack(side=LEFT)

        self.entry5 = Entry(frame3)
        self.entry5.pack(side=LEFT, padx=5, pady=10)

        self.but1 = Button(frame3, text="Пуск", command=self.clickPusk)
        self.but1.pack(side=RIGHT, padx=5, pady=10)

        self.but2 = Button(frame3, text="Cтоп", command=self.clickStop)
        self.but2.pack(side=RIGHT, padx=5, pady=10)

        self.but3 = Button(frame3, text="Принять", command=self.clickGet)
        self.but3.pack(side=RIGHT, padx=5, pady=10)


    def is_digit(self, str):
        if str.isdigit():
            return True
        else:
            try:
                float(str)
                return True
            except ValueError:
                return False

    def clickPusk(self):
        param = struct.pack("3f", self.param_h, self.param_b, self.param_l)
        INTERFACE.sendto(param, ('127.0.0.1', 25000))
        while(self.rab):
            msg, addr=INTERFACE.recvfrom(32)
            x, y=struct.unpack("2f", msg)
            print(x, y)
            self.tex.insert(1.0, f'X:{x}; Y:{y} \n')
            self.tex.update()


    def clickStop(self):
        pass

    def clickGet(self):
        if self.is_digit(self.entry2.get())==False or self.is_digit(self.entry3.get())==False or self.is_digit(self.entry5.get())==False:
            mb.showerror(title="Ошибка", message="Значения введены некорректно")
        else:

            self.param_b=float(self.entry2.get())
            self.param_h=float(self.entry3.get())
            self.param_l=float(self.entry5.get())



root = Tk()
root.geometry("500x540+300+100")
app = interface(root)
root.mainloop()
 

stud_55

Модератор
Команда форума
Модератор
Апр 3, 2020
1 522
672
113
а как после того, как он пришел в отдельный поток, вывести его в интерфейсе? вот, например, класс с потоком. Я не представляю как организовать так, чтобы оно вывелось в интерфейсе
Можно вывести также как и из основного потока, если отдельный поток запускать просто в методе основного класса (а не отдельным классом). То есть по нажатию на кнопку вызывать метод запускающий поток с методом, который ожидает сообщение.
Python:
self.but1 = Button(frame3, text="Пуск", command=self.startClickPusk)

def clickPusk(self):
    param = struct.pack("3f", self.param_h, self.param_b, self.param_l)
    INTERFACE.sendto(param, ('127.0.0.1', 25000))
    #while(self.rab):
    msg, addr=INTERFACE.recvfrom(32)
    x, y=struct.unpack("2f", msg)
    print(x, y)
    self.tex.insert(1.0, f'X:{x}; Y:{y} \n')
    self.tex.update()
           
def startClickPusk(self):
    threading.Thread(target=self.clickPusk).start()
 
  • Мне нравится
Реакции: Анастасия

stud_55

Модератор
Команда форума
Модератор
Апр 3, 2020
1 522
672
113
как можно ожидать сообщения, (как только приходят, сразу выводить) и при этом интерфейс продолжает работать.
Можно ожидать сообщение в отдельном потоке.
 

Анастасия

Новичок
Пользователь
Окт 4, 2020
3
0
1
Можно ожидать сообщение в отдельном потоке.
а как после того, как он пришел в отдельный поток, вывести его в интерфейсе? вот, например, класс с потоком. Я не представляю как организовать так, чтобы оно вывелось в интерфейсе
Python:
class message(Thread):

    def run(self):
        msg, addr = INTERFACE.recvfrom(32)
        x, y = struct.unpack("2f", msg)
 

Анастасия

Новичок
Пользователь
Окт 4, 2020
3
0
1
Можно вывести также как и из основного потока, если отдельный поток запускать просто в методе основного класса (а не отдельным классом). То есть по нажатию на кнопку вызывать метод запускающий поток с методом, который ожидает сообщение.
Python:
self.but1 = Button(frame3, text="Пуск", command=self.startClickPusk)

def clickPusk(self):
    param = struct.pack("3f", self.param_h, self.param_b, self.param_l)
    INTERFACE.sendto(param, ('127.0.0.1', 25000))
    #while(self.rab):
    msg, addr=INTERFACE.recvfrom(32)
    x, y=struct.unpack("2f", msg)
    print(x, y)
    self.tex.insert(1.0, f'X:{x}; Y:{y} \n')
    self.tex.update()
          
def startClickPusk(self):
    threading.Thread(target=self.clickPusk).start()
Большое вам спасибо!
 

Форум IT Специалистов