细节优化
parent
a0417d080c
commit
44c582487e
|
|
@ -0,0 +1,63 @@
|
||||||
|
{
|
||||||
|
"canvas": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"w": 1920.0,
|
||||||
|
"h": 1080.0
|
||||||
|
},
|
||||||
|
"widgets": [
|
||||||
|
{
|
||||||
|
"widget_type": "label",
|
||||||
|
"x": 173.0,
|
||||||
|
"y": 210.0,
|
||||||
|
"w": 162.0,
|
||||||
|
"h": 62.0,
|
||||||
|
"z": 1.0,
|
||||||
|
"config": {
|
||||||
|
"fieldName": "主轴承#3",
|
||||||
|
"prefix": "主轴承温度",
|
||||||
|
"suffix": " ℃",
|
||||||
|
"fontSize": 16,
|
||||||
|
"color": "#FFFFFF"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widget_type": "label",
|
||||||
|
"x": 46.0,
|
||||||
|
"y": 378.0,
|
||||||
|
"w": 162.0,
|
||||||
|
"h": 62.0,
|
||||||
|
"z": 1.0,
|
||||||
|
"config": {
|
||||||
|
"fieldName": "减速箱小轴承2",
|
||||||
|
"prefix": "减速箱小轴承温度",
|
||||||
|
"suffix": "℃",
|
||||||
|
"fontSize": 16,
|
||||||
|
"color": "#FFFFFF"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widget_type": "image",
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"w": 650.0,
|
||||||
|
"h": 865.0,
|
||||||
|
"z": 0.0,
|
||||||
|
"config": {
|
||||||
|
"imagePath": "D:/1-2.JPG"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widget_type": "web",
|
||||||
|
"x": 648.5,
|
||||||
|
"y": 0.0,
|
||||||
|
"w": 887.0,
|
||||||
|
"h": 863.0,
|
||||||
|
"z": 0.0,
|
||||||
|
"config": {
|
||||||
|
"url": "http://127.0.0.1:8086/orgs/b2542eeb72a3e614/dashboards/0f8ab8a328fe9000?lower=now%28%29+-+1h",
|
||||||
|
"locked": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -4,5 +4,5 @@
|
||||||
"org": "MEASCON",
|
"org": "MEASCON",
|
||||||
"bucket": "PCM",
|
"bucket": "PCM",
|
||||||
"interval_ms": 1000,
|
"interval_ms": 1000,
|
||||||
"query": "from(bucket: \"PCM\")\n |> range(start: -3h)\n |> filter(fn: (r) => r._measurement == \"PCM_Measurement\")\n |> filter(fn: (r) => r.data_type == \"LSDAQ\")\n |> keep(columns: [\"_time\", \"_field\", \"_value\"])\n |> last()"
|
"query": "from(bucket: \"PCM\")\n |> range(start: -24h)\n |> filter(fn: (r) => r._measurement == \"PCM_Measurement\")\n |> filter(fn: (r) => r.data_type == \"LSDAQ\")\n |> keep(columns: [\"_time\", \"_field\", \"_value\"])\n |> last()"
|
||||||
}
|
}
|
||||||
129
main.py
129
main.py
|
|
@ -201,6 +201,25 @@ class DashboardItem(QGraphicsRectItem):
|
||||||
super().paint(painter, option, widget)
|
super().paint(painter, option, widget)
|
||||||
|
|
||||||
def to_state(self) -> WidgetState:
|
def to_state(self) -> WidgetState:
|
||||||
|
"""将组件状态转换为 WidgetState,使用精确的 pos() 和 rect(),而不是 sceneBoundingRect()"""
|
||||||
|
pos = self.pos()
|
||||||
|
r = self.rect()
|
||||||
|
return WidgetState(
|
||||||
|
widget_type=self._get_widget_type(),
|
||||||
|
x=float(pos.x()),
|
||||||
|
y=float(pos.y()),
|
||||||
|
w=float(r.width()),
|
||||||
|
h=float(r.height()),
|
||||||
|
z=float(self.zValue()),
|
||||||
|
config=self._get_config(),
|
||||||
|
)
|
||||||
|
|
||||||
|
def _get_widget_type(self) -> str:
|
||||||
|
"""子类需要重写,返回组件类型"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def _get_config(self) -> Dict[str, Any]:
|
||||||
|
"""子类需要重写,返回配置字典"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def apply_state(self, state: WidgetState):
|
def apply_state(self, state: WidgetState):
|
||||||
|
|
@ -387,17 +406,11 @@ class ImageItem(DashboardItem):
|
||||||
)
|
)
|
||||||
self._pixmap_item.setScale(scale)
|
self._pixmap_item.setScale(scale)
|
||||||
|
|
||||||
def to_state(self) -> WidgetState:
|
def _get_widget_type(self) -> str:
|
||||||
r = self.sceneBoundingRect()
|
return "image"
|
||||||
return WidgetState(
|
|
||||||
widget_type="image",
|
def _get_config(self) -> Dict[str, Any]:
|
||||||
x=r.x(),
|
return {"imagePath": self._image_path}
|
||||||
y=r.y(),
|
|
||||||
w=r.width(),
|
|
||||||
h=r.height(),
|
|
||||||
z=float(self.zValue()),
|
|
||||||
config={"imagePath": self._image_path},
|
|
||||||
)
|
|
||||||
|
|
||||||
def apply_state(self, state: WidgetState):
|
def apply_state(self, state: WidgetState):
|
||||||
super().apply_state(state)
|
super().apply_state(state)
|
||||||
|
|
@ -484,17 +497,11 @@ class LabelItem(DashboardItem):
|
||||||
if self._field_name and self._field_name in data:
|
if self._field_name and self._field_name in data:
|
||||||
self._update_preview_text(data[self._field_name])
|
self._update_preview_text(data[self._field_name])
|
||||||
|
|
||||||
def to_state(self) -> WidgetState:
|
def _get_widget_type(self) -> str:
|
||||||
r = self.sceneBoundingRect()
|
return "label"
|
||||||
return WidgetState(
|
|
||||||
widget_type="label",
|
def _get_config(self) -> Dict[str, Any]:
|
||||||
x=r.x(),
|
return self.label_config()
|
||||||
y=r.y(),
|
|
||||||
w=r.width(),
|
|
||||||
h=r.height(),
|
|
||||||
z=float(self.zValue()),
|
|
||||||
config=self.label_config(),
|
|
||||||
)
|
|
||||||
|
|
||||||
def apply_state(self, state: WidgetState):
|
def apply_state(self, state: WidgetState):
|
||||||
super().apply_state(state)
|
super().apply_state(state)
|
||||||
|
|
@ -558,20 +565,14 @@ class WebItem(DashboardItem):
|
||||||
def is_locked(self) -> bool:
|
def is_locked(self) -> bool:
|
||||||
return self._locked
|
return self._locked
|
||||||
|
|
||||||
def to_state(self) -> WidgetState:
|
def _get_widget_type(self) -> str:
|
||||||
r = self.sceneBoundingRect()
|
return "web"
|
||||||
return WidgetState(
|
|
||||||
widget_type="web",
|
def _get_config(self) -> Dict[str, Any]:
|
||||||
x=r.x(),
|
return {
|
||||||
y=r.y(),
|
"url": self._url,
|
||||||
w=r.width(),
|
"locked": self._locked,
|
||||||
h=r.height(),
|
}
|
||||||
z=float(self.zValue()),
|
|
||||||
config={
|
|
||||||
"url": self._url,
|
|
||||||
"locked": self._locked,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
def apply_state(self, state: WidgetState):
|
def apply_state(self, state: WidgetState):
|
||||||
super().apply_state(state)
|
super().apply_state(state)
|
||||||
|
|
@ -715,9 +716,35 @@ class DashboardView(QGraphicsView):
|
||||||
# 布局持久化
|
# 布局持久化
|
||||||
def save_layout(self, path: str):
|
def save_layout(self, path: str):
|
||||||
states = []
|
states = []
|
||||||
|
canvas_bounds = self._scene.canvas_rect()
|
||||||
|
canvas_pos = self._scene.canvas_item.pos()
|
||||||
|
canvas_left = canvas_pos.x()
|
||||||
|
canvas_top = canvas_pos.y()
|
||||||
|
canvas_right = canvas_left + canvas_bounds.width()
|
||||||
|
canvas_bottom = canvas_top + canvas_bounds.height()
|
||||||
|
|
||||||
for it in self._scene.items():
|
for it in self._scene.items():
|
||||||
if isinstance(it, DashboardItem):
|
if isinstance(it, DashboardItem):
|
||||||
states.append(asdict(it.to_state()))
|
# 获取组件状态
|
||||||
|
state = it.to_state()
|
||||||
|
state_dict = asdict(state)
|
||||||
|
|
||||||
|
# 修正超出边界的位置数据(直接修改字典,不移动组件)
|
||||||
|
item_left = state_dict["x"]
|
||||||
|
item_top = state_dict["y"]
|
||||||
|
item_w = state_dict["w"]
|
||||||
|
item_h = state_dict["h"]
|
||||||
|
|
||||||
|
# 修正超出边界的位置数据
|
||||||
|
final_x = max(canvas_left, min(item_left, canvas_right - item_w))
|
||||||
|
final_y = max(canvas_top, min(item_top, canvas_bottom - item_h))
|
||||||
|
|
||||||
|
# 更新状态数据
|
||||||
|
state_dict["x"] = final_x
|
||||||
|
state_dict["y"] = final_y
|
||||||
|
|
||||||
|
states.append(state_dict)
|
||||||
|
|
||||||
with open(path, "w", encoding="utf-8") as f:
|
with open(path, "w", encoding="utf-8") as f:
|
||||||
payload = {
|
payload = {
|
||||||
"canvas": self._scene.canvas_state(),
|
"canvas": self._scene.canvas_state(),
|
||||||
|
|
@ -769,6 +796,28 @@ class DashboardView(QGraphicsView):
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
it.apply_state(ws)
|
it.apply_state(ws)
|
||||||
|
|
||||||
|
# 加载后也应用边界限制,确保组件不超出画布
|
||||||
|
canvas_bounds = self._scene.canvas_rect()
|
||||||
|
canvas_pos = self._scene.canvas_item.pos()
|
||||||
|
canvas_left = canvas_pos.x()
|
||||||
|
canvas_top = canvas_pos.y()
|
||||||
|
canvas_right = canvas_left + canvas_bounds.width()
|
||||||
|
canvas_bottom = canvas_top + canvas_bounds.height()
|
||||||
|
|
||||||
|
pos = it.pos()
|
||||||
|
r = it.rect()
|
||||||
|
item_left = pos.x()
|
||||||
|
item_top = pos.y()
|
||||||
|
item_right = item_left + r.width()
|
||||||
|
item_bottom = item_top + r.height()
|
||||||
|
|
||||||
|
# 修正超出边界的位置
|
||||||
|
final_x = max(canvas_left, min(item_left, canvas_right - r.width()))
|
||||||
|
final_y = max(canvas_top, min(item_top, canvas_bottom - r.height()))
|
||||||
|
|
||||||
|
if final_x != item_left or final_y != item_top:
|
||||||
|
it.setPos(final_x, final_y)
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------
|
# -----------------------------
|
||||||
|
|
@ -1106,6 +1155,8 @@ class MainWindow(QMainWindow):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.setWindowTitle("PCM Viewer - Widgets Dashboard")
|
self.setWindowTitle("PCM Viewer - Widgets Dashboard")
|
||||||
self.resize(1400, 840)
|
self.resize(1400, 840)
|
||||||
|
# 设置焦点策略,确保能够接收键盘事件(特别是 ESC 键)
|
||||||
|
self.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
||||||
self._edit_mode = True
|
self._edit_mode = True
|
||||||
# 全屏编辑标志(展示模式本身也会全屏)
|
# 全屏编辑标志(展示模式本身也会全屏)
|
||||||
self._fullscreen_edit = False
|
self._fullscreen_edit = False
|
||||||
|
|
@ -1219,12 +1270,16 @@ class MainWindow(QMainWindow):
|
||||||
if want_full:
|
if want_full:
|
||||||
# 真全屏:使用 Qt 的 showFullScreen,退出时用 showMaximized 恢复普通 Windows 窗口
|
# 真全屏:使用 Qt 的 showFullScreen,退出时用 showMaximized 恢复普通 Windows 窗口
|
||||||
self.showFullScreen()
|
self.showFullScreen()
|
||||||
|
# 全屏后确保窗口获得焦点,以便接收键盘事件(ESC 键)
|
||||||
|
self.setFocus()
|
||||||
# 全屏时关闭滚动条,避免 1920x1080 屏幕上还出现滚动条
|
# 全屏时关闭滚动条,避免 1920x1080 屏幕上还出现滚动条
|
||||||
self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
||||||
self.view.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
self.view.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
||||||
else:
|
else:
|
||||||
# 恢复为标准的最大化窗口(带边框/任务栏)
|
# 恢复为标准的最大化窗口(带边框/任务栏)
|
||||||
self.showMaximized()
|
self.showMaximized()
|
||||||
|
# 恢复焦点,确保能够接收键盘事件
|
||||||
|
self.setFocus()
|
||||||
self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
||||||
self.view.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
self.view.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue