Skip to content

Commit 693ae34

Browse files
committed
浮窗优化
1 parent f8d9b97 commit 693ae34

4 files changed

Lines changed: 176 additions & 27 deletions

File tree

CHANGELOG/v2.3.0-beta.2/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ v2.3 - Shiroko (砂狼白子) beta 2
1111
- 优化 **ClassIsland 联动**,现在可以传递通知类型,并提醒用户安装插件。
1212
- 优化 **计时器**,阻止外部关闭窗口
1313
- 优化 **浮窗**,阻止外部关闭窗口
14+
- 优化 **浮窗**,启动即自动收纳
15+
- 优化 **浮窗**,切换同步收纳显示
16+
- 优化 **计时器**,倒计时页面居中显示,秒表居中与所有时钟字距优化
1417

1518
## 🐛 修复问题
1619

app/common/notification/notification_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1031,7 +1031,7 @@ def _normalize_text(value):
10311031
draw_count,
10321032
settings,
10331033
settings_group,
1034-
is_animating
1034+
is_animating,
10351035
)
10361036
if status:
10371037
logger.info("成功发送通知到ClassIsland,结果未知")

app/view/another_window/countdown_timer.py

Lines changed: 96 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -576,9 +576,11 @@ def _build_left_panel(self):
576576
outer_layout = QVBoxLayout(self.left_container)
577577
outer_layout.setContentsMargins(0, 0, 0, 0)
578578
outer_layout.setSpacing(0)
579+
self._left_outer_layout = outer_layout
579580

580581
center_widget = QWidget(self.left_container)
581582
center_widget.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
583+
self._left_center_widget = center_widget
582584
ring_layer = QGridLayout(center_widget)
583585
ring_layer.setContentsMargins(0, 0, 0, 0)
584586
ring_layer.setSpacing(0)
@@ -590,7 +592,8 @@ def _build_left_panel(self):
590592
ring_layer.addWidget(self.digit_panel, 0, 0, 1, 1)
591593

592594
outer_layout.addStretch(1)
593-
outer_layout.addWidget(center_widget, 0, Qt.AlignCenter)
595+
outer_layout.addWidget(center_widget, 0)
596+
outer_layout.setAlignment(center_widget, Qt.AlignHCenter | Qt.AlignVCenter)
594597
outer_layout.addStretch(1)
595598

596599
def _build_digit_panel(self, parent_widget=None):
@@ -634,7 +637,7 @@ def _build_digit_panel(self, parent_widget=None):
634637

635638
digits_row = QHBoxLayout()
636639
digits_row.setContentsMargins(0, 0, 0, 0)
637-
digits_row.setSpacing(4)
640+
digits_row.setSpacing(0)
638641
digits_row.setAlignment(Qt.AlignCenter)
639642

640643
minus_row = QHBoxLayout()
@@ -679,6 +682,13 @@ def _build_digit_panel(self, parent_widget=None):
679682
self._ms_minus_placeholder.setVisible(False)
680683
minus_row.addWidget(self._ms_minus_placeholder)
681684

685+
for row in (plus_row, digits_row, minus_row):
686+
row.insertStretch(0, 1)
687+
row.addStretch(1)
688+
self._digit_plus_row_layout = plus_row
689+
self._digit_digits_row_layout = digits_row
690+
self._digit_minus_row_layout = minus_row
691+
682692
digit_v.addLayout(plus_row)
683693
digit_v.addLayout(digits_row)
684694
digit_v.addLayout(minus_row)
@@ -757,7 +767,7 @@ def _build_controls_panel(self):
757767
onClick=lambda: self._set_preset_category("recent"),
758768
)
759769
self.preset_segment.setCurrentItem("common")
760-
preset_panel_layout.addWidget(self.preset_segment, 0, Qt.AlignCenter)
770+
preset_panel_layout.addWidget(self.preset_segment, 0, Qt.AlignLeft)
761771

