重构移动utils文件夹
This commit is contained in:
609
app/views/panels/custom_template_panel.py
Normal file
609
app/views/panels/custom_template_panel.py
Normal file
@@ -0,0 +1,609 @@
|
||||
"""自定义模板结果面板(Step 6 重构)。"""
|
||||
|
||||
import threading
|
||||
import time
|
||||
from tkinter import messagebox
|
||||
import tkinter as tk
|
||||
import ttkbootstrap as ttk
|
||||
|
||||
import colour
|
||||
import numpy as np
|
||||
|
||||
from app.data_range_converter import convert_pattern_params
|
||||
|
||||
def create_custom_template_result_panel(self):
|
||||
"""创建客户模板结果显示区域(黑底表格)"""
|
||||
self.custom_result_frame = ttk.LabelFrame(
|
||||
self.custom_template_tab_frame, text="客户模板结果显示"
|
||||
)
|
||||
self.custom_result_frame.pack(
|
||||
side=tk.TOP, fill=tk.BOTH, expand=True, padx=5, pady=5
|
||||
)
|
||||
|
||||
table_container = tk.Frame(
|
||||
self.custom_result_frame,
|
||||
bg="#000000",
|
||||
highlightthickness=1,
|
||||
highlightbackground="#5a5a5a",
|
||||
)
|
||||
table_container.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
|
||||
|
||||
style = ttk.Style()
|
||||
style.configure(
|
||||
"CustomResult.Treeview",
|
||||
background="#000000",
|
||||
fieldbackground="#000000",
|
||||
foreground="#ffffff",
|
||||
rowheight=28,
|
||||
borderwidth=0,
|
||||
)
|
||||
style.configure(
|
||||
"CustomResult.Treeview.Heading",
|
||||
background="#2f2f2f",
|
||||
foreground="#f5f5f5",
|
||||
font=("Microsoft YaHei", 10, "bold"),
|
||||
relief="flat",
|
||||
)
|
||||
style.map(
|
||||
"CustomResult.Treeview",
|
||||
background=[("selected", "#1f4e79")],
|
||||
foreground=[("selected", "#ffffff")],
|
||||
)
|
||||
style.map(
|
||||
"CustomResult.Treeview.Heading",
|
||||
background=[("active", "#3b3b3b")],
|
||||
)
|
||||
|
||||
columns = (
|
||||
"Pattern",
|
||||
"No.",
|
||||
"X",
|
||||
"Y",
|
||||
"Z",
|
||||
"x",
|
||||
"y",
|
||||
"Lv",
|
||||
"u'",
|
||||
"v'",
|
||||
"Tcp",
|
||||
"duv",
|
||||
"λd/λc",
|
||||
"Pe"
|
||||
)
|
||||
|
||||
self.custom_result_tree = ttk.Treeview(
|
||||
table_container,
|
||||
columns=columns,
|
||||
show="headings",
|
||||
height=4,
|
||||
style="CustomResult.Treeview",
|
||||
)
|
||||
|
||||
column_widths = {
|
||||
"Pattern": 90,
|
||||
"No.": 60,
|
||||
"X": 80,
|
||||
"Y": 80,
|
||||
"Z": 80,
|
||||
"x": 80,
|
||||
"y": 80,
|
||||
"Lv": 80,
|
||||
"u'": 80,
|
||||
"v'": 80,
|
||||
"Tcp": 90,
|
||||
"duv": 80,
|
||||
"λd/λc": 95,
|
||||
"Pe": 80,
|
||||
}
|
||||
|
||||
for col in columns:
|
||||
self.custom_result_tree.heading(col, text=col)
|
||||
self.custom_result_tree.column(
|
||||
col,
|
||||
width=column_widths.get(col, 80),
|
||||
minwidth=60,
|
||||
anchor=tk.CENTER,
|
||||
stretch=False,
|
||||
)
|
||||
|
||||
y_scroll = ttk.Scrollbar(
|
||||
table_container,
|
||||
orient=tk.VERTICAL,
|
||||
command=self.custom_result_tree.yview,
|
||||
)
|
||||
x_scroll = ttk.Scrollbar(
|
||||
table_container,
|
||||
orient=tk.HORIZONTAL,
|
||||
command=self.custom_result_tree.xview,
|
||||
)
|
||||
|
||||
self.custom_result_tree.configure(
|
||||
yscrollcommand=y_scroll.set,
|
||||
xscrollcommand=x_scroll.set,
|
||||
)
|
||||
|
||||
self.custom_result_tree.grid(row=0, column=0, sticky="nsew")
|
||||
y_scroll.grid(row=0, column=1, sticky="ns")
|
||||
x_scroll.grid(row=1, column=0, sticky="ew")
|
||||
|
||||
# 右键菜单:复制全部数据(Excel 可直接按行列粘贴)
|
||||
self.custom_result_menu = tk.Menu(self.root, tearoff=0)
|
||||
self.custom_result_menu.add_command(
|
||||
label="复制全部数据",
|
||||
command=self.copy_custom_result_table,
|
||||
)
|
||||
self.custom_result_menu.add_command(
|
||||
label="单步测试",
|
||||
command=self.start_custom_row_single_step,
|
||||
)
|
||||
|
||||
# self.custom_result_menu.add_separator()
|
||||
# self.custom_result_menu.add_command(
|
||||
# label="单步测试",
|
||||
# command=self.fill_custom_result_test_data,
|
||||
# )
|
||||
self.custom_result_tree.bind("<Button-3>", self.show_custom_result_context_menu)
|
||||
|
||||
table_container.grid_rowconfigure(0, weight=1)
|
||||
table_container.grid_columnconfigure(0, weight=1)
|
||||
|
||||
|
||||
def show_custom_result_context_menu(self, event):
|
||||
"""显示客户模板结果右键菜单"""
|
||||
if not hasattr(self, "custom_result_tree") or not hasattr(
|
||||
self, "custom_result_menu"
|
||||
):
|
||||
return
|
||||
|
||||
if self.testing:
|
||||
# 测试进行中锁定客户模板结果表,禁止右键菜单。
|
||||
return
|
||||
|
||||
row_id = self.custom_result_tree.identify_row(event.y)
|
||||
if row_id:
|
||||
self.custom_result_tree.selection_set(row_id)
|
||||
self.custom_result_tree.focus(row_id)
|
||||
|
||||
has_rows = len(self.custom_result_tree.get_children()) > 0
|
||||
has_selection = len(self.custom_result_tree.selection()) > 0
|
||||
can_single_step = (
|
||||
has_selection
|
||||
and self.ca is not None
|
||||
and self.ucd is not None
|
||||
and not self.testing
|
||||
)
|
||||
try:
|
||||
self.custom_result_menu.entryconfigure(
|
||||
0,
|
||||
state=("normal" if has_rows else "disabled"),
|
||||
)
|
||||
self.custom_result_menu.entryconfigure(
|
||||
1,
|
||||
state=("normal" if can_single_step else "disabled"),
|
||||
)
|
||||
self.custom_result_menu.tk_popup(event.x_root, event.y_root)
|
||||
finally:
|
||||
self.custom_result_menu.grab_release()
|
||||
|
||||
|
||||
def set_custom_result_table_locked(self, locked):
|
||||
"""锁定/解锁客户模板结果表(测试期间禁选择、禁右键)"""
|
||||
if not hasattr(self, "custom_result_tree"):
|
||||
return
|
||||
|
||||
try:
|
||||
self.custom_result_tree.configure(selectmode=("none" if locked else "browse"))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def start_custom_row_single_step(self):
|
||||
"""单步测试当前选中行:发送该行 pattern 并覆盖该行测量结果"""
|
||||
if not hasattr(self, "custom_result_tree"):
|
||||
return
|
||||
|
||||
if self.ca is None or self.ucd is None:
|
||||
messagebox.showerror("错误", "请先连接CA410和信号发生器")
|
||||
return
|
||||
|
||||
if self.testing:
|
||||
messagebox.showinfo("提示", "测试进行中,无法执行单步测试")
|
||||
return
|
||||
|
||||
selected = self.custom_result_tree.selection()
|
||||
if not selected:
|
||||
messagebox.showinfo("提示", "请先选中一行再执行单步测试")
|
||||
return
|
||||
|
||||
item_id = selected[0]
|
||||
values = self.custom_result_tree.item(item_id, "values")
|
||||
if not values:
|
||||
messagebox.showinfo("提示", "选中行没有有效数据")
|
||||
return
|
||||
|
||||
row_no = None
|
||||
if len(values) > 1:
|
||||
try:
|
||||
row_no = int(float(values[1]))
|
||||
except Exception:
|
||||
row_no = None
|
||||
|
||||
if row_no is None or row_no <= 0:
|
||||
children = list(self.custom_result_tree.get_children())
|
||||
row_no = children.index(item_id) + 1 if item_id in children else 1
|
||||
|
||||
self._clear_custom_result_row(item_id, row_no)
|
||||
|
||||
threading.Thread(
|
||||
target=self._run_custom_row_single_step,
|
||||
args=(item_id, row_no),
|
||||
daemon=True,
|
||||
).start()
|
||||
|
||||
|
||||
def _clear_custom_result_row(self, item_id, row_no):
|
||||
"""单步测试开始前清空指定行的测量数据"""
|
||||
if not hasattr(self, "custom_result_tree"):
|
||||
return
|
||||
|
||||
old_values = list(self.custom_result_tree.item(item_id, "values"))
|
||||
pattern_name = old_values[0] if len(old_values) > 0 else f"P {row_no}"
|
||||
|
||||
cleared_values = (
|
||||
pattern_name,
|
||||
row_no,
|
||||
"---",
|
||||
"---",
|
||||
"---",
|
||||
"---",
|
||||
"---",
|
||||
"---",
|
||||
"---",
|
||||
"---",
|
||||
"---",
|
||||
"---",
|
||||
"---",
|
||||
"---",
|
||||
)
|
||||
|
||||
self.custom_result_tree.item(item_id, values=cleared_values)
|
||||
self.custom_result_tree.see(item_id)
|
||||
|
||||
|
||||
def _run_custom_row_single_step(self, item_id, row_no):
|
||||
"""后台执行客户模板单步测试"""
|
||||
try:
|
||||
self.root.after(0, lambda: self.status_var.set(f"单步测试第 {row_no} 行..."))
|
||||
self.log_gui.log(f"开始单步测试第 {row_no} 行")
|
||||
|
||||
self.config.set_current_pattern("custom")
|
||||
|
||||
# 与批量 custom 测试保持一致:根据当前 SDR 配置转换 pattern 数据。
|
||||
import copy
|
||||
|
||||
data_range = self.sdr_data_range_var.get()
|
||||
original_params = copy.deepcopy(self.config.default_pattern_temp["pattern_params"])
|
||||
converted_params = convert_pattern_params(
|
||||
pattern_params=original_params,
|
||||
data_range=data_range,
|
||||
verbose=False,
|
||||
)
|
||||
|
||||
temp_config = self.config.get_temp_config_with_converted_params(
|
||||
mode="custom",
|
||||
converted_params=converted_params,
|
||||
)
|
||||
|
||||
if row_no > len(converted_params):
|
||||
self.log_gui.log(f"❌ 行号超出 pattern 范围: {row_no}/{len(converted_params)}")
|
||||
self.root.after(0, lambda: self.status_var.set("单步测试失败:行号超范围"))
|
||||
return
|
||||
|
||||
self.ucd.set_ucd_params(temp_config)
|
||||
pattern_param = converted_params[row_no - 1]
|
||||
self.ucd.set_pattern(self.ucd.current_pattern, pattern_param)
|
||||
self.ucd.run()
|
||||
|
||||
time.sleep(self.pattern_settle_time)
|
||||
|
||||
# 测量:显示模式1读取 Tcp/duv/Lv,显示模式8读取 λd/Pe/Lv 与 XYZ。
|
||||
self.ca.set_Display(1)
|
||||
tcp, duv, lv, _, _, _ = self.ca.readAllDisplay()
|
||||
|
||||
self.ca.set_Display(8)
|
||||
lambda_d, pe, lv, X, Y, Z = self.ca.readAllDisplay()
|
||||
|
||||
xy = colour.XYZ_to_xy(np.array([X, Y, Z]))
|
||||
u_prime, v_prime, _ = colour.XYZ_to_CIE1976UCS(np.array([X, Y, Z]))
|
||||
|
||||
row_data = {
|
||||
"X": X,
|
||||
"Y": Y,
|
||||
"Z": Z,
|
||||
"x": xy[0],
|
||||
"y": xy[1],
|
||||
"Lv": lv,
|
||||
"u_prime": u_prime,
|
||||
"v_prime": v_prime,
|
||||
"Tcp": tcp,
|
||||
"duv": duv,
|
||||
"lambda_d": lambda_d,
|
||||
"Pe": pe,
|
||||
}
|
||||
|
||||
self.root.after(
|
||||
0,
|
||||
lambda: self._update_custom_result_row(item_id, row_no, row_data),
|
||||
)
|
||||
|
||||
self.log_gui.log(f"✓ 第 {row_no} 行单步测试完成并已覆盖")
|
||||
self.root.after(0, lambda: self.status_var.set(f"第 {row_no} 行单步测试完成"))
|
||||
|
||||
except Exception as e:
|
||||
self.log_gui.log(f"❌ 单步测试失败: {str(e)}")
|
||||
self.root.after(0, lambda: self.status_var.set("单步测试失败"))
|
||||
|
||||
|
||||
def _update_custom_result_row(self, item_id, row_no, result_data):
|
||||
"""覆盖更新客户模板结果表中指定行"""
|
||||
|
||||
def fmt(value, digits=4):
|
||||
if value is None:
|
||||
return "--"
|
||||
if isinstance(value, (int, float, np.floating)):
|
||||
# CA 返回异常哨兵值(如 -99999999)时,显示为占位符。
|
||||
if (not np.isfinite(value)) or value <= -99999998:
|
||||
return "---"
|
||||
return f"{value:.{digits}f}"
|
||||
try:
|
||||
numeric_value = float(value)
|
||||
if (not np.isfinite(numeric_value)) or numeric_value <= -99999998:
|
||||
return "---"
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
return str(value)
|
||||
|
||||
old_values = list(self.custom_result_tree.item(item_id, "values"))
|
||||
pattern_name = old_values[0] if len(old_values) > 0 else f"P {row_no}"
|
||||
|
||||
new_values = (
|
||||
pattern_name,
|
||||
row_no,
|
||||
fmt(result_data.get("X")),
|
||||
fmt(result_data.get("Y")),
|
||||
fmt(result_data.get("Z")),
|
||||
fmt(result_data.get("x")),
|
||||
fmt(result_data.get("y")),
|
||||
fmt(result_data.get("Lv"), 3),
|
||||
fmt(result_data.get("u_prime")),
|
||||
fmt(result_data.get("v_prime")),
|
||||
fmt(result_data.get("Tcp"), 1),
|
||||
fmt(result_data.get("duv"), 5),
|
||||
fmt(result_data.get("lambda_d"), 1),
|
||||
fmt(result_data.get("Pe"), 1),
|
||||
)
|
||||
|
||||
self.custom_result_tree.item(item_id, values=new_values)
|
||||
|
||||
|
||||
def copy_custom_result_table(self):
|
||||
"""复制客户模板结果表格到剪贴板(不含标题行/No./Pattern)"""
|
||||
if not hasattr(self, "custom_result_tree"):
|
||||
return
|
||||
|
||||
items = self.custom_result_tree.get_children()
|
||||
if not items:
|
||||
messagebox.showinfo("提示", "当前没有可复制的数据")
|
||||
return
|
||||
|
||||
lines = []
|
||||
columns = tuple(self.custom_result_tree["columns"])
|
||||
excluded_col_indexes = {
|
||||
idx
|
||||
for idx, col_name in enumerate(columns)
|
||||
if col_name in ("No.", "Pattern")
|
||||
}
|
||||
|
||||
for item in items:
|
||||
values = self.custom_result_tree.item(item, "values")
|
||||
# 跳过 No. 和 Pattern 两列,只保留测量数据列。
|
||||
data_values = [
|
||||
v for idx, v in enumerate(values) if idx not in excluded_col_indexes
|
||||
]
|
||||
row = [
|
||||
str(v).replace("\t", " ").replace("\n", " ")
|
||||
for v in data_values
|
||||
]
|
||||
lines.append("\t".join(row))
|
||||
|
||||
clipboard_text = "\n".join(lines)
|
||||
self.root.clipboard_clear()
|
||||
self.root.clipboard_append(clipboard_text)
|
||||
self.root.update_idletasks()
|
||||
|
||||
if hasattr(self, "status_var"):
|
||||
self.status_var.set(f"已复制 {len(items)} 行客户模板数据到剪贴板")
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(f"✓ 已复制客户模板表格数据({len(items)} 行)")
|
||||
|
||||
|
||||
def fill_custom_result_test_data(self):
|
||||
"""填充 147 行客户模板测试数据(用于界面验证)"""
|
||||
if not hasattr(self, "custom_result_tree"):
|
||||
return
|
||||
|
||||
self.clear_custom_template_results()
|
||||
|
||||
pattern_names = []
|
||||
if hasattr(self, "config") and hasattr(self.config, "get_temp_pattern_names"):
|
||||
pattern_names = self.config.get_temp_pattern_names()
|
||||
|
||||
total_rows = 147
|
||||
for i in range(1, total_rows + 1):
|
||||
ratio = (i - 1) / (total_rows - 1) if total_rows > 1 else 0
|
||||
row_data = {
|
||||
"pattern_name": (
|
||||
pattern_names[i - 1] if i - 1 < len(pattern_names) else f"P {i}"
|
||||
),
|
||||
"X": 0.8 + ratio * 120,
|
||||
"Y": 0.9 + ratio * 135,
|
||||
"Z": 1.1 + ratio * 145,
|
||||
"x": 0.24 + ratio * 0.10,
|
||||
"y": 0.26 + ratio * 0.10,
|
||||
"Lv": 1.0 + ratio * 500,
|
||||
"u_prime": 0.16 + ratio * 0.12,
|
||||
"v_prime": 0.42 + ratio * 0.08,
|
||||
"Tcp": 1800 + ratio * 12000,
|
||||
"duv": -0.01 + ratio * 0.03,
|
||||
"lambda_d": 430 + ratio * 200,
|
||||
"Pe": 10 + ratio * 90,
|
||||
}
|
||||
self.append_custom_template_result(i, row_data)
|
||||
|
||||
if hasattr(self, "chart_notebook") and hasattr(self, "custom_template_tab_frame"):
|
||||
self.chart_notebook.select(self.custom_template_tab_frame)
|
||||
|
||||
if hasattr(self, "status_var"):
|
||||
self.status_var.set("已填充 147 行客户模板测试数据")
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log("✓ 已填充 147 行客户模板测试数据")
|
||||
|
||||
|
||||
def clear_custom_template_results(self):
|
||||
"""清空客户模板结果表格"""
|
||||
if not hasattr(self, "custom_result_tree"):
|
||||
return
|
||||
for item in self.custom_result_tree.get_children():
|
||||
self.custom_result_tree.delete(item)
|
||||
|
||||
|
||||
def auto_expand_custom_result_view(self):
|
||||
"""当客户模板表格有数据时,自动扩展窗口以尽量完整显示所有列"""
|
||||
if not hasattr(self, "custom_result_tree"):
|
||||
return
|
||||
|
||||
if len(self.custom_result_tree.get_children()) == 0:
|
||||
return
|
||||
|
||||
try:
|
||||
self.root.update_idletasks()
|
||||
|
||||
columns = tuple(self.custom_result_tree["columns"])
|
||||
columns_total_width = 0
|
||||
for col in columns:
|
||||
columns_total_width += int(self.custom_result_tree.column(col, "width"))
|
||||
|
||||
left_panel_width = self.left_frame.winfo_width() if hasattr(self, "left_frame") else 180
|
||||
if left_panel_width <= 1:
|
||||
left_panel_width = 180
|
||||
|
||||
# 列宽 + 左侧导航 + 滚动条/边框/外边距。
|
||||
target_width = int(left_panel_width + columns_total_width + 120)
|
||||
|
||||
screen_max_width = max(900, self.root.winfo_screenwidth() - 40)
|
||||
target_width = min(target_width, screen_max_width)
|
||||
|
||||
current_width = self.root.winfo_width()
|
||||
current_height = self.root.winfo_height()
|
||||
|
||||
# 只扩不缩,避免用户窗口被反复改变。
|
||||
if target_width > current_width:
|
||||
self.root.geometry(f"{target_width}x{current_height}")
|
||||
self.root.update_idletasks()
|
||||
except Exception as e:
|
||||
if hasattr(self, "log_gui"):
|
||||
self.log_gui.log(f"⚠️ 自动扩展客户模板窗口失败: {str(e)}")
|
||||
|
||||
|
||||
def append_custom_template_result(self, row_no, result_data):
|
||||
"""追加一条客户模板结果到表格"""
|
||||
|
||||
def fmt(value, digits=4):
|
||||
if value is None:
|
||||
return "--"
|
||||
if isinstance(value, (int, float, np.floating)):
|
||||
# CA 返回异常哨兵值(如 -99999999)时,显示为占位符。
|
||||
if (not np.isfinite(value)) or value <= -99999998:
|
||||
return "---"
|
||||
return f"{value:.{digits}f}"
|
||||
try:
|
||||
numeric_value = float(value)
|
||||
if (not np.isfinite(numeric_value)) or numeric_value <= -99999998:
|
||||
return "---"
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
return str(value)
|
||||
|
||||
row_values = (
|
||||
result_data.get("pattern_name", f"P {row_no}"),
|
||||
row_no,
|
||||
fmt(result_data.get("X")),
|
||||
fmt(result_data.get("Y")),
|
||||
fmt(result_data.get("Z")),
|
||||
fmt(result_data.get("x")),
|
||||
fmt(result_data.get("y")),
|
||||
fmt(result_data.get("Lv"), 3),
|
||||
fmt(result_data.get("u_prime")),
|
||||
fmt(result_data.get("v_prime")),
|
||||
fmt(result_data.get("Tcp"), 1),
|
||||
fmt(result_data.get("duv"), 5),
|
||||
fmt(result_data.get("lambda_d"), 1),
|
||||
fmt(result_data.get("Pe"), 1)
|
||||
)
|
||||
|
||||
if hasattr(self, "custom_result_tree"):
|
||||
item_id = self.custom_result_tree.insert("", tk.END, values=row_values)
|
||||
# 新增数据后自动跳转到最新行。
|
||||
self.custom_result_tree.see(item_id)
|
||||
self.auto_expand_custom_result_view()
|
||||
|
||||
|
||||
def start_custom_template_test(self):
|
||||
"""开始客户模板测试(SDR)"""
|
||||
|
||||
if hasattr(self, "chart_notebook") and hasattr(self, "custom_template_tab_frame"):
|
||||
self.chart_notebook.select(self.custom_template_tab_frame)
|
||||
|
||||
if self.ca is None or self.ucd is None:
|
||||
messagebox.showerror("错误", "请先连接CA410和信号发生器")
|
||||
return
|
||||
|
||||
if self.testing:
|
||||
messagebox.showinfo("提示", "测试已在进行中")
|
||||
return
|
||||
|
||||
if hasattr(self, "debug_container"):
|
||||
self.debug_container.pack_forget()
|
||||
|
||||
self.testing = True
|
||||
self.start_btn.config(state=tk.DISABLED)
|
||||
self.stop_btn.config(state=tk.NORMAL)
|
||||
self.save_btn.config(state=tk.DISABLED)
|
||||
self.clear_config_btn.config(state=tk.DISABLED)
|
||||
self.custom_btn.config(state=tk.DISABLED)
|
||||
self.status_var.set("客户模板测试进行中...")
|
||||
|
||||
self.log_gui.clear_log()
|
||||
self.clear_custom_template_results()
|
||||
|
||||
confirm = messagebox.askyesno(
|
||||
"确认测试", "开始客户模板测试(SDR)?\n\n将采集并显示客户模板格式结果。"
|
||||
)
|
||||
|
||||
if not confirm:
|
||||
self.testing = False
|
||||
self.start_btn.config(state=tk.NORMAL)
|
||||
self.stop_btn.config(state=tk.DISABLED)
|
||||
self.clear_config_btn.config(state=tk.NORMAL)
|
||||
self.custom_btn.config(state=tk.NORMAL)
|
||||
self.status_var.set("测试已取消")
|
||||
self.set_custom_result_table_locked(False)
|
||||
return
|
||||
|
||||
self.set_custom_result_table_locked(True)
|
||||
|
||||
self.test_thread = threading.Thread(target=self.run_custom_sdr_test, args=([],))
|
||||
self.test_thread.daemon = True
|
||||
self.test_thread.start()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user