修正 Studio 力曲线原点、运行不可用提示与禁用按钮样式

FN 轴视图留 8% 余量使 0 刻度与静止曲线离开边框;实时视图在轨道上直接写出运行不可用的原因;禁用按钮改为虚线无填充,复选框加勾,单选框选中不再变方,并放大勾选框、微调框箭头、滚动条与菜单行以便触屏操作。另修 ui_check 桩 worker 签名与英文回放提示。在 Linux 离屏环境对比未改动的 HEAD 验证:studio 失败集合为 HEAD 的子集,ui_check 结果一致。
This commit is contained in:
ykcheungab
2026-10-18 14:39:13 +08:00
parent 7b5ffa74f6
commit 85d0b396e3
9 changed files with 226 additions and 49 deletions
+43 -7
View File
@@ -4,7 +4,7 @@ from __future__ import annotations
import numpy as np
from orisys_app_shared.i18n import t
from orisys_studio.ui.force_plots import ForcePlotsPanel, _nice_ticks
from orisys_studio.ui.force_plots import ForcePlotsPanel, _display_range, _nice_ticks
def _panel(unit: str = "raw") -> ForcePlotsPanel:
@@ -23,6 +23,12 @@ def _ticks(panel: ForcePlotsPanel, channel: int) -> list[float]:
return [float(value) for value, _text in levels[0]]
def _view(panel: ForcePlotsPanel, channel: int) -> tuple[float, float]:
"""The Y range the subplot actually draws."""
low, high = panel.plots[channel].getViewBox().viewRange()[1]
return float(low), float(high)
def _curve(panel: ForcePlotsPanel, channel: int) -> np.ndarray:
_times, values = panel.curves[channel].getData()
return np.asarray(values, dtype=float)
@@ -82,14 +88,15 @@ def test_the_configured_ranges_reach_every_axis(qt_app):
)
panel.set_fixed_newton(True)
# The panel starts in raw, so the raw limits are the ones on the axes.
assert panel.plots[0].getViewBox().viewRange()[1] == [-100000.0, 1000000.0]
assert panel.plots[1].getViewBox().viewRange()[1] == [-500000.0, 500000.0]
# The panel starts in raw, so the raw limits are the ones on the axes (drawn
# with a small margin beyond each bound; see ``_display_range``).
assert _view(panel, 0) == _display_range(-100000.0, 1000000.0)
assert _view(panel, 1) == _display_range(-500000.0, 500000.0)
panel.set_units("N")
assert panel.plots[0].getViewBox().viewRange()[1] == [-5.0, 15.0]
assert panel.plots[1].getViewBox().viewRange()[1] == [-3.0, 3.0]
assert panel.plots[2].getViewBox().viewRange()[1] == [-3.0, 3.0]
assert _view(panel, 0) == _display_range(-5.0, 15.0)
assert _view(panel, 1) == _display_range(-3.0, 3.0)
assert _view(panel, 2) == _display_range(-3.0, 3.0)
assert panel._fixed_y_range(0) == (-5.0, 15.0)
assert panel._fixed_y_range(1) == (-3.0, 3.0)
# A range that starts below zero carries an explicit 0 tick: that is the
@@ -164,3 +171,32 @@ def test_the_default_ranges_are_the_ones_they_always_were(qt_app):
(15.0, "15"),
(20.0, "20"),
]
def test_the_default_fn_origin_is_drawn_off_the_frame(qt_app):
"""FN starts at 0, yet its 0 label and resting curve stay off the plot border.
With the view ending exactly at 0 the label was not drawn and an idle FN
curve lay on the frame shared with FX — the customer's "缺少原点" report.
"""
for unit in ("raw", "N"):
panel = ForcePlotsPanel(theme="dark")
panel.set_units(unit)
panel.set_fixed_newton(True)
ymin, ymax = panel._fixed_y_range(0)
assert ymin == 0.0, "the configured FN floor stays 0"
view_min, view_max = _view(panel, 0)
assert view_min < 0.0 < view_max, unit
assert view_max > ymax, unit
assert 0.0 in _ticks(panel, 0), unit
assert panel.zero_lines[0].isVisibleTo(panel.plots[0].getViewBox()), unit
def test_a_margin_never_brings_an_excluded_zero_into_view():
# A margin that stays on its own side of zero is kept...
assert _display_range(100.0, 1100.0) == (20.0, 1180.0)
# ...one that would cross zero stops at the configured bound.
assert _display_range(10.0, 1010.0) == (10.0, 1090.0)
assert _display_range(-1010.0, -10.0) == (-1090.0, -10.0)
# A range that already holds zero gets the full margin on both sides.
assert _display_range(0.0, 20.0) == (-1.6, 21.6)
+17 -2
View File
@@ -1576,6 +1576,8 @@ def test_live_run_refuses_a_video_source(make_window, monkeypatch):
window._set_source_mode("video")
QApplication.processEvents()
assert not window.toolbar.btn_run.isEnabled(), "Run is offered for a video file in live"
# The reason is on the rail as text, not only in a tooltip (no hover on touch).
assert window.toolbar.run_hint.text() == t("toolbar.run_video_in_replay")
called: list[str] = []
monkeypatch.setattr(
"orisys_app_shared.acquisition.sdk_worker.orisys_importable",
@@ -3138,6 +3140,19 @@ def test_force_threshold_is_on_for_every_sensor_by_default(make_window):
_finish(window, stuck)
def test_the_run_hint_clears_once_run_is_available(make_window):
from PySide6.QtWidgets import QApplication
window = make_window(sensor_type="finger", source_mode="camera")
try:
window.brand_bar.btn_live.click()
QApplication.processEvents()
window._set_source_mode("video")
QApplication.processEvents()
assert window.toolbar.run_hint.text()
window._set_source_mode("camera")
QApplication.processEvents()
assert window.toolbar.btn_run.isEnabled()
assert window.toolbar.run_hint.text() == ""
finally:
window.close()