场景
一般我们会在程序运行的过程中配置对应的日志信息,帮助我们了解当前程序执行的进度。
当使用qt增加了操作界面时,同样需要将日志信息在界面中显示出来。
思路
-
使用qt的QtWidgets.QTextEdit()
控件作为日志显示的区域。
- 日志展示区域应该能够看到最新的日志,
-
QtWidgets.QTextEdit().moveCursor(QTextCursor.StartOfLine)
;
-
QtWidgets.QTextEdit().ensureCursorVisible()
-
使用qt的信号机制将接受的日志信息写入QtWidgets.QTextEdit()
控件
-
根据日志信息中的日志级别关键字,控制设置文本的格式
def update_log(self, text):
"""将日志输出到 text widget"""
if not self.isVisible():
return
if "ERROR" in text:
text = f"<font color='red'><b>{text}</font><br>"
elif "INFO" in text:
text = f"<font color='green'>{text}</font><br>"
elif "WARNING" in text:
text = f"<font color='cyan'>{text}</font><br>"
elif "DEBUG" in text:
text = f"<font color='blue'>{text}</font><br>"
else:
text = f"{text}<br>"
self.log_browser.setWordWrapMode(QTextOption.WordWrap)
self.log_browser.moveCursor(QTextCursor.End)
self.log_browser.insertHtml(text)
self.log_browser.ensureCursorVisible()
实现
效果:
![在这里插入图片描述](https://img-blog.csdnimg.cn/25507bed6149412bb6d270487fcd4dd4.png)
示例代码:(为保证能够直接运行,已注释掉其他依赖的代码)
"""
@ProjectName : pythonProject
@FileName : camera_win.py
@Description:
@Time : 2022/10/27 11:21
@Author : Qredsun
"""
import json
from PyQt5 import QtWidgets
from PyQt5.QtCore import QObject
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtGui import QTextCursor
from PyQt5.QtGui import QTextOption
from loguru import logger
from camera_set_conf.camera_conf_set import CameraConf
from ui.Camera_ui import Ui_Form
from ui.browser_win import Dialog as conf_dialog
from ui.common import choose_file
from ui.common import info_box
from util.collect_project_info import read_conf_from_json
from util.collect_project_info import write_json_file
from PyQt5 import QtCore, QtGui, QtWidgets
CameraConf = None
conf_dialog = None
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.setWindowModality(QtCore.Qt.ApplicationModal)
Form.resize(356, 285)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
Form.setSizePolicy(sizePolicy)
self.gridLayout_2 = QtWidgets.QGridLayout(Form)
self.gridLayout_2.setObjectName("gridLayout_2")
self.label = QtWidgets.QLabel(Form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
self.label.setSizePolicy(sizePolicy)
self.label.setMinimumSize(QtCore.QSize(0, 35))
self.label.setMaximumSize(QtCore.QSize(16777215, 55))
self.label.setObjectName("label")
self.gridLayout_2.addWidget(self.label, 0, 0, 1, 1)
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.common_conf_path_edit = QtWidgets.QLineEdit(Form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.common_conf_path_edit.sizePolicy().hasHeightForWidth())
self.common_conf_path_edit.setSizePolicy(sizePolicy)
self.common_conf_path_edit.setMinimumSize(QtCore.QSize(135, 35))
self.common_conf_path_edit.setMaximumSize(QtCore.QSize(16777215, 55))
self.common_conf_path_edit.setObjectName("common_conf_path_edit")
self.gridLayout.addWidget(self.common_conf_path_edit, 0, 0, 1, 1)
self.common_conf_path_choose = QtWidgets.QPushButton(Form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.common_conf_path_choose.sizePolicy().hasHeightForWidth())
self.common_conf_path_choose.setSizePolicy(sizePolicy)
self.common_conf_path_choose.setMaximumSize(QtCore.QSize(16777215, 55))
self.common_conf_path_choose.setObjectName("common_conf_path_choose")
self.gridLayout.addWidget(self.common_conf_path_choose, 0, 1, 1, 1)
self.common_conf_edit = QtWidgets.QPushButton(Form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.common_conf_edit.sizePolicy().hasHeightForWidth())
self.common_conf_edit.setSizePolicy(sizePolicy)
self.common_conf_edit.setMaximumSize(QtCore.QSize(16777215, 55))
self.common_conf_edit.setObjectName("common_conf_edit")
self.gridLayout.addWidget(self.common_conf_edit, 0, 2, 1, 1)
self.gridLayout_2.addLayout(self.gridLayout, 1, 0, 1, 1)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_3 = QtWidgets.QLabel(Form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_3.sizePolicy().hasHeightForWidth())
self.label_3.setSizePolicy(sizePolicy)
self.label_3.setMaximumSize(QtCore.QSize(80, 55))
self.label_3.setObjectName("label_3")
self.horizontalLayout.addWidget(self.label_3)
self.comboBox = QtWidgets.QComboBox(Form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.comboBox.sizePolicy().hasHeightForWidth())
self.comboBox.setSizePolicy(sizePolicy)
self.comboBox.setMinimumSize(QtCore.QSize(120, 35))
self.comboBox.setMaximumSize(QtCore.QSize(16777215, 55))
self.comboBox.setObjectName("comboBox")
self.horizontalLayout.addWidget(self.comboBox)
self.private_conf_edit = QtWidgets.QPushButton(Form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.private_conf_edit.sizePolicy().hasHeightForWidth())
self.private_conf_edit.setSizePolicy(sizePolicy)
self.private_conf_edit.setMaximumSize(QtCore.QSize(16777215, 55))
self.private_conf_edit.setObjectName("private_conf_edit")
self.horizontalLayout.addWidget(self.private_conf_edit)
self.set_conf_btn = QtWidgets.QPushButton(Form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.set_conf_btn.sizePolicy().hasHeightForWidth())
self.set_conf_btn.setSizePolicy(sizePolicy)
self.set_conf_btn.setMaximumSize(QtCore.QSize(16777215, 55))
self.set_conf_btn.setObjectName("set_conf_btn")
self.horizontalLayout.addWidget(self.set_conf_btn)
self.gridLayout_2.addLayout(self.horizontalLayout, 2, 0, 1, 1)
self.log_browser = QtWidgets.QTextEdit(Form)
self.log_browser.setMinimumSize(QtCore.QSize(0, 140))
font = QtGui.QFont()
font.setPointSize(9)
self.log_browser.setFont(font)
self.log_browser.setObjectName("log_browser")
self.gridLayout_2.addWidget(self.log_browser, 3, 0, 1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "CAMERA设备配置"))
self.label.setText(_translate("Form", "相机公共配置"))
self.common_conf_path_edit.setPlaceholderText(_translate("Form", "公共配置文件路径"))
self.common_conf_path_choose.setText(_translate("Form", "选择文件"))
self.common_conf_edit.setText(_translate("Form", "配置预览"))
self.label_3.setText(_translate("Form", "相机编号"))
self.private_conf_edit.setText(_translate("Form", "配置预览"))
self.set_conf_btn.setText(_translate("Form", "一键配置"))
self.log_browser.setHtml(_translate("Form",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'SimSun\'; font-size:14pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;\"><br /></p></body></html>"))
self.log_browser.setPlaceholderText(_translate("Form", "程序配置日志"))
class Widget(QtWidgets.QWidget, Ui_Form):
def __init__(self, project_conf):
super().__init__()
self.setupUi(self)
log_out = Stream()
log_out.newText.connect(self.update_log)
logger.add(log_out, format="{time} | {level} | {message}")
self.devices_info = project_conf
self.common_conf_file_path = None
self.common_conf = None
self.cur_device_ip = None
self.private_conf = None
self.conf_setting_obj = None
self.default_win_status()
self.load_devices_ip()
self.common_conf_path_choose.clicked.connect(self.choose_common_conf_file)
self.common_conf_edit.clicked.connect(self.show_common_conf)
self.comboBox.currentTextChanged.connect(self.load_devices_info)
self.private_conf_edit.clicked.connect(self.show_private_conf)
self.set_conf_btn.clicked.connect(self.set_all_conf)
self.common_conf_edit.hide()
self.set_conf_btn.hide()
self.common_conf_path_choose.hide()
self.common_conf_edit.hide()
def set_all_conf(self):
self.log_browser.clear()
msg = '设备所有配置'
try:
if not self.conf_setting_obj.web_set_default_conf():
return
if not self.conf_setting_obj.sdk_set_conf():
return
logger.info(f'{msg} 成功')
except Exception as e:
logger.error(f'{msg} 失败 {e}')
def default_win_status(self):
self.set_conf_btn.setEnabled(False)
self.common_conf_edit.setEnabled(False)
def load_devices_ip(self):
items = list(self.devices_info.keys())
self.comboBox.clear()
self.comboBox.addItems(items)
logger.info('加载设备列表')
self.load_devices_info(update_setting_obj=False)
def load_devices_info(self, update_setting_obj=True):
self.log_browser.clear()
self.cur_device_ip = self.comboBox.currentText()
self.private_conf = self.devices_info.get(self.cur_device_ip, {})
if not len(self.private_conf):
msg = f'没有 {self.cur_device_ip} 对应的设备信息'
logger.error(msg)
info_box(msg, self)
return
if update_setting_obj:
self._widget_load_common_conf()
def update_log(self, text):
"""将日志输出到 text widget"""
if not self.isVisible():
return
if "ERROR" in text:
text = f"<font color='red'><b>{text}</font><br>"
elif "INFO" in text:
text = f"<font color='green'>{text}</font><br>"
elif "WARNING" in text:
text = f"<font color='cyan'>{text}</font><br>"
elif "DEBUG" in text:
text = f"<font color='blue'>{text}</font><br>"
else:
text = f"{text}<br>"
self.log_browser.setWordWrapMode(QTextOption.WordWrap)
self.log_browser.moveCursor(QTextCursor.End)
self.log_browser.insertHtml(text)
self.log_browser.ensureCursorVisible()
def open_conf_browser(self, text, title):
msg = 'test msg test msg test msg test msg test msg test msg test msg test msg test msg test msg '
logger.debug(msg)
logger.info(msg)
logger.warning(msg)
logger.error(msg)
logger.critical(msg)
def update_conf_by_signal(self, content):
self.text_browser_conf = content
def choose_common_conf_file(self):
self.log_browser.clear()
file_path = choose_file(win_name='设备公共配置文件', file_type='*.json', cur_img_save_dir='.', widget=self)
file_path = r'D:\work\boradxt\pythonProject\camera_set_conf\project_conf_jichang.json'
self.common_conf_file_path = file_path
self.common_conf_path_edit.setText(file_path)
self.common_conf = read_conf_from_json(self.common_conf_file_path)
logger.info(f'加载公共配置文件:{file_path}')
self._widget_load_common_conf()
def _widget_load_common_conf(self):
try:
self.common_conf_edit.setEnabled(True)
self.update_cam_setting_obj()
except Exception as e:
logger.error(f'{self.common_conf_file_path} 配置文件格式不符合要求 {e}')
def update_cam_setting_obj(self):
msg = f'初始化设备 {self.cur_device_ip} 配置对象'
try:
if not self.common_conf_file_path:
raise ValueError('缺失公共配置')
self.conf_setting_obj = CameraConf(self.cur_device_ip, self.private_conf, self.common_conf_file_path)
self.conf_setting_obj.load_conf(self.common_conf)
logger.debug(f'{msg}成功')
self.set_conf_btn.setEnabled(True)
except Exception as e:
info_box(f'{msg}失败:{e}', self, 2, '错误')
logger.error(f'{msg}失败:{e}')
def show_common_conf(self):
title = f'{self.common_conf["project_name"]}_{self.common_conf["version"]} 公共配置'
conf_data = json.dumps(self.common_conf, indent=4, ensure_ascii=False)
self.open_conf_browser(conf_data, title)
self.common_conf = json.loads(self.text_browser_conf)
write_json_file(self.common_conf, self.common_conf_file_path)
logger.info(f'{title} 结束预览')
def show_private_conf(self):
title = f'{self.cur_device_ip} 私有配置'
conf_data = json.dumps(self.private_conf, indent=4, ensure_ascii=False)
self.open_conf_browser(conf_data, title)
logger.info(f'{title} 结束预览')
class Stream(QObject):
"""Redirects console output to text widget."""
newText = pyqtSignal(str)
def write(self, text):
self.newText.emit(str(text))
import sys
if __name__ == '__main__':
project_conf = {
"10.10.40.2": {
"ip": "10.10.40.2",
"xiecn_ip": "10.10.40.249",
"netmask": "255.255.255.0",
"gateway": "10.10.40.254",
"rod_id": "252L",
"slot_id": 2,
"device_option": "M2391-10-TL-M20",
"point_id": 12000001,
"osd": "252L-00001-2",
"is_middle": True
}}
app = QtWidgets.QApplication(sys.argv)
w = Widget(project_conf)
w.show()
sys.exit(app.exec_())
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)