#python #qt #python-3.x #pyqt
#python #qt #python-3.x #pyqt
Вопрос:
Я пытаюсь отправить стандартный вывод как на консоль, так и QTextBrowser
на виджет. Но я получаю какой-то бесконечный цикл, а затем приложение завершает работу.
Вот мой код:
import sys
from PyQt5 import QtWidgets, uic
from PyQt5.QtCore import *
qtCreatorFile = "qt_ui.ui"
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
self.start_button.clicked.connect(printing)
def printing():
print("Pressed!n")
class Logger(QObject):
def __init__(self):
super().__init__()
self.terminal = sys.stdout
def write(self, message):
self.terminal.write(message)
self.log_browser.setText(message) #problem is in this line
def flush(self):
pass
if __name__ == "__main__":
sys.stdout = Logger()
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
В результате при нажатии кнопки start_button наблюдается следующее:
"C:...python.exe" "E:/.../qt_gui.py"
Pressed!
Pressed!
Pressed!
... (totaly 332 times)
Pressed!
Pressed!
Pressed!
Process finished with exit code 1
Я просто не могу понять, почему эта строка создает цикл:
self.log_browser.setText(message)
Редактировать после 1-го ответа:
Я заменил строку выше на print(message)
, но все равно получаю те же результаты. Я был бы признателен за любую помощь.
Комментарии:
1. В определении класса ошибка отступа
2. Это была ошибка копирования / вставки, а не из исходного кода. Я исправил это.
Ответ №1:
Вы можете выдать пользовательский сигнал Logger
и подключить его к обозревателю журналов:
class Logger(QObject):
loggerMessage = pyqtSignal(str)
def __init__(self):
super().__init__()
self.terminal = sys.stdout
def write(self, message):
self.terminal.write(message)
self.loggerMessage.emit(message)
def flush(self):
pass
if __name__ == "__main__":
sys.stdout = Logger()
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
sys.stdout.loggerMessage.connect(window.log_browser.insertPlainText)
window.show()
sys.exit(app.exec_())
Комментарии:
1. Я пробовал этот код, но сообщения не отображаются в QTextBrowser. Есть предложения, почему?
2.@dandepeched. Кажется, что
stdout
дважды — один раз для текста и один раз для конечной строки. Поэтому, если вы используетеsetText
, второй сигнал перезапишет первый. Я изменил свой пример для использованияinsertPlainText
, поэтому вместо этого он добавляет все сообщения.
Ответ №2:
Похоже, что опубликованный вами код не является кодом, который вы запустили, но, предполагая, что он репрезентативен, возникают две ошибки: базовый класс Logger должен быть инициализирован, а self.log_browser нигде не определен. Но это не вызывает цикла, приложение завершает работу (потому что есть исключение, но нет исключения, см. ). Поскольку я не знаю, каким должен быть log_browser, я определил его как Mock() (из unittest.mock), который примет все, что с ним сделано, и проблема исчезнет.
class Logger(QObject):
def __init__(self):
super().__init__()
self.terminal = sys.stdout
from unittest.mock import Mock
self.log_browser = Mock()
def write(self, message):
self.terminal.write(message)
self.log_browser.setText(message) # problem was this line
def flush(self):
pass
Комментарии:
1. log_browser определен в файле «qt_ui.ui», который переведен uic.
2. self.log_browser = QtWidgets. QTextBrowser(self.centralwidget)
3. Я упростил код, заменив log_browser функцией печати, также инициализировал класс, как вы сказали, но все равно получаю то же поведение.
4. Вызов print() из метода write() снова вызовет write(), что приведет к рекурсии, пока в интерпретаторе Python не закончится пространство стека.