1 Star 1 Fork 0

Ellu_IFX / DP100-PyQt5-GUI

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
DP100_gui.py 49.29 KB
一键复制 编辑 原始数据 按行查看 历史
Ellu 提交于 2023-11-28 21:31 . publish
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341
import datetime
import logging
import math
import os
import random
import sys
import time
from typing import List
os.environ["PYQTGRAPH_QT_LIB"] = "PyQt5"
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
import warnings
# ignore opengl runtime warnings
warnings.filterwarnings("ignore", category=RuntimeWarning)
from threading import Lock
import numpy as np
import pyqtgraph as pg
import qdarktheme
from PyQt5 import QtCore, QtGui, QtWidgets
from qframelesswindow import AcrylicWindow, FramelessWindow, TitleBar
from simple_pid import PID
OPENGL_AVAILABLE = False
try:
import OpenGL
OPENGL_AVAILABLE = True
pg.setConfigOption("enableExperimental", True)
pg.setConfigOption("antialias", True)
logger.info("OpenGL successfully enabled")
except Exception as e:
logger.warning(f"Enabling OpenGL failed with {e}.")
try:
import numba as nb
pg.setConfigOption("useNumba", True)
logger.info("Numba successfully enabled")
except Exception as e:
logger.warning(f"Enabling Numba failed with {e}.")
from DP100API import DP100
from DP100GUI import Ui_DialogGraphics, Ui_DialogSettings, Ui_MainWindow
api = DP100()
_PATH = os.path.dirname(__file__)
ICON_PATH = os.path.join(_PATH, "icon.ico")
qdarktheme.enable_hi_dpi()
app = QtWidgets.QApplication(sys.argv)
class FmtAxisItem(pg.AxisItem):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def tickStrings(self, values, scale, spacing):
if len(values) == 0 or max(values) < 1e6:
return super().tickStrings(values, scale, spacing)
else:
return [f"{v:.2e}" for v in values]
class Data_Share:
def __init__(self, data_length=1000) -> None:
self.start_time = time.perf_counter()
self.graph_start_time = time.perf_counter()
self.last_time = 0
self.save_datas_flag = False
self.filter_k = 1
self.voltage = 0
self.current = 0
self.power = 0
self.energy = 0
self.resistance = 0
self.sync_lock = Lock()
self.voltages = np.zeros(data_length, np.float64)
self.currents = np.zeros(data_length, np.float64)
self.powers = np.zeros(data_length, np.float64)
self.resistances = np.zeros(data_length, np.float64)
self.times = np.zeros(data_length, np.float64)
self.update_count = data_length
self.data_length = data_length
class Data_Record:
def __init__(self) -> None:
self.voltages: List[float] = []
self.currents: List[float] = []
self.times: List[float] = []
self.start_time = None
def to_csv(self, filename):
data = np.array([self.times, self.voltages, self.currents]).T
np.savetxt(
filename,
data,
delimiter=",",
fmt="%f",
header="time,voltage,current",
comments="",
)
def set_color(widget: QtWidgets.QWidget, rgb):
color = f"rgb({rgb[0]},{rgb[1]},{rgb[2]})" if isinstance(rgb, tuple) else rgb
widget.setStyleSheet(f"color: {color}")
class FPSCounter(object):
def __init__(self, max_sample=40) -> None:
self.t = time.perf_counter()
self.max_sample = max_sample
self.t_list: List[float] = []
self._fps = 0.0
def clear(self) -> None:
self.t = time.perf_counter()
self.t_list = []
self._fps = 0.0
def tick(self) -> None:
t = time.perf_counter()
self.t_list.append(t - self.t)
self.t = t
if len(self.t_list) > self.max_sample:
self.t_list.pop(0)
@property
def fps(self) -> float:
length = len(self.t_list)
sum_t = sum(self.t_list)
if length == 0:
self._fps = 0.0
else:
fps = length / sum_t
if self._fps < 1:
self._fps = fps
self._fps += (fps - self._fps) * 2 / self._fps
return self._fps
class CustomTitleBar(TitleBar):
def __init__(self, parent):
super().__init__(parent)
self.label = QtWidgets.QLabel("DP100数控电源上位机", self)
self.label.setStyleSheet(
"QLabel{font: 13px 'Microsoft YaHei UI'; margin: 10px}"
)
self.label.adjustSize()
self.darkStyle = {
"normal": {
"color": (255, 255, 255),
}
}
self.lightStyle = {
"normal": {
"color": (20, 20, 20),
}
}
self.autoStyle = {
"normal": {
"color": (140, 140, 140),
}
}
def set_theme(self, theme):
style = getattr(self, f"{theme}Style")
self.minBtn.updateStyle(style)
self.maxBtn.updateStyle(style)
self.closeBtn.updateStyle(style)
self.fullBtn.updateStyle(style)
class DP100GUI(QtWidgets.QMainWindow, FramelessWindow): # QtWidgets.QMainWindow
data = Data_Share()
data_fps = 50
graph_fps = 50
graph_max_fps = 50
graph_keep_flag = False
graph_record_flag = False
output_state = False
_v_set = 0
_i_set = 0
open_r = 1e6
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.fps_counter = FPSCounter()
# self.windowEffect.setAcrylicEffect(self.winId(), "10101090")
self.CustomTitleBar = CustomTitleBar(self)
self.CustomTitleBar.set_theme("dark")
self.ui.comboDataFps.setCurrentText(f"{self.data_fps}Hz")
self.setTitleBar(self.CustomTitleBar)
self.initSignals()
self.resize(900, 780)
self.initGraph()
self.initTimer()
self.update_connection_state()
api.register_output_info_callback(self._state_callback)
self.ui.progressBarVoltage.setMaximum(1000)
self.ui.progressBarCurrent.setMaximum(1000)
self._last_state_change_t = time.perf_counter()
self.titleBar.raise_()
self.ui.comboPreset.setItemData(0, 0, QtCore.Qt.UserRole - 1)
self.ui.btnSeqStop.hide()
self.ui.listSeq.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
def initTimer(self):
self.check_connection_timer = QtCore.QTimer(self)
self.check_connection_timer.timeout.connect(self.update_connection_state)
self.state_request_sender_timer = QtCore.QTimer(self)
self.state_request_sender_timer.setTimerType(QtCore.Qt.PreciseTimer)
self.state_request_sender_timer.timeout.connect(api.get_output_info)
self.draw_graph_timer = QtCore.QTimer(self)
self.draw_graph_timer.timeout.connect(self.draw_graph)
self.func_sweep_timer = QtCore.QTimer(self)
self.func_sweep_timer.timeout.connect(self._func_sweep)
self.func_wave_gen_timer = QtCore.QTimer(self)
self.func_wave_gen_timer.timeout.connect(self._func_wave_gen)
self.func_keep_power_timer = QtCore.QTimer(self)
self.func_keep_power_timer.timeout.connect(self._func_keep_power)
self.func_seq_timer = QtCore.QTimer(self)
self.func_seq_timer.timeout.connect(self._func_seq)
self.graph_record_save_timer = QtCore.QTimer(self)
self.graph_record_save_timer.timeout.connect(self._graph_record_save)
def initSignals(self):
self.ui.comboDataFps.currentTextChanged.connect(self._set_data_fps)
self.ui.comboPreset.currentTextChanged.connect(self._set_preset)
self._ignore_preset_changed_signal = False
self.ui.comboPresetEdit.currentTextChanged.connect(self._get_preset)
self.ui.comboGraph1Data.currentTextChanged.connect(self._set_graph1_data)
self.ui.comboGraph2Data.currentTextChanged.connect(self._set_graph2_data)
self.ui.spinBoxVoltage.valueChanged.connect(self._voltage_changed)
self.ui.spinBoxCurrent.valueChanged.connect(self._current_changed)
self.ui.comboWaveGenType.currentTextChanged.connect(self._set_wavegen_type)
def startMyTimer(self):
self.data.start_time = time.perf_counter()
self.data.graph_start_time = time.perf_counter()
self.data.last_time = 0
self.data.energy = 0
self.check_connection_timer.start(1000)
self.state_request_sender_timer.start(1000 // self.data_fps)
self.draw_graph_timer.start(1000 // self.graph_fps)
def stopMyTimer(self):
self.check_connection_timer.stop()
self.state_request_sender_timer.stop()
self.draw_graph_timer.stop()
if self.func_sweep_timer.isActive():
self.stop_func_sweep()
if self.func_wave_gen_timer.isActive():
self.stop_func_wave_gen()
if self.func_keep_power_timer.isActive():
self.stop_func_keep_power()
def switch_fullscreen(self):
if self.isFullScreen():
self.showNormal()
else:
self.showFullScreen()
########## 基本功能 ##########
@property
def preset(self):
return int(self.ui.comboPreset.currentText())
@property
def v_set(self):
return self._v_set
@v_set.setter
def v_set(self, value):
api.set_output(
output=self.output_state,
v_set=value,
i_set=self._i_set,
preset=self.preset,
)
self._v_set = value
self.ui.spinBoxVoltage.setValue(value)
self._last_state_change_t = time.perf_counter()
@property
def i_set(self):
return self._i_set
@i_set.setter
def i_set(self, value):
api.set_output(
output=self.output_state,
v_set=self._v_set,
i_set=value,
preset=self.preset,
)
self._i_set = value
self.ui.spinBoxCurrent.setValue(value)
self._last_state_change_t = time.perf_counter()
def update_output_state_text(self):
state = api.get_state()
to_state = state["output"]
preset = state["preset"]
v_set = state["v_set"]
i_set = state["i_set"]
if to_state:
self.ui.btnOutput.setText("开启")
set_color(self.ui.btnOutput, "lightgreen")
else:
self.ui.btnOutput.setText("关闭")
set_color(self.ui.btnOutput, "khaki")
self.output_state = to_state
self.ui.comboPreset.setCurrentText(str(preset))
self._v_set = v_set
self.ui.spinBoxVoltage.setValue(v_set)
self._i_set = i_set
self.ui.spinBoxCurrent.setValue(i_set)
@QtCore.pyqtSlot()
def on_btnOutput_clicked(self):
self.output_state = not self.output_state
self._last_state_change_t = time.perf_counter()
api.set_output(self.output_state)
self.update_output_state_text()
api.set_output(self.output_state)
def update_connection_state(self):
state = api.connected
if state:
self.ui.labelConnectState.setText("已连接")
set_color(self.ui.labelConnectState, "lightgreen")
self.ui.frameOutputSetting.setEnabled(True)
self.ui.frameGraph.setEnabled(True)
if (
self.output_state
and self.v_set > 0
and self.i_set > 0
and self.data.voltage < 0.9 * self.v_set
and self.data.current < 0.9 * self.i_set
and time.perf_counter() - self._last_state_change_t > 0.5
):
self.ui.btnOutput.setText("异常")
set_color(self.ui.btnOutput, "red")
elif self.ui.btnOutput.text() == "异常":
self.update_output_state_text()
else:
self.ui.labelConnectState.setText("未连接")
set_color(self.ui.labelConnectState, "red")
set_color(self.ui.btnOutput, "grey")
self.ui.frameOutputSetting.setEnabled(False)
self.ui.frameGraph.setEnabled(False)
self.ui.progressBarCurrent.setValue(0)
self.ui.progressBarVoltage.setValue(0)
self._state_callback(0, 0)
self.stopMyTimer()
@QtCore.pyqtSlot()
def on_btnConnect_clicked(self):
try:
if api.connected:
api.disconnect()
else:
api.connect()
self._last_state_change_t = time.perf_counter()
self.startMyTimer()
state = api.get_state()
self.ui.spinBoxVoltage.setValue(state["v_set"])
self.ui.spinBoxCurrent.setValue(state["i_set"])
self._v_set = state["v_set"]
self._i_set = state["i_set"]
preset = str(state["preset"])
if preset != self.ui.comboPreset.currentText():
self._ignore_preset_changed_signal = True
self.ui.comboPreset.setCurrentText(preset)
self._get_preset(self.ui.comboPresetEdit.currentText())
self.update_output_state_text()
self.ui.btnGraphClear.clicked.emit()
except Exception as e:
self.ui.labelConnectState.setText("连接失败")
set_color(self.ui.labelConnectState, "red")
QtCore.QTimer.singleShot(1000, self.update_connection_state)
return
self.update_connection_state()
def _state_callback(self, voltage, current):
v = voltage / 1000
i = current / 1000
p = voltage * current / 1000000
if current != 0:
r = voltage / current
else:
r = self.open_r
t1 = time.perf_counter()
data = self.data
with data.sync_lock:
t = t1 - data.start_time
data.energy += voltage * current * (t - data.last_time) / 1000000
data.last_time = t
data.power += (p - data.power) * data.filter_k
data.voltage += (v - data.voltage) * data.filter_k
data.current += (i - data.current) * data.filter_k
data.resistance += (r - data.resistance) * data.filter_k
if data.save_datas_flag:
# data.voltages = np.hstack((data.voltages[1:], v))
# data.currents = np.hstack((data.currents[1:], i))
# data.powers = np.hstack((data.powers[1:], p))
# data.resistances = np.hstack((data.resistances[1:], r))
# data.times = np.hstack((data.times[1:], t1 - data.graph_start_time))
data.voltages = np.roll(data.voltages, -1)
data.currents = np.roll(data.currents, -1)
data.powers = np.roll(data.powers, -1)
data.resistances = np.roll(data.resistances, -1)
data.times = np.roll(data.times, -1)
data.voltages[-1] = v
data.currents[-1] = i
data.powers[-1] = p
data.resistances[-1] = r
data.times[-1] = t1 - data.graph_start_time
if data.update_count > 0:
data.update_count -= 1
if self.graph_record_flag:
self.graph_record_data.voltages.append(v)
self.graph_record_data.currents.append(i)
if self.graph_record_data.start_time is None:
self.graph_record_data.start_time = t1
self.graph_record_data.times.append(t1 - self.graph_record_data.start_time)
r_text = f"{data.resistance:.3f}" if data.resistance < self.open_r - 1 else "--"
self.ui.lcdVoltage.display(f"{data.voltage:.3f}")
self.ui.lcdCurrent.display(f"{data.current:.3f}")
self.ui.lcdResistence.display(r_text)
self.ui.lcdPower.display(f"{data.power:.3f}")
self.ui.lcdAvgPower.display(f"{data.energy / t:.3f}")
self.ui.lcdEnerge.display(f"{data.energy:.3f}")
self.fps_counter.tick()
def _set_filter_k(self, k):
self.data.filter_k = k
def _set_data_fps(self, text):
if text != "":
self.data_fps = int(text.replace("Hz", ""))
self.graph_fps = min(self.data_fps, self.graph_max_fps)
if self.state_request_sender_timer.isActive():
self.state_request_sender_timer.stop()
self.state_request_sender_timer.start(int(1000 / self.data_fps))
if self.draw_graph_timer.isActive():
self.draw_graph_timer.stop()
self.draw_graph_timer.start(int(1000 / self.graph_fps))
self.fps_counter.clear()
def _set_graph_max_fps(self, fps):
self.graph_max_fps = fps
self._set_data_fps(self.ui.comboDataFps.currentText())
def _set_data_length(self, length):
save = self.data.save_datas_flag
filter_k = self.data.filter_k
self.data = Data_Share(length)
self.curve1.setData(x=[], y=[])
self.curve2.setData(x=[], y=[])
self.data.save_datas_flag = save
self.data.filter_k = filter_k
@QtCore.pyqtSlot()
def on_btnRecordClear_clicked(self):
with self.data.sync_lock:
self.data.start_time = time.perf_counter()
self.data.last_time = 0
self.data.energy = 0
def update_progressbar(self):
v_value = round(self.data.voltage / self.v_set * 1000) if self.v_set != 0 else 0
i_value = round(self.data.current / self.i_set * 1000) if self.i_set != 0 else 0
self.ui.progressBarVoltage.setValue(v_value)
self.ui.progressBarCurrent.setValue(i_value)
self.ui.progressBarVoltage.update()
self.ui.progressBarCurrent.update()
@QtCore.pyqtSlot()
def on_spinBoxVoltage_editingFinished(self):
v_set = self.ui.spinBoxVoltage.value()
self.v_set = v_set
@QtCore.pyqtSlot()
def on_spinBoxCurrent_editingFinished(self):
i_set = self.ui.spinBoxCurrent.value()
self.i_set = i_set
def _voltage_changed(self, value):
if not self.ui.checkBoxQuickset.isChecked():
return
self.v_set = value
def _current_changed(self, value):
if not self.ui.checkBoxQuickset.isChecked():
return
self.i_set = value
########## 图像绘制 ##########
def initGraph(self):
self.ui.widgetGraph1.setBackground(None)
self.ui.widgetGraph2.setBackground(None)
self.ui.widgetGraph1.setLabel("left", "电压", units="V")
self.ui.widgetGraph2.setLabel("left", "电流", units="A")
self._graph_units_dict = {"电压": "V", "电流": "A", "功率": "W", "阻抗": "Ω"}
self.ui.widgetGraph1.showGrid(x=True, y=True)
self.ui.widgetGraph2.showGrid(x=True, y=True)
self.ui.widgetGraph1.setMouseEnabled(x=False, y=False)
self.ui.widgetGraph2.setMouseEnabled(x=False, y=False)
self.pen1 = pg.mkPen(color="salmon", width=1)
self.pen2 = pg.mkPen(color="turquoise", width=1)
self.curve1 = self.ui.widgetGraph1.plot(pen=self.pen1, clear=True)
self.curve2 = self.ui.widgetGraph2.plot(pen=self.pen2, clear=True)
self.data.graph_start_time = time.perf_counter()
self.data.save_datas_flag = True
self._graph_auto_scale_flag = True
self.ui.widgetGraph1.setAxisItems(
axisItems={"left": FmtAxisItem(orientation="left")}
)
self.ui.widgetGraph2.setAxisItems(
axisItems={"left": FmtAxisItem(orientation="left")}
)
self._set_graph1_data("电压")
self._set_graph2_data("电流")
def _get_data(self, text):
if text == "电压":
return self.data.voltages[self.data.update_count :]
elif text == "电流":
return self.data.currents[self.data.update_count :]
elif text == "功率":
return self.data.powers[self.data.update_count :]
elif text == "阻抗":
return self.data.resistances[self.data.update_count :]
elif text == "无":
return None
_typename_dict = {
"电压": "V",
"电流": "I",
"功率": "P",
"阻抗": "R",
}
def float_str(self, value, limit=1e5):
if value > limit:
return f"{value:.1e}"
else:
return f"{value:.3f}"
def draw_graph(self):
self.update_progressbar()
self.ui.labelFps.setText(f"{self.fps_counter.fps:.1f}Hz")
if self.graph_keep_flag:
return
type1 = self.ui.comboGraph1Data.currentText()
type2 = self.ui.comboGraph2Data.currentText()
data1 = self._get_data(type1)
data2 = self._get_data(type2)
time = self.data.times[self.data.update_count :]
text1 = None
text2 = None
if data1 is not None and data1.size > 0:
self.curve1.setData(x=time, y=data1)
avg1 = np.mean(data1)
max1 = np.max(data1)
min1 = np.min(data1)
pp1 = max1 - min1
_ = self._typename_dict[type1]
text1 = f"{_}avg: {self.float_str(avg1)} {_}max: {self.float_str(max1)} {_}min: {self.float_str(min1)} {_}pp: {self.float_str(pp1)}"
if data2 is not None and data2.size > 0:
self.curve2.setData(x=time, y=data2)
avg2 = np.mean(data2)
max2 = np.max(data2)
min2 = np.min(data2)
pp2 = max2 - min2
_ = self._typename_dict[type2]
text2 = f"{_}avg: {self.float_str(avg2)} {_}max: {self.float_str(max2)} {_}min: {self.float_str(min2)} {_}pp: {self.float_str(pp2)}"
if text1 and text2:
text = text1 + " | " + text2
elif text1:
text = text1
elif text2:
text = text2
else:
text = "No Info"
self.ui.labelGraphInfo.setText(text)
if time.size != 0 and self._graph_auto_scale_flag:
if data1 is not None:
max1 = np.max(data1)
min1 = np.min(data1)
if max1 != np.inf and min1 != -np.inf:
add1 = max(0.02, (max1 - min1) * 0.05)
self.ui.widgetGraph1.setYRange(min1 - add1, max1 + add1)
self.ui.widgetGraph1.setXRange(time[0], time[-1])
if data2 is not None:
max2 = np.max(data2)
min2 = np.min(data2)
if max2 != np.inf and min2 != -np.inf:
add2 = max(0.02, (max2 - min2) * 0.05)
self.ui.widgetGraph2.setYRange(min2 - add2, max2 + add2)
self.ui.widgetGraph2.setXRange(time[0], time[-1])
def _set_graph1_data(self, text):
if text == "无":
self.ui.widgetGraph1.hide()
return
self.ui.widgetGraph1.show()
self.ui.widgetGraph1.setLabel("left", text, units=self._graph_units_dict[text])
def _set_graph2_data(self, text):
if text == "无":
self.ui.widgetGraph2.hide()
return
self.ui.widgetGraph2.show()
self.ui.widgetGraph2.setLabel("left", text, units=self._graph_units_dict[text])
@QtCore.pyqtSlot()
def on_btnGraphClear_clicked(self):
with self.data.sync_lock:
self.data.save_datas_flag = False
self.data.voltages = np.zeros_like(self.data.voltages)
self.data.currents = np.zeros_like(self.data.currents)
self.data.powers = np.zeros_like(self.data.powers)
self.data.resistances = np.zeros_like(self.data.resistances)
self.data.times = np.zeros_like(self.data.times)
self.data.update_count = self.data.data_length
self.data.graph_start_time = time.perf_counter()
self.data.save_datas_flag = True
self.curve1.setData(x=[], y=[])
self.curve2.setData(x=[], y=[])
@QtCore.pyqtSlot()
def on_btnGraphKeep_clicked(self):
self.graph_keep_flag = not self.graph_keep_flag
if self.graph_keep_flag:
self.ui.btnGraphKeep.setText("解除")
else:
self.ui.btnGraphKeep.setText("保持")
mouse_enabled = self.graph_keep_flag or (not self._graph_auto_scale_flag)
self.ui.widgetGraph1.setMouseEnabled(x=mouse_enabled, y=mouse_enabled)
self.ui.widgetGraph2.setMouseEnabled(x=mouse_enabled, y=mouse_enabled)
@QtCore.pyqtSlot()
def on_btnGraphAutoScale_clicked(self):
self._graph_auto_scale_flag = not self._graph_auto_scale_flag
if self._graph_auto_scale_flag:
self.ui.btnGraphAutoScale.setText("适应")
else:
self.ui.btnGraphAutoScale.setText("手动")
mouse_enabled = self.graph_keep_flag or (not self._graph_auto_scale_flag)
self.ui.widgetGraph1.setMouseEnabled(x=mouse_enabled, y=mouse_enabled)
self.ui.widgetGraph2.setMouseEnabled(x=mouse_enabled, y=mouse_enabled)
@QtCore.pyqtSlot()
def on_btnGraphRecord_clicked(self):
self.graph_record_flag = not self.graph_record_flag
if self.graph_record_flag:
self.graph_record_data = Data_Record()
time_str = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime())
self.graph_record_filename = f"./record_{time_str}.csv"
self.ui.btnGraphRecord.setText("停止")
self.graph_record_save_timer.start(5000)
else:
self.graph_record_save_timer.stop()
self.graph_record_data.to_csv(self.graph_record_filename)
self.graph_record_data = Data_Record()
msg_box = QtWidgets.QMessageBox()
msg_box.setWindowTitle("录制完成")
msg_box.setText(f"数据已保存至:{self.graph_record_filename[2:]}")
msg_box.exec_()
self.ui.btnGraphRecord.setText("录制")
def _graph_record_save(self):
if self.graph_record_flag:
self.graph_record_data.to_csv(self.graph_record_filename)
else:
self.graph_record_save_timer.stop()
######### 辅助功能-预设组 #########
def _check_edit_presets(self):
if (
self.ui.comboPresetEdit.currentText() == self.ui.comboPreset.currentText()
or self.ui.comboPresetEdit.currentText() == "0"
):
self.ui.btnPresetSave.setText("无法修改")
self.ui.btnPresetSave.setEnabled(False)
else:
self.ui.btnPresetSave.setText("保存")
self.ui.btnPresetSave.setEnabled(True)
def _set_preset(self, text):
if self._ignore_preset_changed_signal:
self._ignore_preset_changed_signal = False
return
preset = int(text)
if preset == 0:
return
get = api.get_preset(preset)
now_state = self.output_state
api.set_output(False)
api.use_preset(preset)
self._v_set = get["v_set"]
self._i_set = get["i_set"]
api.set_output(
preset=preset, output=now_state, v_set=self.v_set, i_set=self.i_set
)
self.ui.spinBoxVoltage.setValue(self.v_set)
self.ui.spinBoxCurrent.setValue(self.i_set)
self._check_edit_presets()
@QtCore.pyqtSlot()
def on_btnPresetSave_clicked(self):
preset = int(self.ui.comboPresetEdit.currentText())
v_set = self.ui.spinBoxPresetVoltage.value()
i_set = self.ui.spinBoxPresetCurrent.value()
ovp = self.ui.spinBoxPresetOvp.value()
ocp = self.ui.spinBoxPresetOcp.value()
try:
api.set_preset(preset, v_set, i_set, ovp, ocp)
self.ui.btnPresetSave.setText("保存成功")
except:
self.ui.btnPresetSave.setText("保存失败")
QtCore.QTimer.singleShot(1000, lambda: self.ui.btnPresetSave.setText("保存"))
def _get_preset(self, text):
preset = int(text)
get = api.get_preset(preset)
self.ui.spinBoxPresetVoltage.setValue(get["v_set"])
self.ui.spinBoxPresetCurrent.setValue(get["i_set"])
self.ui.spinBoxPresetOvp.setValue(get["ovp"])
self.ui.spinBoxPresetOcp.setValue(get["ocp"])
self._check_edit_presets()
######### 辅助功能-参数扫描 #########
@QtCore.pyqtSlot()
def on_btnSweep_clicked(self):
if self.func_sweep_timer.isActive():
self.stop_func_sweep()
else:
self._sweep_target = self.ui.comboSweepTarget.currentText()
self._sweep_start = self.ui.spinBoxSweepStart.value()
self._sweep_stop = self.ui.spinBoxSweepStop.value()
self._sweep_step = self.ui.spinBoxSweepStep.value()
self._sweep_delay = self.ui.spinBoxSweepDelay.value()
try:
assert self._sweep_step > 0
assert self._sweep_start != self._sweep_stop
assert self._sweep_delay > 0
except:
self.ui.btnSweep.setText("非法参数")
QtCore.QTimer.singleShot(
1000, lambda: self.ui.btnSweep.setText("功能已关闭")
)
return
self._sweep_temp = None
self.func_sweep_timer.start(int(self._sweep_delay * 1000))
self.ui.btnSweep.setText("功能已开启")
if self._sweep_target == "电压":
self.ui.spinBoxVoltage.setEnabled(False)
elif self._sweep_target == "电流":
self.ui.spinBoxCurrent.setEnabled(False)
self.ui.scrollAreaSweep.setEnabled(False)
if not self.output_state:
self.v_set = self._sweep_start
self.on_btnOutput_clicked()
def stop_func_sweep(self):
self.func_sweep_timer.stop()
self.ui.btnSweep.setText("功能已关闭")
if self._sweep_target == "电压":
self.ui.spinBoxVoltage.setEnabled(True)
elif self._sweep_target == "电流":
self.ui.spinBoxCurrent.setEnabled(True)
self.ui.scrollAreaSweep.setEnabled(True)
def _func_sweep(self):
if self._sweep_temp is None:
self._sweep_temp = self._sweep_start
else:
if self._sweep_start <= self._sweep_stop:
self._sweep_temp += self._sweep_step
else:
self._sweep_temp -= self._sweep_step
if (
self._sweep_start > self._sweep_stop
and self._sweep_temp <= self._sweep_stop
) or (
self._sweep_start <= self._sweep_stop
and self._sweep_temp >= self._sweep_stop
):
self._swep_temp = self._sweep_stop
self.stop_func_sweep()
if self._sweep_target == "电压":
self.v_set = self._sweep_temp
elif self._sweep_target == "电流":
self.i_set = self._sweep_temp
######### 辅助功能-发生器 #########
@QtCore.pyqtSlot()
def on_btnWaveGen_clicked(self):
if self.func_wave_gen_timer.isActive():
self.stop_func_wave_gen()
else:
self._wavegen_type = self.ui.comboWaveGenType.currentText()
self._wavegen_period = self.ui.spinBoxWaveGenPeriod.value()
self._wavegen_highlevel = self.ui.spinBoxWaveGenHigh.value()
self._wavegen_lowlevel = self.ui.spinBoxWaveGenLow.value()
self._wavegen_loopfreq = self.ui.spinBoxWaveGenLoopFreq.value()
try:
assert self._wavegen_highlevel > self._wavegen_lowlevel
assert self._wavegen_period > 0
assert self._wavegen_loopfreq > 0
except:
self.ui.btnWaveGen.setText("非法参数")
QtCore.QTimer.singleShot(
1000, lambda: self.ui.btnWaveGen.setText("功能已关闭")
)
return
self._wavegen_start_time = time.perf_counter()
self.func_wave_gen_timer.start(int(1000 / self._wavegen_loopfreq))
self.ui.btnWaveGen.setText("功能已开启")
self.ui.spinBoxWaveGenLoopFreq.setEnabled(False)
self.ui.spinBoxVoltage.setEnabled(False)
if not self.output_state:
self.v_set = self._wavegen_lowlevel
self.on_btnOutput_clicked()
def stop_func_wave_gen(self):
self.func_wave_gen_timer.stop()
self.ui.btnWaveGen.setText("功能已关闭")
self.ui.spinBoxWaveGenLoopFreq.setEnabled(True)
self.ui.spinBoxVoltage.setEnabled(True)
def _set_wavegen_type(self, _):
self._wavegen_type = self.ui.comboWaveGenType.currentText()
@QtCore.pyqtSlot()
def on_spinBoxWaveGenPeriod_editingFinished(self):
self._wavegen_period = self.ui.spinBoxWaveGenPeriod.value()
@QtCore.pyqtSlot()
def on_spinBoxWaveGenHigh_editingFinished(self):
self._wavegen_highlevel = self.ui.spinBoxWaveGenHigh.value()
@QtCore.pyqtSlot()
def on_spinBoxWaveGenLow_editingFinished(self):
self._wavegen_lowlevel = self.ui.spinBoxWaveGenLow.value()
def _func_wave_gen(self):
t = time.perf_counter() - self._wavegen_start_time
if self._wavegen_type == "正弦波":
voltage = (
self._wavegen_lowlevel
+ (self._wavegen_highlevel - self._wavegen_lowlevel)
* (math.sin(2 * math.pi / self._wavegen_period * t) + 1.0)
/ 2
)
elif self._wavegen_type == "方波":
voltage = (
self._wavegen_highlevel
if math.sin(2 * math.pi / self._wavegen_period * t) > 0
else self._wavegen_lowlevel
)
elif self._wavegen_type == "三角波":
mul = (t / self._wavegen_period) % 2
mul = mul if mul < 1 else 2 - mul
voltage = (
self._wavegen_lowlevel
+ (self._wavegen_highlevel - self._wavegen_lowlevel) * mul
)
elif self._wavegen_type == "锯齿波":
voltage = (self._wavegen_highlevel - self._wavegen_lowlevel) * (
(t / self._wavegen_period) % 1
) + self._wavegen_lowlevel
elif self._wavegen_type == "噪音":
voltage = random.uniform(self._wavegen_lowlevel, self._wavegen_highlevel)
else:
voltage = 0
voltage = max(
min(voltage, self._wavegen_highlevel), self._wavegen_lowlevel
) # 限幅
self.v_set = voltage
######### 辅助功能-功率保持 #########
@QtCore.pyqtSlot()
def on_btnKeepPower_clicked(self):
if self.func_keep_power_timer.isActive():
self.stop_func_keep_power()
else:
self._keep_power_target = self.ui.spinBoxKeepPowerSet.value()
self._keep_power_loopfreq = self.ui.spinBoxKeepPowerLoopFreq.value()
self._keep_power_pid_i = self.ui.spinBoxKeepPowerPi.value()
self._keep_power_pid_max_v = self.ui.spinBoxKeepPowerMaxV.value()
try:
assert self._keep_power_loopfreq > 0
assert self._keep_power_pid_i > 0
except:
self.ui.btnKeepPower.setText("非法参数")
QtCore.QTimer.singleShot(
1000, lambda: self.ui.btnKeepPower.setText("功能已关闭")
)
return
self._keep_power_pid = PID(
0,
self._keep_power_pid_i,
0,
setpoint=self._keep_power_target,
auto_mode=False,
)
self._keep_power_pid.output_limits = (0, self._keep_power_pid_max_v)
self._keep_power_pid.set_auto_mode(True, last_output=self.v_set)
self.func_keep_power_timer.start(int(1000 / self._keep_power_loopfreq))
self.ui.btnKeepPower.setText("功能已开启")
self.ui.spinBoxVoltage.setEnabled(False)
self.ui.spinBoxKeepPowerLoopFreq.setEnabled(False)
def stop_func_keep_power(self):
self.func_keep_power_timer.stop()
self.ui.btnKeepPower.setText("功能已关闭")
self.ui.spinBoxVoltage.setEnabled(True)
self.ui.spinBoxKeepPowerLoopFreq.setEnabled(True)
def _func_keep_power(self):
if not self.output_state:
if self._keep_power_pid.auto_mode:
self._keep_power_pid.set_auto_mode(False)
voltage = 0
else:
if not self._keep_power_pid.auto_mode:
self._keep_power_pid.set_auto_mode(True, last_output=self.v_set)
voltage = self._keep_power_pid(self.data.power)
self.v_set = voltage
@QtCore.pyqtSlot()
def on_spinBoxKeepPowerSet_editingFinished(self):
self._keep_power_target = self.ui.spinBoxKeepPowerSet.value()
if self.func_keep_power_timer.isActive():
self._keep_power_pid.setpoint = self._keep_power_target
@QtCore.pyqtSlot()
def on_spinBoxKeepPowerPi_editingFinished(self):
self._keep_power_pid_i = self.ui.spinBoxKeepPowerPi.value()
if self.func_keep_power_timer.isActive():
self._keep_power_pid.tunings = (0, self._keep_power_pid_i, 0)
@QtCore.pyqtSlot()
def on_spinBoxKeepPowerMaxV_editingFinished(self):
self._keep_power_pid_max_v = self.ui.spinBoxKeepPowerMaxV.value()
if self.func_keep_power_timer.isActive():
self._keep_power_pid.output_limits = (0, self._keep_power_pid_max_v)
######### 辅助功能-序列 #########
def _seq_btn_disable(self):
self.ui.btnSeqSave.hide()
self.ui.btnSeqLoad.hide()
self.ui.btnSeqSingle.hide()
self.ui.btnSeqLoop.hide()
self.ui.btnSeqDelay.hide()
self.ui.btnSeqWaitTime.hide()
self.ui.btnSeqVoltage.hide()
self.ui.btnSeqCurrent.hide()
self.ui.listSeq.setEnabled(False)
self.ui.btnSeqStop.show()
def _seq_btn_enable(self):
self.ui.btnSeqSave.show()
self.ui.btnSeqLoad.show()
self.ui.btnSeqSingle.show()
self.ui.btnSeqLoop.show()
self.ui.btnSeqDelay.show()
self.ui.btnSeqWaitTime.show()
self.ui.btnSeqVoltage.show()
self.ui.btnSeqCurrent.show()
self.ui.listSeq.setEnabled(True)
self.ui.btnSeqStop.hide()
@QtCore.pyqtSlot()
def on_btnSeqSingle_clicked(self):
cnt = self.ui.listSeq.count()
if cnt == 0:
return
self._seq_btn_disable()
self._start_seq(loop=False)
if not self.output_state:
self.ui.btnOutput.click()
@QtCore.pyqtSlot()
def on_btnSeqLoop_clicked(self):
cnt = self.ui.listSeq.count()
if cnt == 0:
return
self._seq_btn_disable()
self._start_seq(loop=True)
if not self.output_state:
self.ui.btnOutput.click()
@QtCore.pyqtSlot()
def on_btnSeqStop_clicked(self):
self.func_seq_timer.stop()
self._seq_btn_enable()
# listSeq 删除
def _seq_del_item(self):
row = self.ui.listSeq.currentRow()
cnt = self.ui.listSeq.count()
if cnt == 0:
return
if row == -1:
row = cnt - 1
self.ui.listSeq.takeItem(row)
self.ui.listSeq.setCurrentRow(max(row - 1, 0))
def _seq_edit_item(self):
row = self.ui.listSeq.currentRow()
cnt = self.ui.listSeq.count()
if cnt == 0:
return
if row == -1:
return
item = self.ui.listSeq.item(row)
text = item.text()
text, ok = QtWidgets.QInputDialog.getText(
self, "编辑动作", "请确保修改后动作文本格式正确,否则无法识别动作", text=text
)
if not ok:
return
item.setText(text)
def _seq_clear_all(self):
ok = QtWidgets.QMessageBox.question(
self,
"清空序列",
"确定要清空序列吗?",
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
QtWidgets.QMessageBox.No,
)
if ok == QtWidgets.QMessageBox.Yes:
self.ui.listSeq.clear()
# listSeq 右键菜单 (listSeq)
@QtCore.pyqtSlot(QtCore.QPoint)
def on_listSeq_customContextMenuRequested(self, pos):
row = self.ui.listSeq.currentRow()
cnt = self.ui.listSeq.count()
if cnt == 0:
return
if row == -1:
return
menu = QtWidgets.QMenu()
menu.addAction("编辑", lambda: self._seq_edit_item())
menu.addAction("删除", lambda: self._seq_del_item())
menu.addAction("清空", lambda: self._seq_clear_all())
menu.exec_(QtGui.QCursor.pos())
# 双击修改
@QtCore.pyqtSlot(QtWidgets.QListWidgetItem)
def on_listSeq_itemDoubleClicked(self, item):
self._seq_edit_item()
@QtCore.pyqtSlot()
def on_btnSeqDelay_clicked(self):
row = self.ui.listSeq.currentRow()
delay, ok = QtWidgets.QInputDialog.getInt(
self, "输入延时", "请输入延时时间 (ms)", 1000, 0, 100000, 1
)
if not ok:
return
self.ui.listSeq.insertItem(row + 1, f"延时 {delay} ms")
self.ui.listSeq.setCurrentRow(row + 1)
@QtCore.pyqtSlot()
def on_btnSeqWaitTime_clicked(self):
row = self.ui.listSeq.currentRow()
time_now_str = datetime.datetime.now().strftime("%y-%m-%d %H:%M:%S")
wait_time, ok = QtWidgets.QInputDialog.getText(
self,
"输入等待时间",
"请输入等待时间 (格式: 年-月-日 时:分:秒)",
text=time_now_str,
)
if not ok:
return
try:
datetime.datetime.strptime(wait_time, "%y-%m-%d %H:%M:%S")
except ValueError:
QtWidgets.QMessageBox.warning(self, "错误", "时间格式错误")
return
if not ok:
return
self.ui.listSeq.insertItem(row + 1, f"等待 {wait_time}")
self.ui.listSeq.setCurrentRow(row + 1)
@QtCore.pyqtSlot()
def on_btnSeqVoltage_clicked(self):
row = self.ui.listSeq.currentRow()
voltage, ok = QtWidgets.QInputDialog.getDouble(
self, "输入电压", "请输入电压值 (V)", 1, 0, 30, 2
)
if not ok:
return
self.ui.listSeq.insertItem(row + 1, f"电压 {voltage:.2f} V")
self.ui.listSeq.setCurrentRow(row + 1)
@QtCore.pyqtSlot()
def on_btnSeqCurrent_clicked(self):
row = self.ui.listSeq.currentRow()
current, ok = QtWidgets.QInputDialog.getDouble(
self, "输入电流", "请输入电流值 (A)", 1, 0, 5, 3
)
if not ok:
return
self.ui.listSeq.insertItem(row + 1, f"电流 {current:.3f} A")
self.ui.listSeq.setCurrentRow(row + 1)
def _switch_to_seq(self, index) -> bool:
if index > self._seq_cnt:
return False
item = self.ui.listSeq.item(index)
if item is None:
return False
self._seq_index = index
self.ui.listSeq.setCurrentRow(index)
text = item.text()
self._seq_type = text[:2]
if self._seq_type == "等待":
self._seq_value = datetime.datetime.strptime(text[3:], "%y-%m-%d %H:%M:%S")
else:
self._seq_value = float(text[3:-2]) # type: ignore
if self._seq_type in ("延时", "等待") or self._seq_index == 0:
self._seq_time = time.perf_counter()
return True
def _start_seq(self, loop=False):
self._seq_loop = loop
self._seq_index = 0
self._seq_cnt = self.ui.listSeq.count()
self._switch_to_seq(0)
self.func_seq_timer.start(1)
def _func_seq(self):
now = time.perf_counter()
if self._seq_type == "延时":
if now - self._seq_time < self._seq_value / 1000:
return
elif self._seq_type == "等待":
now = datetime.datetime.now()
if now < self._seq_value:
return
elif self._seq_type == "电压":
self.v_set = self._seq_value
elif self._seq_type == "电流":
self.i_set = self._seq_value
else:
raise ValueError("Unknown seq type")
if not self._switch_to_seq(self._seq_index + 1):
if self._seq_loop:
self._switch_to_seq(0)
else:
self.func_seq_timer.stop()
self._seq_btn_enable()
@QtCore.pyqtSlot()
def on_btnSeqSave_clicked(self):
if self.ui.listSeq.count() == 0:
return
# 保存到文件
filename, _ = QtWidgets.QFileDialog.getSaveFileName(
self, "保存", "", "文本文件 (*.txt)"
)
if filename == "" or filename is None:
return
lines = []
for i in range(self.ui.listSeq.count()):
lines.append(self.ui.listSeq.item(i).text())
with open(filename, "w", encoding="utf-8") as f:
f.write("\n".join(lines))
@QtCore.pyqtSlot()
def on_btnSeqLoad_clicked(self):
# 从文件加载
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
self, "打开", "", "文本文件 (*.txt)"
)
if filename == "" or filename is None:
return
with open(filename, "r", encoding="utf-8") as f:
lines = f.read().strip().split("\n")
self.ui.listSeq.clear()
for line in lines:
try:
_ = line.split(" ")
assert len(_) == 3
assert _[0] in ["延时", "电压", "电流", "等待"]
if _[0] != "等待":
assert _[2] in ["ms", "V", "A"]
float(_[1])
self.ui.listSeq.addItem(line)
except:
QtWidgets.QMessageBox.warning(self, "错误", f"数据验证错误: {line}")
return
MainWindow = DP100GUI()
class DP100Settings(QtWidgets.QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_DialogSettings()
self.ui.setupUi(self)
self.api_lock = QtCore.QMutex()
api._api_lock = QtCore.QMutexLocker(self.api_lock)
def initValues(self):
settings = api.get_settings()
self.ui.spinBoxBacklight.setValue(settings["backlight"])
self.ui.spinBoxVolume.setValue(settings["volume"])
self.ui.spinBoxOtp.setValue(settings["otp"])
self.ui.spinBoxOpp.setValue(settings["opp"])
self.ui.checkBoxRevProtect.setChecked(settings["reverse_protect"])
self.ui.checkBoxAuto.setChecked(settings["auto_output"])
def show(self) -> None:
if not api.connected:
QtWidgets.QMessageBox.warning(self, "错误", "未连接设备")
return
self.initValues()
return super().show()
@QtCore.pyqtSlot()
def on_btnSave_clicked(self):
settings = (
int(self.ui.spinBoxBacklight.value()),
int(self.ui.spinBoxVolume.value()),
self.ui.spinBoxOpp.value(),
int(self.ui.spinBoxOtp.value()),
bool(self.ui.checkBoxRevProtect.isChecked()),
bool(self.ui.checkBoxAuto.isChecked()),
)
api.set_settings(*settings)
self.ui.btnSave.setText("保存成功")
QtCore.QTimer.singleShot(1000, self._reset_btn_text)
def _reset_btn_text(self):
self.ui.btnSave.setText("保存")
class DP100Graphics(QtWidgets.QDialog):
set_max_fps_sig = QtCore.pyqtSignal(float)
set_data_len_sig = QtCore.pyqtSignal(int)
set_filter_k_sig = QtCore.pyqtSignal(float)
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_DialogGraphics()
self.ui.setupUi(self)
if not OPENGL_AVAILABLE:
self.ui.checkBoxOpenGL.setEnabled(False)
# connect signals
self.ui.radioDark.clicked.connect(lambda: self.set_theme("dark"))
self.ui.radioLight.clicked.connect(lambda: self.set_theme("light"))
self.ui.radioAuto.clicked.connect(lambda: self.set_theme("auto"))
self.ui.checkBoxOpenGL.clicked.connect(self.set_opengl)
self.ui.comboFilterK.currentTextChanged.connect(self.set_filter)
def set_theme(self, theme):
# app.setStyleSheet(qdarktheme.load_stylesheet(theme))
qdarktheme.setup_theme(theme)
MainWindow.ui.widgetGraph1.setBackground(None)
MainWindow.ui.widgetGraph2.setBackground(None)
MainWindow.CustomTitleBar.set_theme(theme)
def set_opengl(self, enable):
pg.setConfigOption("useOpenGL", enable)
logger.info(f"OpenGL {'enabled' if enable else 'disabled'}")
def on_spinMaxFps_editingFinished(self):
self.set_max_fps_sig.emit(self.ui.spinMaxFps.value())
def on_spinDataLength_editingFinished(self):
self.set_data_len_sig.emit(self.ui.spinDataLength.value())
# def on_spinFilterK_editingFinished(self):
# self.set_filter_k_sig.emit(self.ui.spinFilterK.value())
def set_filter(self, _=None) -> None:
text = self.ui.comboFilterK.currentText()
if text == "无":
self.set_filter_k_sig.emit(1)
elif text == "低":
self.set_filter_k_sig.emit(0.25)
elif text == "中":
self.set_filter_k_sig.emit(0.1)
elif text == "高":
self.set_filter_k_sig.emit(0.01)
elif text == "极高":
self.set_filter_k_sig.emit(0.001)
def _init_spin(self, length, fps):
self.ui.spinDataLength.setValue(length)
self.ui.spinMaxFps.setValue(fps)
DialogSettings = DP100Settings()
DialogGraphics = DP100Graphics()
DialogGraphics._init_spin(MainWindow.data.data_length, MainWindow.graph_max_fps)
MainWindow.ui.btnSettings.clicked.connect(DialogSettings.show)
MainWindow.ui.btnGraphics.clicked.connect(DialogGraphics.show)
DialogGraphics.set_max_fps_sig.connect(MainWindow._set_graph_max_fps)
DialogGraphics.set_data_len_sig.connect(MainWindow._set_data_length)
DialogGraphics.set_filter_k_sig.connect(MainWindow._set_filter_k)
# app.setStyleSheet(qdarktheme.load_stylesheet())
app.setWindowIcon(QtGui.QIcon(ICON_PATH))
qdarktheme.setup_theme()
def show_app():
MainWindow.show()
sys.exit(app.exec_())
if __name__ == "__main__":
show_app()
Python
1
https://gitee.com/Ellu_IFX/DP100-PyQt5-GUI.git
git@gitee.com:Ellu_IFX/DP100-PyQt5-GUI.git
Ellu_IFX
DP100-PyQt5-GUI
DP100-PyQt5-GUI
master

搜索帮助