Форум программистов, компьютерный форум, киберфорум
Python: GUI, графика
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.85/34: Рейтинг темы: голосов - 34, средняя оценка - 4.85
0 / 0 / 0
Регистрация: 03.11.2020
Сообщений: 4
PyQt5

Зависает графический интерфейс при выполнении задачи

03.11.2020, 00:56. Показов 7591. Ответов 9

Студворк — интернет-сервис помощи студентам
Доброго времени суток. Сразу извиняюсь за вопрос, уверен, для специалистов ответ очевиден, но я пишу свою первую программу с GUI (надоело скрипты через консоль запускать) И столкнулся с проблемой: моя программа должна будет получать список ip, а затем подключаться к каждому и по FTP закидывать туда файл прошивки и в режиме реального времени выводить отчет о выполнении операции. НО! Пока она подключается, заливает файл, переподключается к следующему объекту, само окно висит. В итоге итог работы я узнаю только когда всё кончилось, и интерфейс отвисает.

Я понимаю, что тут нужно использовать многопоточность, но я не понимаю, ЧТО ИМЕННО Я ДЕЛАЮ НЕ ПРАВИЛЬНО
Мучаюсь уже несколько дней, посмотрел кучу примеров с потоками Python, но ни один из них не помог.

Накидал максимально простую программку, чтобы на ней тестировать. Она по нажатию кнопки СТАРТ должна просто и в консоль и в окно 8 раз с перерывом в секунду скинуть время.

Итог: я нажимаю "СТАРТ", в консоль начинает выводиться время, окно зависает, проходит 8 секунд, окно отвисает и в нем появляются все значения.

Я пробовал создавать другой класс, наследуя его от threading.Thread и стартовать его в функции внутри главного окна - не помогло, сейчас я завис на этом варианте, но результат тот же.

Я мозг сломал, помогите, пожалуйста.

Вот файл, сгенерированный QT Designer
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
from PyQt5 import QtCore, QtGui, QtWidgets
 
 
class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(414, 508)
        self.verticalLayout_2 = QtWidgets.QVBoxLayout(Form)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.output = QtWidgets.QPlainTextEdit(Form)
        self.output.setObjectName("output")
        self.verticalLayout.addWidget(self.output)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.start = QtWidgets.QPushButton(Form)
        self.start.setObjectName("start")
        self.horizontalLayout.addWidget(self.start)
        self.stop = QtWidgets.QPushButton(Form)
        self.stop.setObjectName("stop")
        self.horizontalLayout.addWidget(self.stop)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.verticalLayout_2.addLayout(self.verticalLayout)
 
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)
 
    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.start.setText(_translate("Form", "START"))
        self.stop.setText(_translate("Form", "STOP"))
Вот, то, что делаю я...
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
import threading
from PyQt5 import QtWidgets
import sys
import time
from ui import Ui_Form
 
isTrue = True
 
# Create app
app = QtWidgets.QApplication(sys.argv)
 
# init
Form = QtWidgets.QWidget()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
 
 
# Logic
def start():
    global isTrue
    isTrue = True
    print(isTrue)
    for i in range(8):
        ti = str(time.time())
        print(ti)
        threading.Thread(target=ui.output.appendPlainText(ti)).start()
        # ui.output.appendPlainText(ti)
        time.sleep(1)
 
 
def stop():
    global isTrue
    isTrue = False
    print(isTrue)
 
 
ui.start.clicked.connect(start)
# ui.start.clicked.connect(threading.Thread(target=start).start())
ui.stop.clicked.connect(stop)
 
# Main loop
sys.exit(app.exec_())
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
03.11.2020, 00:56
Ответы с готовыми решениями:

Зависает потом отвисает интерфейс при выполнении цикла while
Вопрос к знатокам. Хочу организовать отслеживание прогресса выполнения копирования файлов, прогрессбар или отображение процента. Всё это...

Tkinter. Зависает графический интерфейс
Здравствуйте! Написал такой код: # -*- coding: utf-8 -*- from Tkinter import * import urllib, ttk, tkMessageBox from threading...

Зависает интерфейс при выполнении отдельного потока
Как сделать так чтобы при выполнении потока не зависалось GUI? Вот небольшой код: using System; using...

9
0 / 0 / 0
Регистрация: 03.11.2020
Сообщений: 4
03.11.2020, 13:17  [ТС]
Посмотрел похожие темы от Programming - решение нашел, правда, я не понимаю, почему это не работает
Python
1
2
3
4
5
6
7
8
def start():
    for i in range(8):
        ti = str(time.time())
        print(ti)
        threading.Thread(target=ui.output.appendPlainText(ti)).start()
        time.sleep(1)
 
ui.start.clicked.connect(start)
а это работает

Python
1
2
3
4
5
6
7
8
9
10
11
12
def start():
    for i in range(8):
        ti = str(time.time())
        print(ti)
        ui.output.appendPlainText(ti)
        time.sleep(1)
 