762772
self._common_presets = [
763773
_Preset("05:00", 5 * 60),
@@ -785,7 +795,7 @@ def _build_controls_panel(self):
785795
preset_panel_layout.addLayout(self.preset_grid)
786796
self._sync_preset_buttons()
787797

788-
controls_layout.addWidget(self.preset_panel, 0, Qt.AlignTop)
798+
controls_layout.addWidget(self.preset_panel, 0, Qt.AlignTop | Qt.AlignLeft)
789799
self._build_stopwatch_panel(controls_layout)
790800
controls_layout.addStretch(1)
791801

@@ -1209,25 +1219,42 @@ def _apply_time_font(self, mode: str):
12091219
int(digit_metrics.horizontalAdvance("0")),
12101220
int(digit_metrics.horizontalAdvance("8")),
12111221
)
1212-
+ 8
1222+
+ 4
12131223
)
12141224

12151225
sample_colon_font = QFont(self._font_family, int(colon_size))
12161226
sample_colon_font.setBold(True)
12171227
colon_metrics = QFontMetrics(sample_colon_font)
1218-
colon_width = int(colon_metrics.horizontalAdvance(":")) + 6
1228+
colon_width = int(colon_metrics.horizontalAdvance(":")) + 2
12191229

12201230
sample_ms_font = QFont(self._font_family, int(ms_size))
12211231
sample_ms_font.setBold(True)
12221232
ms_metrics = QFontMetrics(sample_ms_font)
1223-
ms_width = int(ms_metrics.horizontalAdvance(".000")) + 10
1233+
ms_width = int(ms_metrics.horizontalAdvance(".000")) + 2
12241234
else:
12251235
digit_size = 50
1226-
digit_width = 42
12271236
colon_size = 42
12281237
ms_size = 32
1229-
ms_width = 84
1230-
colon_width = 14
1238+
sample_digit_font = QFont(self._font_family, int(digit_size))
1239+
sample_digit_font.setBold(True)
1240+
digit_metrics = QFontMetrics(sample_digit_font)
1241+
digit_width = (
1242+
max(
1243+
int(digit_metrics.horizontalAdvance("0")),
1244+
int(digit_metrics.horizontalAdvance("8")),
1245+
)
1246+
+ 4
1247+
)
1248+
1249+
sample_colon_font = QFont(self._font_family, int(colon_size))
1250+
sample_colon_font.setBold(True)
1251+
colon_metrics = QFontMetrics(sample_colon_font)
1252+
colon_width = int(colon_metrics.horizontalAdvance(":")) + 2
1253+
1254+
sample_ms_font = QFont(self._font_family, int(ms_size))
1255+
sample_ms_font.setBold(True)
1256+
ms_metrics = QFontMetrics(sample_ms_font)
1257+
ms_width = int(ms_metrics.horizontalAdvance(".000")) + 2
12311258
date_size = 18 if mode == "clock" else 16
12321259

12331260
for lab in self._digit_labels:
@@ -1381,6 +1408,7 @@ def _sync_controls_state(self):
13811408
or force_compact_by_width
13821409
)
13831410
self._set_compact_view(desired_compact)
1411+
13841412
if not is_mini:
13851413
self.left_container.setSizePolicy(
13861414
QSizePolicy.Minimum, QSizePolicy.Expanding
@@ -1482,21 +1510,68 @@ def _sync_controls_state(self):
14821510
and self._center_between_spacer is not None
14831511
and self._center_right_spacer is not None
14841512
):
1513+
digit_rows = [
1514+
getattr(self, "_digit_plus_row_layout", None),
1515+
getattr(self, "_digit_digits_row_layout", None),
1516+
getattr(self, "_digit_minus_row_layout", None),
1517+
]
1518+
for row in digit_rows:
1519+
if row is not None and row.count() >= 2:
1520+
row.setStretch(0, 1)
1521+
row.setStretch(row.count() - 1, 1)
1522+
1523+
base_margin = 20 if w and (w.isFullScreen() or w.isMaximized()) else 0
1524+
between_w = 0
1525+
if not is_mini and not desired_compact:
1526+
if mode == "clock":
1527+
between_w = 0
1528+
elif window_width > 550:
1529+
between_w = 20
1530+
else:
1531+
between_w = 0
1532+
1533+
extra_left = 0
1534+
if not is_mini:
1535+
if (
1536+
mode == "countdown"
1537+
and getattr(self, "preset_panel", None) is not None
1538+
and self.preset_panel.isVisible()
1539+
and getattr(self, "right_container", None) is not None
1540+
and self.right_container.isVisible()
1541+
):
1542+
extra_left = between_w + max(
1543+
0, int(self.right_container.sizeHint().width())
1544+
)
1545+
elif (
1546+
mode == "stopwatch"
1547+
and getattr(self, "right_container", None) is not None
1548+
and self.right_container.isVisible()
1549+
):
1550+
extra_left = between_w + max(
1551+
0, int(self.right_container.sizeHint().width())
1552+
)
1553+
1554+
try:
1555+
cap = max(
1556+
0,
1557+
int(window_width)
1558+
- max(0, int(self.left_container.sizeHint().width()))
1559+
- 10,
1560+
)
1561+
extra_left = min(int(extra_left), int(cap))
1562+
except Exception:
1563+
extra_left = int(extra_left)
1564+
14851565
self._center_left_spacer.changeSize(
1486-
0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum
1566+
int(base_margin) + int(extra_left),
1567+
0,
1568+
QSizePolicy.Expanding,
1569+
QSizePolicy.Minimum,
14871570
)
14881571
self._center_right_spacer.changeSize(
1489-
0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum
1572+
int(base_margin), 0, QSizePolicy.Expanding, QSizePolicy.Minimum
14901573
)
14911574

