我目前正在使用qt designer处理GUI。我想知道如何在GUI上打印字符串,就像记录器窗口一样。我正在使用pyqt5。
答案 0 :(得分:11)
如果您使用Python logging
模块可以轻松创建自定义日志记录处理程序,将日志消息传递到QPlainTextEdit
实例(如Christopher所述)。
为此,您首先将logging.Handler
子类化。在此__init__
中,我们创建了包含日志的QPlainTextEdit
。这里的关键位是句柄将通过emit()
函数接收消息。因此,我们重载此函数并将消息文本传递到QPlainTextEdit
。
import logging
class QPlainTextEditLogger(logging.Handler):
def __init__(self, parent):
super(Logger, self).__init__()
self.widget = QPlainTextEdit(parent)
self.widget.setReadOnly(True)
def emit(self, record):
msg = self.format(record)
self.widget.textCursor().appendPlainText(msg)
def write(self, m):
pass
从此类创建一个对象,将其传递给QPlainTextEdit
的父对象(例如主窗口或布局)。然后,您可以为当前记录器添加此处理程序。
# Set up logging to use your widget as a handler
log_handler = QPlainTextEditLogger(<parent widget>)
logging.getLogger().addHandler(log_handler)
答案 1 :(得分:9)
以下是基于mfitzp's answer的完整工作示例:
<img src="~/Content/images/login-logo.png" width="{{image.width}}" height="{{image.size}}"/>
<div class="right-wrapper">
<h3 class="right-head">Appearance <img src="~/Content/images/info-icon.png"></h3>
<div ng-if="isImage">
<div ng-class="form-group">
size
<input class="form-control" type="textbox" ng-model="image.size" />
</div>
<div ng-class="form-group">
width
<input class="form-control" type="textbox" ng-model="image.width" />
</div>
</div>
</div>
答案 2 :(得分:8)
改编自Todd Vanyo的PyQt5示例:
import sys
from PyQt5 import QtWidgets
import logging
# Uncomment below for terminal log messages
# logging.basicConfig(level=logging.DEBUG, format=' %(asctime)s - %(name)s - %(levelname)s - %(message)s')
class QTextEditLogger(logging.Handler):
def __init__(self, parent):
super().__init__()
self.widget = QtWidgets.QPlainTextEdit(parent)
self.widget.setReadOnly(True)
def emit(self, record):
msg = self.format(record)
self.widget.appendPlainText(msg)
class MyDialog(QtWidgets.QDialog, QtWidgets.QPlainTextEdit):
def __init__(self, parent=None):
super().__init__(parent)
logTextBox = QTextEditLogger(self)
# You can format what is printed to text box
logTextBox.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
logging.getLogger().addHandler(logTextBox)
# You can control the logging level
logging.getLogger().setLevel(logging.DEBUG)
self._button = QtWidgets.QPushButton(self)
self._button.setText('Test Me')
layout = QtWidgets.QVBoxLayout()
# Add the new logging box widget to the layout
layout.addWidget(logTextBox.widget)
layout.addWidget(self._button)
self.setLayout(layout)
# Connect signal to slot
self._button.clicked.connect(self.test)
def test(self):
logging.debug('damn, a bug')
logging.info('something to remember')
logging.warning('that\'s not right')
logging.error('foobar')
app = QtWidgets.QApplication(sys.argv)
dlg = MyDialog()
dlg.show()
dlg.raise_()
sys.exit(app.exec_())
答案 3 :(得分:6)
class QTextEditLogger(logging.Handler, QtCore.QObject):
appendPlainText = QtCore.pyqtSignal(str)
def __init__(self, parent):
super().__init__()
QtCore.QObject.__init__(self)
self.widget = QtWidgets.QPlainTextEdit(parent)
self.widget.setReadOnly(True)
self.appendPlainText.connect(self.widget.appendPlainText)
def emit(self, record):
msg = self.format(record)
self.appendPlainText.emit(msg)
logTextBox = QTextEditLogger(self)
# log to text box
logTextBox.setFormatter(
logging.Formatter(
'%(asctime)s %(levelname)s %(module)s %(funcName)s %(message)s'))
logging.getLogger().addHandler(logTextBox)
logging.getLogger().setLevel(logging.DEBUG)
# log to file
fh = logging.FileHandler('my-log.log')
fh.setLevel(logging.DEBUG)
fh.setFormatter(
logging.Formatter(
'%(asctime)s %(levelname)s %(module)s %(funcName)s %(message)s'))
logging.getLogger().addHandler(fh)
答案 4 :(得分:1)
听起来你想要将QPlainTextEdit小部件设置为只读。
考虑将背景颜色更改为灰色,以便为用户提供不可编辑的提示。如果您希望它可滚动或文本可选,也由您决定。
This answer可以让你开始子类化QPlainTextEdit来滚动输出,保存到文件,等等。
答案 5 :(得分:0)
在单线程情况下,Alex的回答应该可以,但是,如果您登录另一个线程(QThread),则会收到警告。
QObject::connect: Cannot queue arguments of type 'QTextCursor'
(Make sure 'QTextCursor' is registered using qRegisterMetaType().)
因为您正在从主线程以外的其他线程修改GUI(self.widget.appendPlainText(msg)
),而不使用Signal / Slot。
这是我的解决方法:
# my_logger.py
import logging
from PyQt5.QtCore import pyqtSignal, QObject
class Handler(QObject, logging.Handler):
new_record = pyqtSignal(object)
def __init__(self, parent):
super().__init__(parent)
super(logging.Handler).__init__()
formatter = Formatter('%(asctime)s|%(levelname)s|%(message)s|', '%d/%m/%Y %H:%M:%S')
self.setFormatter(formatter)
def emit(self, record):
msg = self.format(record)
self.new_record.emit(msg) # <---- emit signal here
class Formatter(logging.Formatter):
def formatException(self, ei):
result = super(Formatter, self).formatException(ei)
return result
def format(self, record):
s = super(Formatter, self).format(record)
if record.exc_text:
s = s.replace('\n', '')
return s
# gui.py
... # GUI code
...
def setup_logger(self)
handler = Handler(self)
log_text_box = QPlainTextEdit(self)
self.main_layout.addWidget(log_text_box)
logging.getLogger().addHandler(handler)
logging.getLogger().setLevel(logging.INFO)
handler.new_record.connect(log_text_box.appendPlainText) # <---- connect QPlainTextEdit.appendPlainText slot
...