def starter():
    th = threading.Thread(target=start)
    th.start()
 
ui.start.clicked.connect(starter)
Может кто-то объяснить? в моем понимании - одно и то же действие, но в первом случае программа зависает, а во втором - нет...
0
 Аватар для kapbepucm
1566 / 739 / 321
Регистрация: 02.05.2020
Сообщений: 1,654
03.11.2020, 14:45
Цитата Сообщение от Drackar Посмотреть сообщение
Может кто-то объяснить?
в первом случае: time.sleep(1) выполняется в основном потоке, который нельзя нагружать, поэтому записает GUI
в втором случае это вынесено в отдельный поток
0
13 / 10 / 5
Регистрация: 11.10.2019
Сообщений: 290
03.11.2020, 15:40
Drackar, В такой простой программе как у вас,потоки я думаю нахрен не нужны. Не смотрел код,но смысл понятен,я сам мучался с такими, и с потоками у меня до сих пор путаница.
Идею понял,когда что-то делается нужно окно с результатами типа прогресс бара или счетчика.То есть у вас окно в сером цвете или в прозрачном то есть завис пока выполняется что-то.


Если есть внутри кода какой нибудь цикл загрузки со счетчиком,то это хорошая идея как избавиться от потоков.
Да даже если цикла нет,то можно просто текст меняющийся сделать в разных местах

Вот как можно сделать:
1)вам нужно окошко в котором будет сообщаловка о результате в режиме реального времени
например у меня
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
#Инфо сообщение. Типа прогресс бара
def SAY( txt0 ):
 
    font_medium = 'font:24px;font-weight:bold;'
    bg_txt = 'background:#008B8B;color:#FFF;'
    
    info_dlg = QtWidgets.QDialog()
    info_dlg.setWindowTitle("Информация")
    info_dlg.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.WindowStaysOnTopHint)
    info_dlg.resize(400,100)
    lab_txt = QtWidgets.QLabel( txt0, info_dlg )
    lab_txt.setGeometry(0,20,400,60)
    lab_txt.setAlignment(QtCore.Qt.AlignCenter)
    info_dlg.setStyleSheet( font_medium + bg_txt )
    info_dlg.show()
    
    QtWidgets.qApp.processEvents()   <==это то что, нужно запускает цикл обработки,чтобы окно не зависло.
 
    return info_dlg, lab_txt
 
 
#а в самой программе перед выполнением чего то запустить это окно
#Инфо окно    
info_dlg, lab_txt = SAY( 'Идет загрузка с фтп...' )
 
А в цикле где идет процесс чего то.например счетчик если есть
#Меняем текст в инфо окне
lab_txt.setText( 'Данные обновлены...' ) <==меняется текст или счетчик добавьте,что угодно чтобы следить за процессом
QtWidgets.qApp.processEvents()
 
 
Если еще цикл есть то еще пишем,сколько угодно можно менять текст
#Меняем текст в инфо окне
lab_txt.setText( 'другой текст...' ) <==меняется текст или счетчик добавьте,что угодно чтобы следить за процессом
QtWidgets.qApp.processEvents()
 
 
И после выполнения закрываем
info_dlg.close()                #Закрываем инфо окно
0
Модератор
Эксперт Python
 Аватар для Fudthhh
2695 / 1601 / 513
Регистрация: 21.02.2017
Сообщений: 4,210
Записей в блоге: 1
05.11.2020, 10:17
Сергей225, любая долгая работа должна выполняться в потоках.

Хочешь писать GUI? Люби и потоки применять.

Добавлено через 2 минуты
Drackar, кстати в Qt есть собственные потоки, QtCore.QThread.

Сразу реализованы сигналы запуска и окончания потоков.
1
13 / 10 / 5
Регистрация: 11.10.2019
Сообщений: 290
05.11.2020, 10:46
DmFat, Я согласен с вами. Если сложный какой-то процесс то лучше потоки применить. А тут просто выгрузка на фтп. У меня в своей пг тоже есть выгрузка на фтп и загрузка с фтп,но потоки не применяю,все прекрасно и шустро и без него,с окошком о результатах о котором описывал. Когда есть несколько окон в котором параллельно что-то делается то точно нужны потоки. А то получается будет куча потоков,для параллельных процессов и еще для дебильного окошка с результатом пфф,так себе затея. Так что считаю лучшим для окошко то что описал,а остальное в потоки пихнуть если есть какие то дополнительные процессы.
0
0 / 0 / 0
Регистрация: 03.11.2020
Сообщений: 4
05.11.2020, 13:01  [ТС]
DmFat, Спасибо, посмотрю по ним инфу. А там есть возможность ставить его на паузу, а потом возобновлять с того же места? Скажем, у меня есть пул ip-адресов, и с каждым нужно произвести какое-то действие, и я хочу иметь возможность в процессе приостановить выполнение действия, а потом запустить с того же места?

