目录
①创建元素 分类管理元素,新增的界面元素都按照各自的类别分别管理。
②排版 在widget_content列表里,按照预想的位置去排列元素.
前言
python开发的脚本总是要配合界面才会好用.平时,添加一些功能就要调整一下界面.
现在,改出一个通用版本,方便快速的调整界面.
结构说明
①创建元素 分类管理元素,新增的界面元素都按照各自的类别分别管理。
# 创建按钮 self._setting_btn() # 创建标签信息 self._setting_label() # 创建文本输入框 self._setting_text_edit() # 创建 选择框 self._setting_combo()
②排版 在widget_content列表里,按照预想的位置去排列元素.
__核心方法__ self.__setting_layout()
widget_content = [
# 第一行第一个
[self.lb_file2],
# 第二行 并排多个
[self.bt_file2, self.edit_file2],
[self.bt_file, self.edit_file],
[self.bt_clear_file2, self.bt_combine_file],
[self.lb_setting],
# 数组嵌套 前者在上面(标签说明),后者在下面(输入框)
[[self.bt_setting], [self.lb_input_num, self.input_num],
[self.lb_unit, self.cb_units], [self.lb_time, self.cb_time]],
[self.lb_file],
[self.bt_file, self.edit_file],
[self.bt_clear_file, self.bt_split],
[self.lb_process]
]
③修改样式
调整edit_style的内容
属性 | 作用 |
:checked | 按钮控件被选中 |
:unchecked | 按钮控件未被选中 |
:indeterminate | 对于checkBox 或者redioButton 部分选中 |
:hover | 鼠标放上去 |
:pressed | 按下 |
:focus | 获取焦点 |
:disabled | 控件禁用 |
:enabled | 控件启用 |
:on | 可用 |
:off | 关闭 |
background-color | 背景颜色 |
color | 字体颜色 |
border | 边框宽度 |
border-radius | 边框圆角 |
font-size | 字体大小 |
font-family | 字体类型(Times New Roman) |
代码
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @FileName :my_interface.py
# @Time :2022/7/19 11:10
# @Author :Marst
"""
task:
step1
step2
...
"""
import datetime
import os
import shutil
import sys
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtGui import QFont, QIntValidator
from PyQt5.QtWidgets import QMainWindow, QStatusBar, QProgressBar, QApplication, QPushButton, QComboBox, QLineEdit, \
QWidget, QVBoxLayout, QHBoxLayout
from PyQt5.QtWidgets import QTextEdit, QFileDialog, QLabel, QMessageBox
sys.path.append('..')
today_date = datetime.datetime.now().strftime("%F")
DEFAULT_TIP = "请选择或拖拽file(CSV)文件到框中"
DEFAULT_TIP2 = "请选择或拖拽file2(CSV)文件到框中"
DEFAULT_TIP3 = "请选择或拖拽file(CSV)文件到框中"
DEFAULT_TIP_Items = "(可选)请拖拽存放位置到框中"
DEFAULT_LABEL_TEXT_file2 = "①file2文件路径"
DEFAULT_LABEL_TEXT_PARA = "②参数设定"
DEFAULT_LABEL_TEXT_file = "③file文件路径"
DEFAULT_LABEL_TEXT_Items = "时间误差"
DEFAULT_LABEL_TEXT2 = "file Unit"
DEFAULT_LABEL_Time = "file Start Time"
INTRODUTION_REPORT = "①选file2文件,点击下方对应 Clear按钮;\n" \
"②设定参数;\n" \
"③选file文件,点击下方对应 Clear按钮;\n" \
"④最后点击Run按钮,开始合并数据."
REPORT_FOLDER = ""
TODAY_FOLDER = ""
REPORT_SETTING = {}
version = "0.0.1"
class ComboxTime(QWidget):
def __init__(self, time_list=None, parent=None):
super(ComboxTime, self).__init__(parent)
self.setWindowTitle("选择初始时间")
self.resize(420, 90)
layout = QVBoxLayout()
self.lb = QLabel()
if time_list:
self.cb_time.addItems(time_list)
layout.addWidget(self.cb_time)
layout.addWidget(self.lb)
self.setLayout(layout)
class ReportTool(QMainWindow):
window_title = f'ReportTool v{version} Marst'
tool_x, tool_y = 770, 700
# 设置按钮控件大小
w, h = 90, 25
pos_x, pos_y = 15, 25
delta_y = 150
tx_pos_x, tx_w = 210, 900
select_cbox_items = ["数据合并", "批量处理"]
select_ct = ["left", "right"]
edit_style = """
QTextEdit{background:#F5F5DC;border:1px solid white;border-radius:5px;font-weight:bold;font-size:9px}
QComboBox{border:1px solid white;font-size:12px;}
QLineEdit{border:1px solid white;font-size:12px;}
QPushButton{font-weight:bold;font-size:18px;background-color:#ff4c41;font-family:'Arial';color:#ffffff;
border:1px solid white;border-radius:6px}
QPushButton:hover{background-color:rgb(44,169,225);border:1px solid rgb(44,169,225)}
QPushButton:disabled{background-color:#a9b6bb}
QLabel{font-weight:bold;font-size:11px;}
#Anc{font-size:12px;font-family:'Arial';color:#0968F7}
#mode{font-size:26px;font-family:'Arial';color:black}
#RunBt:hover{background-color:#22DD92}
#RunBt:disabled{background-color:#a9b6bb}
#RunBt{font-weight:bold;font-size:29px;background-color:rgb(44,169,225);border:1px solid white;border-radius:6px;};
background-color:#FFEBCD;color:#2B2B2B;
"""
def __init__(self):
super().__init__()
self.csv_path = None
self.target_path = None
self.value = 0
self.worker = None
self.start_time_file2 = REPORT_SETTING.get('start_time_file2')
self.start_time_file = None
self.file_data = None
self.file2_data = None
self.unit_pos = None
self.show_msg_list = []
# 输入框
self.input_num = self.create_validator()
self.input_num.setText(f"{REPORT_SETTING.get('time', 5)}")
self.input_num.setToolTip(f"file2与file的时间差范围值")
self.input_num.setFixedWidth(38)
self.input_num.setFixedHeight(self.h)
# 创建按钮
self._setting_btn()
# 创建标签信息
self._setting_label()
# 创建文本输入框
self._setting_text_edit()
# 创建 选择框
self._setting_combo()
# 状态栏
self.statusBar = QStatusBar(self)
# 进度条
self.progressBar = QProgressBar()
self.__setting_layout()
self.init_ui()
self.setStyleSheet(self.edit_style)
def __setting_layout(self):
# 主要布局
self.mainLayout = QVBoxLayout(self)
# 顶层的设定
header_layout = QHBoxLayout()
header_widget = QWidget()
header_layout.addStretch(1)
header_layout.addWidget(self.label_mode)
header_layout.addWidget(self.cb_mode)
header_layout.addStretch(9)
header_layout.addWidget(self.label_introdution)
header_widget.setLayout(header_layout)
self.mainLayout.addWidget(header_widget)
widget_content = [
[self.lb_file2],
[self.bt_file2, self.edit_file2],
[self.bt_file, self.edit_file],
[self.bt_clear_file2, self.bt_combine_file],
[self.lb_setting],
[[self.bt_setting], [self.lb_input_num, self.input_num],
[self.lb_unit, self.cb_units], [self.lb_time, self.cb_time]],
[self.lb_file],
[self.bt_file, self.edit_file],
[self.bt_clear_file, self.bt_split],
[self.lb_process]
]
for y, row_line in enumerate(widget_content):
temp_layout = QHBoxLayout()
temp_widget = QWidget()
for x, wid in enumerate(row_line):
if x == 0:
temp_layout.addSpacing(5)
if isinstance(wid, list):
vtemp_layout = QVBoxLayout()
vtemp_widget = QWidget()
for _ in wid:
vtemp_layout.addWidget(_)
vtemp_layout.addSpacing(1)
vtemp_widget.setLayout(vtemp_layout)
temp_layout.addWidget(vtemp_widget)
temp_layout.addStretch(2)
else:
temp_layout.addWidget(wid)
temp_widget.setLayout(temp_layout)
self.mainLayout.addWidget(temp_widget)
self.mainLayout.addStretch(2)
# 布局生效
widget = QWidget()
widget.setLayout(self.mainLayout)
self.setCentralWidget(widget)
self.setLayout(self.mainLayout)
def _setting_btn(self):
self.bt_file = QPushButton('&file', self)
self.bt_file.setToolTip("选取CT文件")
self.bt_file.setFixedWidth(self.w)
self.bt_clear_file = QPushButton('Clear', self)
self.bt_clear_file.setToolTip("对CT文件进行预处理")
self.bt_clear_file.setFixedWidth(self.w)
self.bt_file2 = QPushButton('&file2', self)
self.bt_file2.setToolTip("选取file2文件")
self.bt_file2.setFixedWidth(self.w)
self.bt_file = QPushButton('file', self)
self.bt_file.setToolTip("选取file文件")
self.bt_file.setFixedWidth(self.w)
self.bt_clear_file2 = QPushButton('Clear', self)
self.bt_clear_file2.setToolTip("对file2文件进行预处理")
self.bt_clear_file2.setFixedWidth(self.w)
self.bt_combine_file = QPushButton('Combine', self)
self.bt_combine_file.setToolTip("合并file文件")
self.bt_combine_file.setFixedWidth(self.w)
self.bt_setting = QPushButton('Setting', self)
self.bt_setting.setToolTip("保存设定参数,包括文件的路径等")
self.bt_setting.setFixedWidth(self.w)
self.bt_run = QPushButton('&RUN', self)
self.bt_run.setObjectName("RunBt")
self.bt_split = QPushButton('Split', self)
self.bt_split.setObjectName("SplitBt")
self.bt_split.setFixedWidth(self.w)
self.bt_split.setToolTip("将文件拆分成两半.")
# 实行按钮功能
self.bt_file.clicked.connect(self.open_csv_file)
self.bt_clear_file.clicked.connect(self.func_one)
self.bt_file2.clicked.connect(self.open_target_file)
self.bt_file.clicked.connect(self.open_target_file_file)
self.bt_clear_file2.clicked.connect(self.func_two)
self.bt_combine_file.clicked.connect(self.func_combine_file)
self.bt_setting.clicked.connect(self.update_setting)
self.bt_split.clicked.connect(self.func_four)
# 设置开始按钮
self.bt_run.clicked.connect(self.start_process)
def _setting_label(self):
self.label_mode = QLabel(self)
self.label_mode.setText("模式")
self.label_mode.setObjectName("mode")
self.label_introdution = QLabel(self)
self.label_introdution.setText(INTRODUTION_REPORT)
self.label_introdution.setObjectName("Anc")
self.lb_file = QLabel(self)
self.lb_file.setText(DEFAULT_LABEL_TEXT_file)
self.lb_file2 = QLabel(self)
self.lb_file2.setText(DEFAULT_LABEL_TEXT_file2)
self.lb_setting = QLabel(self)
self.lb_setting.setText(DEFAULT_LABEL_TEXT_PARA)
self.lb_input_num = QLabel(self)
self.lb_input_num.setText(DEFAULT_LABEL_TEXT_Items)
self.lb_unit = QLabel(self)
self.lb_unit.setText(DEFAULT_LABEL_TEXT2)
self.lb_time_title = QLabel(self)
self.lb_time_title.setText("时间误差")
self.lb_time_title.setHidden(True)
self.lb_time = QLabel(self)
self.lb_time.setText(DEFAULT_LABEL_Time)
self.lb_process = QLabel(self)
# 设置状态标签
self.show_msg('程序初始化成功!')
def _setting_text_edit(self):
self.edit_file = MyTextEdit(self)
self.edit_file.setText(REPORT_SETTING.get("file_path", ""))
self.edit_file.setFixedHeight(self.h)
self.edit_file2 = MyTextEdit(self)
self.edit_file2.setText(REPORT_SETTING.get("file2_path", ""))
self.edit_file2.setFixedHeight(self.h)
self.edit_file = MyTextEdit(self)
self.edit_file.setText(REPORT_SETTING.get("file_path", ""))
self.edit_file.setFixedHeight(self.h)
self.tx3 = MyTextEdit(self)
self.tx3.setHidden(True)
self.edit_file.setPlaceholderText(DEFAULT_TIP)
self.edit_file2.setPlaceholderText(DEFAULT_TIP2)
self.edit_file.setPlaceholderText(DEFAULT_TIP3)
def _setting_combo(self):
self.cb_mode = QComboBox(self)
self.cb_mode.addItems(self.select_cbox_items)
self.cb_mode.currentIndexChanged.connect(self.model_selection_change)
self.cb_mode.setFixedWidth(120)
self.cb_units = QComboBox(self)
self.cb_units.addItems(self.select_ct)
self.cb_units.setToolTip(f"left 1,3,5,7\nright 2,4,6,8")
self.cb_units.setFixedWidth(80)
self.cb_units.setFixedHeight(self.h)
self.cb_time = QComboBox(self)
self.cb_time.setToolTip("设定file数据的开始时间")
self.cb_time.setFixedWidth(200)
self.cb_time.setFixedHeight(self.h)
# file2_time_list
_file2_time_list = REPORT_SETTING.get("file2_time_list")
if _file2_time_list:
self.cb_time.addItems(_file2_time_list)
def init_ui(self):
# 设置字体大小
font = QFont()
font.setFamily('STSong')
font.setPointSize(9)
self.setFont(font)
self.setWindowTitle(self.window_title)
# 定义状态栏
self.setStatusBar(self.statusBar)
self.statusBar.addPermanentWidget(self.bt_run, stretch=0)
self.statusBar.addPermanentWidget(self.progressBar, stretch=2)
self.progressBar.setRange(0, 100) # 设置进度条的范围
self.progressBar.setValue(0)
self.setFixedSize(self.tool_y, self.tool_x)
def hide_all(self, hide_val=False):
hidden_list = [
self.bt_file,
self.bt_file2,
self.edit_file,
self.edit_file2,
self.tx3,
self.lb_time_title,
self.lb_input_num,
self.lb_unit,
self.input_num,
self.lb_file,
self.lb_file2,
]
for h in hidden_list:
h.setHidden(hide_val)
def model_selection_change(self):
# 测试项筛选
self.hide_all(False)
def show_msg(self, val):
if val:
self.show_msg_list.append(f"{val}")
str_val = '\n'.join(self.show_msg_list[-3:])
self.lb_process.setText(str_val)
def open_csv_file(self):
self.edit_file.clear()
# 文件夹
# csv_path = QFileDialog.getExistingDirectory(self, '', './')
# 单文件
csv_path = QFileDialog.getOpenFileName(self, '选取csv文件', './')
self.edit_file.setText(csv_path[0])
self.bt_run.setEnabled(True)
def func_one(self):
"""
开始处理 file 文件
:return:
"""
csv_path = self.edit_file.toPlainText()
if not os.path.exists(csv_path):
self.show_msg(f"文件不存在,请检查 {csv_path}")
QMessageBox.critical(self, "警告", f"文件不存在,请检查 {csv_path}")
return
def func_two(self):
csv_path = self.edit_file2.toPlainText()
if not os.path.exists(csv_path):
self.show_msg(f"文件不存在,请检查 {csv_path}")
QMessageBox.critical(self, "警告", f"文件不存在,请检查 {csv_path}")
return
def func_three(self):
file_path = self.edit_file.toPlainText()
self.show_msg(f"获取file文件 {file_path}")
def open_target_file(self):
"""
打开文件夹 只见xlsx文件
:return:
"""
self.edit_file2.clear()
# files = QFileDialog.getOpenFileName(self, 'Open file', './', 'xlsx files (*.xlsx)')
csv_path = QFileDialog.getOpenFileName(self, '选取csv文件', './')
self.edit_file2.setText(csv_path[0])
def open_target_file_file(self):
"""
打开文件夹 只见xlsx文件
:return:
"""
self.edit_file.clear()
# files = QFileDialog.getOpenFileName(self, 'Open file', './', 'xlsx files (*.xlsx)')
csv_path = QFileDialog.getOpenFileName(self, '选取csv文件', './')
self.edit_file.setText(csv_path[0])
def update_setting(self):
p = self.edit_file.toPlainText()
if p:
REPORT_SETTING["file_path"] = p
p2 = self.edit_file2.toPlainText()
if p2:
REPORT_SETTING["file2_path"] = p2
p3 = self.edit_file.toPlainText()
if p3:
REPORT_SETTING["file_path"] = p3
time_range = int(self.input_num.text())
REPORT_SETTING["time"] = time_range
REPORT_SETTING["start_time_file2"] = self.start_time_file2
self.show_msg(f"设定参数保存成功")
def func_four(self):
csv_path = self.edit_file.toPlainText()
if not os.path.exists(csv_path):
self.show_msg(f"文件不存在,请检查 {csv_path}")
QMessageBox.critical(self, "警告", f"文件不存在,请检查 {csv_path}")
return
def func_combine_file(self):
self.show_msg("combine")
def create_validator(self):
int_line_edit = QLineEdit(self)
int_validator = QIntValidator(self)
int_validator.setRange(1, 9999)
int_line_edit.setValidator(int_validator)
input_config_num = int_line_edit
input_config_num.setPlaceholderText('输入数字')
input_config_num.setFixedSize(130, 40)
return input_config_num
def start_process(self):
model_text = self.cb_mode.currentText()
if model_text == self.select_cbox_items[0]:
if self.file2_data is None:
self.show_msg(f"请先预处理file2文件, 对file2进行Clear")
return
if self.file_data is None:
self.show_msg(f"请先预处理file文件, 对file进行Clear")
return
value = 0
self.progressBar.setValue(value)
self.show_msg("开始合并数据")
self.bt_run.setEnabled(False)
if self.file_data and self.file2_data:
# 这句就很关键了
self.lb_process.repaint()
self.worker = ReportWorker(self.file_data, self.file2_data, self.end_process, self)
self.worker.start()
elif model_text == self.select_cbox_items[1]:
...
else:
self.show_msg('请选择要处理的文件!')
def end_process(self, value):
self.progressBar.setValue(value)
if value == 100:
del self.worker
if os.path.exists('res_img'):
shutil.rmtree('res_img')
self.bt_run.setEnabled(True)
class ReportWorker(QThread):
_signal = pyqtSignal(int)
def __init__(self, file_data, file2_data, func, parent=None):
super(ReportWorker, self).__init__()
self.file_data = file_data
self.file2_data = file2_data
self.parent = parent
self._signal.connect(func)
def update_process_bar(self, val, count):
value = int(val * 100 / count)
if value <= 99:
self._signal.emit(value)
def run(self):
try:
self.parent.show_msg("start run")
except Exception as e:
self.parent.show_msg(e)
self._signal.emit(100)
class MyTextEdit(QTextEdit):
"""实现文件拖放功能"""
def __init__(self, parent=None):
super().__init__(parent)
self.setAcceptDrops(True) # 设置接受拖放动作
def dragEnterEvent(self, e):
if e.mimeData().text().endswith(''): # 如果是.srt结尾的路径接受
e.accept()
else:
e.ignore()
def dropEvent(self, e): # 放下文件后的动作
if os.name == 'nt':
path = e.mimeData().text().replace('file:///', '') # 删除多余开头
else:
path = e.mimeData().text().replace('file://', '') # 删除多余开头
self.setText(path)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = ReportTool()
ex.show()
sys.exit(app.exec_())
优点
这个脚本的好处是快速便捷,使用时,只要创建新的元素,并通过修改widget_content列表的内容就可以马上产生自己想要的效果.