1492-
if w and (w.isFullScreen() or w.isMaximized()):
1493-
self._center_left_spacer.changeSize(
1494-
20, 0, QSizePolicy.Expanding, QSizePolicy.Minimum
1495-
)
1496-
self._center_right_spacer.changeSize(
1497-
20, 0, QSizePolicy.Expanding, QSizePolicy.Minimum
1498-
)
1499-
15001575
if not is_mini and not desired_compact:
15011576
# For clock mode the right panel is hidden; keep the center
15021577
# spacer fixed so the left clock container stays centered.
@@ -1506,7 +1581,7 @@ def _sync_controls_state(self):
15061581
)
15071582
elif window_width > 550:
15081583
self._center_between_spacer.changeSize(
1509-
20, 0, QSizePolicy.MinimumExpanding, QSizePolicy.Minimum
1584+
20, 0, QSizePolicy.Fixed, QSizePolicy.Minimum
15101585
)
15111586
else:
15121587
self._center_between_spacer.changeSize(

app/view/floating_window/levitation.py

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,18 +89,20 @@ def __init__(self, parent=None):
8989
# ==================== 构建UI ====================
9090
self._build_ui()
9191
self._apply_position()
92-
self._apply_window()
93-
self._install_drag_filters()
9492

9593
# ==================== 信号连接 ====================
9694
self._connect_signals()
9795

9896
# ==================== 主题应用 ====================
9997
self._apply_theme_style()
10098

99+
self._apply_window()
100+
self._install_drag_filters()
101+
101102
# ==================== 启动周期性置顶 ====================
102103
self._start_periodic_topmost()
103-
self._startup_initial_show = False
104+
if not bool(getattr(self, "_visible_on_start", False)):
105+
QTimer.singleShot(0, lambda: self._check_edge_proximity(immediate=True))
104106

105107
# ==================== 初始化方法 ====================
106108

@@ -1010,9 +1012,20 @@ def toggle_user_requested_visible(self) -> None:
10101012

10111013
def set_user_requested_visible(self, visible: bool) -> None:
10121014
self._user_requested_visible = bool(visible)
1015+
storage = getattr(self, "storage_window", None)
10131016
if self._user_requested_visible:
10141017
super().show()
1018+
if bool(getattr(self, "_retracted", False)) and storage is not None:
1019+
try:
1020+
storage.show()
1021+
except Exception:
1022+
pass
10151023
else:
1024+
if storage is not None and bool(storage.isVisible()):
1025+
try:
1026+
storage.hide()
1027+
except Exception:
1028+
pass
10161029
super().hide()
10171030

10181031
def _apply_size_setting(self, size_idx: int):
@@ -1129,7 +1142,17 @@ def showEvent(self, event):
11291142
super().showEvent(event)
11301143
if not bool(getattr(self, "_suppress_visibility_tracking", False)):
11311144
self._user_requested_visible = True
1132-
QTimer.singleShot(100, self._check_edge_proximity)
1145+
if bool(getattr(self, "_retracted", False)):
1146+
storage = getattr(self, "storage_window", None)
1147+
if storage is not None and not bool(storage.isVisible()):
1148+
try:
1149+
storage.show()
1150+
except Exception:
1151+
pass
1152+
if bool(getattr(self, "_startup_initial_show", False)):
1153+
self._check_edge_proximity(immediate=True)
1154+
else:
1155+
QTimer.singleShot(100, self._check_edge_proximity)
11331156
if bool(getattr(self, "_startup_initial_show", False)):
11341157
self._startup_initial_show = False
11351158
self._schedule_auto_hide(force=False)
@@ -1144,6 +1167,12 @@ def hideEvent(self, event):
11441167
super().hideEvent(event)
11451168
if not bool(getattr(self, "_suppress_visibility_tracking", False)):
11461169
self._user_requested_visible = False
1170+
storage = getattr(self, "storage_window", None)
1171+
if storage is not None and bool(storage.isVisible()):
1172+
try:
1173+
storage.hide()
1174+
except Exception:
1175+
pass
11471176
self._apply_topmost_runtime()
11481177

11491178
def closeEvent(self, event):
@@ -2093,7 +2122,7 @@ def _expand_from_edge(self):
20932122
self._retracted = False
20942123
# logger.debug(f"_expand_from_edge: 窗口位置已展开到 ({self.x()}, {self.y()})")
20952124

2096-
def _check_edge_proximity(self):
2125+
def _check_edge_proximity(self, immediate: bool = False):
20972126
"""检测窗口是否靠近屏幕边缘,并实现贴边隐藏功能(带动画效果)"""
20982127
# logger.debug("开始检查边缘贴边隐藏功能")
20992128

@@ -2129,6 +2158,27 @@ def _check_edge_proximity(self):
21292158
if not hasattr(self, "_original_position"):
21302159
self._original_position = window_pos
21312160

2161+
if bool(immediate):
2162+
end_rect = QRect(
2163+
screen.left() - window_width + 1,
2164+
window_pos.y(),
2165+
window_width,
2166+
window_height,
2167+
)
2168+
try:
2169+
self.setGeometry(end_rect)
2170+
except Exception:
2171+
pass
2172+
self._create_arrow_button(
2173+
"right",
2174+
0,
2175+
window_pos.y()
2176+
+ window_height // 2
2177+
- self._storage_btn_size.height() // 2,
2178+
)
2179+
self._retracted = True
2180+
return
2181+
21322182
# 创建平滑动画效果
21332183
self.animation = QPropertyAnimation(self, b"geometry")
21342184
# 设置动画持续时间(更流畅的过渡)
@@ -2175,6 +2225,27 @@ def on_animation_finished():
21752225
if not hasattr(self, "_original_position"):
21762226
self._original_position = window_pos
21772227

2228+
if bool(immediate):
2229+
end_rect = QRect(
2230+
screen.right() - 1,
2231+
window_pos.y(),
2232+
window_width,
2233+
window_height,
2234+
)
2235+
try:
2236+
self.setGeometry(end_rect)
2237+
except Exception:
2238+
pass
2239+
self._create_arrow_button(
2240+
"left",
2241+
screen.width() - self._storage_btn_size.width(),
2242+
window_pos.y()
2243+
+ window_height // 2
2244+
- self._storage_btn_size.height() // 2,
2245+
)
2246+
self._retracted = True
2247+
return
2248+
21782249
# 创建平滑动画效果
21792250
self.animation = QPropertyAnimation(self, b"geometry")
21802251
# 设置动画持续时间(更流畅的过渡)

0 commit comments

Comments
 (0)