Сергей225, там не только ftp будет, но и получение данных с ккт, смена ip адреса и прочее... загрузка по ftp просто самый долгий из этих процессов, поэтому я его указал. И, да, возможно, можно было бы написать это без потоков, я хз, но у меня ровно нулевой опыт написания программ. До этого были лишь простенькие скрипты на питоне или java и чуть-чуть VueJs. У меня очень мало опыта, и в таких условиях я предпочту идти проторенной дорожкой, а не изголяться, ища обходные пути...
0
13 / 10 / 5
Регистрация: 11.10.2019
Сообщений: 290
05.11.2020, 13:17
Drackar, Ну вот для простого и попробуйте мой пример,чтобы посмотреть заработало ли как вам надо или нет. А на счет паузы не знаю,может где остановились записать в переменную и закрыть это окошко и при следующем открытии эту переменную со значением впихнуть в окошко типа аля продолжение процесса. Ну чтоб знать что не висит тупо окошко. То есть закройте окошко перед паузой и потом снова откройте но с другой информацией и все. Это самый простой вариант. Ну а сам процесс задачи которую нужно остановить это уже вам там любым способом,типа таймера или другое что-то.
0
Модератор
Эксперт Python
 Аватар для Fudthhh
2695 / 1601 / 513
Регистрация: 21.02.2017
Сообщений: 4,210
Записей в блоге: 1
05.11.2020, 13:18
Drackar, если только использовать какой либо курсор. Например:

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
73
74
75
76
77
import sys
from PySide2 import QtWidgets, QtCore
 
 
class Worker(QtCore.QThread):
    current_step: int = 0
 
    paused: QtCore.SignalInstance = QtCore.Signal()
    stopped: QtCore.SignalInstance = QtCore.Signal()
 
    def run(self):
        for i in range(self.current_step, 10):
            self.current_step = i
            print(f"STEP {i}")
            self.msleep(500)
 
    def pause(self):
        self.terminate()
        self.paused.emit()
 
    def stop(self):
        self.current_step = 0
        if self.isRunning():
            self.terminate()
        self.stopped.emit()
 
 
class Widget(QtWidgets.QWidget):
 
    def __init__(self, parent: QtWidgets.QWidget = None):
        QtWidgets.QWidget.__init__(self, parent)
 
        self.worker = Worker(self)
 
        self.start = QtWidgets.QPushButton("START", self)
        self.pause = QtWidgets.QPushButton("PAUSE", self)
        self.stop = QtWidgets.QPushButton("STOP", self)
 
        self.pause.setDisabled(True)
        self.stop.setDisabled(True)
 
        self.start.clicked.connect(self.worker.start)
        self.pause.clicked.connect(self.worker.pause)
        self.stop.clicked.connect(self.worker.stop)
 
        self.worker.started.connect(self.startWorkerEvent)
        self.worker.paused.connect(self.pauseWorkerEvent)
        self.worker.stopped.connect(self.stopWorkerEvent)
 
        layout = QtWidgets.QHBoxLayout(self)
        layout.addWidget(self.start)
        layout.addWidget(self.pause)
        layout.addWidget(self.stop)
 
        if not parent:
            self.show()
 
    def startWorkerEvent(self):
        self.start.setDisabled(True)
        self.pause.setEnabled(True)
        self.stop.setEnabled(True)
 
    def pauseWorkerEvent(self):
        self.start.setEnabled(True)
        self.pause.setDisabled(True)
        self.stop.setEnabled(True)
 
    def stopWorkerEvent(self):
        self.start.setEnabled(True)
        self.pause.setDisabled(True)
        self.stop.setDisabled(True)
 
 
if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    main = Widget()
    sys.exit(app.exec_())
1
13 / 10 / 5
Регистрация: 11.10.2019
Сообщений: 290
05.11.2020, 13:30
Drackar, То есть я считаю что само информационное окошко сделать без потока,то есть один общий для всех потоков информация. А сами задачи которые пишете,как сказалDmFat, запихните в потоки.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
05.11.2020, 13:30
Помогаю со студенческими работами здесь

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

Какую библиотеку/Что нужно использовать, чтобы сделать графический интерфейс для данной задачи с многопоточностью
Винни-Пух и пчелы. Заданное количество пчел добывают мед равными порциями, задерживаясь в пути на случайное время. Винни-Пух потребляет...

Зависает форма при выполнении
Программа считывает звук с микрофона и выводит спектр на график, я ее изменил, чтобы она записывала спектр звука в файл. Но при выполнение...

Форма зависает при выполнении операции
Добрый день. У меня сканируется большое количество каталогов на наличие файлов, потом определяется размер огромного количества файлов....

Зависает форма при выполнении потока
Всем привет! Пишу на C++ Builder XE. Пишу MDI-приложение. 1. Основной поток запускает главную форму. 2. Из главной...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США. Нашел на реддите интересную статью под названием «Кто-нибудь знает, где получить бесплатный компьютер или. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru