Вызвать поток с петлей из графического интерфейса без заморозки графического интерфейса - PullRequest
0 голосов
/ 24 октября 2019

Я хочу запустить измерительную программу, которая получает измерения от двух разных устройств в течение одного и того же периода. Я хочу начать и остановить измерение в небольшом графическом интерфейсе. Поскольку мне нужен цикл while для измерения, построения и сохранения одного из измерений и запуска его до тех пор, пока я не прерву его кнопкой остановки, я подумал, что мне нужно вызвать его как другой поток, чтобы не замораживать графический интерфейс пользователя и иметь возможность использоватькнопка остановкиТакже я подумал, что не стоит использовать .join (), чтобы не заморозить графический интерфейс. Но почему-то мой графический интерфейс все еще зависает, и я не могу использовать кнопку остановки. Я уже читал подобные вопросы на форумах, но не могу понять, что я делаю неправильно. На самом деле это мой первый проект с использованием потоков, поэтому я не разбираюсь с опциями и событиями, но я также не вижу, как они мне помогут.

Итак, у меня есть класс для связи с моим arduino, один для связи с saleae (второе устройство) и один класс data_treatment для построения и сохранения данных из arduino.

Так что в моем основном у меня есть небольшой графический интерфейс с кнопкой запуска и остановки. Когда я нажимаю кнопку «Пуск», я хотел бы запустить измерение saleae (оно удобно выполняется в собственной программе) и вызвать функцию записи моего класса ardunio. Эта функция имеет цикл while, который считывает значения и передает их функции data_treatment. Когда я нажимаю start, он запускает измерение saleae и измерение arduino, и все работает как запланировано, но я не могу нажать stop, потому что кажется, что графический интерфейс ожидает другую угрозу, которая не заканчивается, пока я не нажму stop.

Итак, моя основная функция (cambine_func) - это просто функция, позволяющая вызывать несколько функций с помощью кнопки), а ниже - класс arduino:

if __name__ == '__main__':
window = gui.Window("Measurement")

start_button = window.add_button("Start")
start_button.pack(pady = 20)
gui.on("btnPress", start_button, lambda: combine_funcs(saleae.start_measurement(),
                                                       threading.Thread(target = arduino.record_values(300)).start()))

stop_button = window.add_button("Stopp")
stop_button.pack(pady = 20)
gui.on("btnPress", stop_button, lambda: combine_funcs(saleae.end_measurement(),
                                                      saleae.save_data(),
                                                      arduino.close_port(),
                                                      window.destroy()))

window.start()




import time

class Arduino_communication:
"""
reads what comes in from Arduino and transformes it into single values
"""
def __init__(self, arduino, data_treatment):
    self.arduino = arduino
    self.data_treatment = data_treatment
    self.interrupted = False

def record_values(self, measurement_period):
    """
    reads values from the Arduino and converts it into single values,
    counts faulty lines received from Arduino
    :return: array of 6 columns (roll, pitch, yaw, x-position, y-position, z-position)
    """
    faulty_values = 0
    data = [0, 0, 0, 0, 0, 0]
    start_time = float(time.time())
    time_vector = []

    while self.interrupted == False:

        self.arduino.flushInput()               # delete what's in buffer
        self.arduino.readline()                 # read a byte string and throw away (deleting buffer may lead to uncomplete line)
        b = self.arduino.readline()             # read next line
        time_vector.append(float(time.time())-start_time)

        try:
            string_n = b.decode()               # decode byte string into Unicode
        except UnicodeDecodeError:              # Arduino sometimes sends faulty lines
            faulty_values += 1
        string = string_n.rstrip()              # remove \n and \r
        single_strings = string.split('/')
        try:
            data = [float(j) for j in single_strings]  # convert string to float
        except (ValueError, UnicodeDecodeError): # Arduino sometimes sends faulty lines
            faulty_values += 1

        self.data_treatment.plot_new_data_line(time_vector[-1], data)
        self.data_treatment.write_to_csv(time_vector[-1], data)

    print('Es gab ', faulty_values, ' fehlerhafte Übertragungen.')
    self.data_treatment.finish_plotting()

def close_port(self):
    """
    stops measurement and closes arduino port
    """
    self.interrupted = True
    self.arduino.close()

Ответы [ 2 ]

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

Я не мог найти решение, которое, как я думал, сработало, но я нашел этот ответ , который я мог бы адаптировать к своему проекту, и теперь он работает так, как я хотел.

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

У вас есть:

threading.Thread(target = arduino.record_values(300)).start()

Это вызывает метод, а затем запускает поток с результатом в качестве цели.

Где вы хотите:

threading.Thread(target=arduino.record_values, args=[300]).start()

Это запускает поток с целью arduino.record_values и аргументом 300.

Возможно, вы захотите придерживаться этогоПоток, чтобы можно было предотвратить запуск кнопки другого потока записи во время записи потока.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...