С Новым годом! Форум программистов, компьютерный форум, киберфорум
Python: GUI, графика
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/15: Рейтинг темы: голосов - 15, средняя оценка - 4.80
5 / 0 / 0
Регистрация: 20.09.2019
Сообщений: 26

Зависают виджеты созданные библиотекой PyQt5 при использовании многопоточной библиотеки QThread

04.08.2021, 21:10. Показов 3164. Ответов 5
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Уважаемые знатоки. Проблема следующая.
Написал простенькую программу которая принимает данные извне. В данную программу в любой момент времени приходят данные (целочисленные значения типа Int).
В моём коде для наглядной иллюстрации приход данных имитируется функцией (make_data) Main класса. Данная функция запускается вторым потоком из класса DataMaker путем нажатия на кнопку Start.
После нажатия кнопки в программу раз в 1 секунду начинает приходить список из четырёх числе (10, 20, 11, 21).
Проходимся по данному списку через цикл for и определяем переменные index и key. Index это первая цифра числа, а key это вторая цифра.
Если вторая (key) цифра равна нулю, то изменяем цвет лейбла (mark_0 или mark_1) на зеленый в зависимости от того какая (index) цифра была первой (1 или 2) при помощи метода (activate_mark)
Если же вторая (key) цифра была 1, то добавляем к значению списка self.result_list[index] единицу и при помощи метода insetr_in_winget отражаем значение из списка в одном из (point_0 или point_1). Далее также зажигаем зеленом нужный из (mark_0 или mark_1) при помощи метода (activate_mark).
Далее создается новый поток при помощи метода (deactivate_mark) и снова меняет цвет (mark_0 или mark_1) на красный. Тем самым программа показывает исправный прием данных.
Также кнопками Clear можно обнулить значения в result_list, а кнопкой Stop остановить прием данных.

Суть проблемы следующая. Если дать программе немного поработать, то визуализация зависнет т.е. значения в (point_0 или point_1) и (mark_0 или mark_1) перестанут обновляться. Причем в консоль данные при помощи функции print выводиться не перестанут, а значит второй поток исправно работает и значения приходят При нажатии на любую их кнопок Clear в одной графе все обнуляется, а во второй значения начисляются сразу за все пропущенное время. Т.е. если программа зависля на 100 очках в виджетах point и простояла 10 секунд. Я нажимаю на кнопку Clear и в одной графе все очищается, а во вторую начисляются те 10 секунд простоя, что программа не работала.

Помогите, никак не могу побороть данную проблему. Код Xml и самой программы прилагается.
main.py:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import time, sys
from threading import Thread
from PyQt5 import QtWidgets, uic
from PyQt5.QtCore import QThread
 
 
class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = uic.loadUi('gui.ui')
        self.point_tuple = (self.ui.point_0, self.ui.point_1)
        self.mark_tuple = (self.ui.mark_0, self.ui.mark_1)
        self.result_list = [0, 0]
 
        self.subFlow = DataMaker(self.make_data)
 
        self.ui.startBtn.clicked.connect(lambda: self.starter())
        self.ui.stopBtn.clicked.connect(lambda: self.stopper())
        self.ui.clearBtn_0.clicked.connect(lambda: self.clear_point(0))
        self.ui.clearBtn_1.clicked.connect(lambda: self.clear_point(1))
 
    def starter(self):
        self.subFlow.start()
 
    def stopper(self):
        self.subFlow.terminate()
 
    def clear_point(self, index):
        self.result_list[index] = 0
        self.insert_in_widget(index)
 
    def make_data(self):
        data = [10, 20, 11, 21]
        print(data)
        for value in data:
            index = (value // 10) - 1
            key = value % 10
            if key == 1:
                self.result_list[index] += 1
                self.insert_in_widget(index)
            self.activate_mark(index)
            time.sleep(1)
 
    def insert_in_widget(self, index):
        self.point_tuple[index].setText(str(self.result_list[index]))
 
    def activate_mark(self, index):
        self.mark_tuple[index].setStyleSheet('QLabel {background-color: green;}')
        th = Thread(target=self.deactivate_mark, args=(index, ))
        th.start()
 
    def deactivate_mark(self, index):
        time.sleep(0.5)
        self.mark_tuple[index].setStyleSheet('QLabel {background-color: red;}')
 
class DataMaker(QThread):
    def __init__(self, func, parent=None):
        super(DataMaker, self).__init__(parent)
        self.delay = 1
        self.func = func
 
    def run(self):
        while True:
            self.func()
            time.sleep(self.delay)
 
 
if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    open = MainWindow()
    open.ui.show()
    app.exec()
gui.ui:

XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>273</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Gui</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QWidget" name="layoutWidget">
    <property name="geometry">
     <rect>
      <x>100</x>
      <y>70</y>
      <width>611</width>
      <height>51</height>
     </rect>
    </property>
    <layout class="QHBoxLayout" name="horizontalLayout_2">
     <item>
      <widget class="QLabel" name="point_1">
       <property name="styleSheet">
        <string notr="true">font: 24pt &quot;Ubuntu&quot;;</string>
       </property>
       <property name="frameShape">
        <enum>QFrame::Box</enum>
       </property>
       <property name="text">
        <string>0</string>
       </property>
       <property name="alignment">
        <set>Qt::AlignCenter</set>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QLabel" name="mark_1">
       <property name="styleSheet">
        <string notr="true">background-color: rgb(239, 41, 41);</string>
       </property>
       <property name="frameShape">
        <enum>QFrame::Box</enum>
       </property>
       <property name="text">
        <string/>
       </property>
       <property name="alignment">
        <set>Qt::AlignCenter</set>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QPushButton" name="clearBtn_1">
       <property name="styleSheet">
        <string notr="true">font: 24pt &quot;Ubuntu&quot;;</string>
       </property>
       <property name="text">
        <string>Clear</string>
       </property>
      </widget>
     </item>
    </layout>
   </widget>
   <widget class="QPushButton" name="startBtn">
    <property name="geometry">
     <rect>
      <x>100</x>
      <y>170</y>
      <width>199</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 24pt &quot;Ubuntu&quot;;</string>
    </property>
    <property name="text">
     <string>Start</string>
    </property>
   </widget>
   <widget class="QPushButton" name="stopBtn">
    <property name="geometry">
     <rect>
      <x>510</x>
      <y>170</y>
      <width>199</width>
      <height>41</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 24pt &quot;Ubuntu&quot;;</string>
    </property>
    <property name="text">
     <string>Stop</string>
    </property>
   </widget>
   <widget class="QWidget" name="">
    <property name="geometry">
     <rect>
      <x>100</x>
      <y>10</y>
      <width>611</width>
      <height>51</height>
     </rect>
    </property>
    <layout class="QHBoxLayout" name="horizontalLayout">
     <item>
      <widget class="QLabel" name="point_0">
       <property name="styleSheet">
        <string notr="true">font: 24pt &quot;Ubuntu&quot;;</string>
       </property>
       <property name="frameShape">
        <enum>QFrame::Box</enum>
       </property>
       <property name="text">
        <string>0</string>
       </property>
       <property name="alignment">
        <set>Qt::AlignCenter</set>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QLabel" name="mark_0">
       <property name="styleSheet">
        <string notr="true">background-color: rgb(239, 41, 41);</string>
       </property>
       <property name="frameShape">
        <enum>QFrame::Box</enum>
       </property>
       <property name="text">
        <string/>
       </property>
       <property name="alignment">
        <set>Qt::AlignCenter</set>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QPushButton" name="clearBtn_0">
       <property name="styleSheet">
        <string notr="true">font: 24pt &quot;Ubuntu&quot;;</string>
       </property>
       <property name="text">
        <string>Clear</string>
       </property>
      </widget>
     </item>
    </layout>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>22</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
04.08.2021, 21:10
Ответы с готовыми решениями:

QT: лаги программы при использовании QVector<QThread>
Создал тестовую программу, где реализовал шаблон потоков QVector&lt;VlThread*&gt;. vlthread.h: #ifndef VLTHREAD_H #define VLTHREAD_H ...

PyQt5 QThread
Здравствуйте форумчане. Собственно решил побаловаться с потоками в PyQt5. Придумал небольшую учебную задачку для себя по данной теме. ...

Ошибка при установке библиотеки pyqt5-tools
Добрый вечер, возникла проблема с инсталляцией библиотеки pyqt5-tools, которая нужна мне для перевода файлов формата .ui в .py....

5
290 / 205 / 68
Регистрация: 18.09.2019
Сообщений: 407
Записей в блоге: 58
04.08.2021, 22:51
Как интересно! Вот буквально позавчера была тема Отображение главного окна программы | QThread просто близнец поднятой Вами. И Вас тоже не остановило прямое указание в документации Qt, что GUI исполняется исключительно в главном потоке, иначе называемом GUI-потоком. Фантастика!

Добавлено через 3 минуты
И вот эта тоже позавчера была Не до конца закрывается программа с бесконечным циклом while
Как-то кучно пошло.

Добавлено через 19 минут
И тут https://doc.qt.io/qt-5/threads-technologies.html тоже вроде бы ясно расписаны пределы применимости разных вариантов использования QThread и способ получения данных от QThread.
0
290 / 205 / 68
Регистрация: 18.09.2019
Сообщений: 407
Записей в блоге: 58
05.08.2021, 09:20
А самое печальное, что тут даже обсуждать-то нечего - Ваше решение просто неприменимо.
0
 Аватар для kapbepucm
1566 / 739 / 321
Регистрация: 02.05.2020
Сообщений: 1,654
06.08.2021, 10:39
Лучший ответ Сообщение было отмечено Удалов Павел как решение

Решение

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import sys
from PyQt5 import QtWidgets, uic
from PyQt5.QtCore import QThread, pyqtSignal, QTimer
 
class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = uic.loadUi('gui.ui')
        self.point_tuple = (self.ui.point_0, self.ui.point_1)
        self.mark_tuple = (self.ui.mark_0, self.ui.mark_1)
        self.result_list = [0, 0]
 
        self.subFlow = DataMaker()
 
        self.ui.startBtn.clicked.connect(self.starter)
        self.ui.stopBtn.clicked.connect(self.stopper)
        self.ui.clearBtn_0.clicked.connect(lambda: self.clear_point(0))
        self.ui.clearBtn_1.clicked.connect(lambda: self.clear_point(1))
        self.subFlow.insert.connect(self.insert_in_widget)
        self.subFlow.activate.connect(self.activate_mark)
 
    def starter(self):
        self.subFlow.start()
 
    def stopper(self):
        self.subFlow.terminate()
 
    def clear_point(self, index):
        self.result_list[index] = -1
        self.insert_in_widget(index)
 
    def insert_in_widget(self, index):
        self.result_list[index] += 1
        self.point_tuple[index].setText(str(self.result_list[index]))
 
    def activate_mark(self, index):
        self.mark_tuple[index].setStyleSheet('QLabel {background-color: green;}')
        QTimer.singleShot(500, lambda i=index: self.deactivate_mark(i))
 
    def deactivate_mark(self, index):
        self.mark_tuple[index].setStyleSheet('QLabel {background-color: red;}')
 
class DataMaker(QThread):
    insert = pyqtSignal(int)
    activate = pyqtSignal(int)
    def __init__(self, parent=None):
        super(DataMaker, self).__init__(parent)
        self.delay = 1
 
    def run(self):
        while True:
            self.make_data()
            QThread.sleep(self.delay)
 
    def make_data(self):
        data = [10, 20, 11, 21]
        print(data)
        for value in data:
            index = (value // 10) - 1
            key = value % 10
            if key == 1:
              self.insert.emit(index)
            self.activate.emit(index)
            QThread.sleep(1)
 
if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    open = MainWindow()
    open.ui.show()
    app.exec_()
3
290 / 205 / 68
Регистрация: 18.09.2019
Сообщений: 407
Записей в блоге: 58
06.08.2021, 12:20
Спасибо, kapbepucm! Умыл Во как можно! И даже terninate() без матов. Век живи, век учись...
0
5 / 0 / 0
Регистрация: 20.09.2019
Сообщений: 26
08.08.2021, 13:28  [ТС]
Спасибо большое, kapbepucm. Решение крылось в сигналах и слотах.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.08.2021, 13:28
Помогаю со студенческими работами здесь

Добрый день, возникла проблема: при попытке импортировать из библиотеки PyQt5!
Добрый день, возникла проблема: при попытке импортировать из библиотеки PyQt5, импортируемые объекты выделяются как ошибки =&gt; при...

Проблема с библиотекой PyQT5
Здравствуйте, не устанавливается библиотека PyQT5

Ошибка при использовании библиотеки
Traceback (most recent call last): File &quot;*путь файла*&quot;, line 1, in &lt;module&gt; from PIL import Image ModuleNotFoundError: No...

Почему при нажатии кнопки при использовании библиотеки createjs функция запускается несколько раз?
Здравствуйте, на creatjs делаю переключения между уровнями. Когда нажимаю на кнопку то уровень очищается и появляются новые объекты, щелкаю...

Ошибка при использовании библиотеки getch
У меня ошибка при использовании библиотеки getch Ввожу: import getch print(getch.getch()) Вывод:


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 07.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и источниками (напряжения, ЭДС и тока). Найти токи и напряжения во всех элементах. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru