Skip to content

Commit a60b0d8

Browse files
committed
修复 浮窗通知闪烁,修复更新标签时导致的闪烁问题
1 parent 1e819af commit a60b0d8

2 files changed

Lines changed: 93 additions & 39 deletions

File tree

CHANGELOG/v2.2.0/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ v2.0 - Koharu(小鸟游星野) release 3
2929
- 修复 **收纳浮窗无焦点**,修复无焦点模式未生效
3030
- 修复 **自动播放动画**,修复次数不准确导致的卡顿问题
3131
- 修复 **手动停止动画**,修复动画闪几下后停止的问题
32+
- 修复 **浮窗通知闪烁**,修复更新标签时导致的闪烁问题
3233

3334
## 🔧 其它变更
3435

app/common/notification/notification_service.py

Lines changed: 92 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,48 @@ def __init__(self, parent=None):
2222
self.layout.setContentsMargins(15, 15, 15, 15)
2323
self.layout.setSpacing(10)
2424
self.content_widgets = []
25+
self.cached_widgets = []
2526

2627
def update_content(self, widgets):
27-
"""更新内容控件"""
28-
# 清除现有内容
29-
for widget in self.content_widgets:
28+
"""更新内容控件(优化版,复用控件避免闪烁)"""
29+
if not widgets:
30+
return
31+
32+
min_count = min(len(widgets), len(self.cached_widgets))
33+
34+
for i in range(min_count):
35+
old_widget = self.cached_widgets[i]
36+
new_widget = widgets[i]
37+
38+
if old_widget and new_widget:
39+
old_layout = old_widget.layout()
40+
new_layout = new_widget.layout()
41+
42+
if old_layout and new_layout:
43+
for j in range(min(old_layout.count(), new_layout.count())):
44+
old_item = old_layout.itemAt(j)
45+
new_item = new_layout.itemAt(j)
46+
47+
if old_item and new_item:
48+
old_label = old_item.widget()
49+
new_label = new_item.widget()
50+
51+
if old_label and new_label:
52+
old_label.setText(new_label.text())
53+
old_label.setStyleSheet(new_label.styleSheet())
54+
55+
for i in range(min_count, len(widgets)):
56+
self.layout.addWidget(widgets[i])
57+
self.content_widgets.append(widgets[i])
58+
59+
for i in range(min_count, len(self.cached_widgets)):
60+
widget = self.cached_widgets[i]
3061
self.layout.removeWidget(widget)
3162
widget.deleteLater()
32-
self.content_widgets.clear()
63+
if widget in self.content_widgets:
64+
self.content_widgets.remove(widget)
3365

34-
# 添加新内容
35-
for widget in widgets:
36-
self.layout.addWidget(widget)
37-
self.content_widgets.append(widget)
66+
self.cached_widgets = widgets
3867

3968
# 确保新添加的 BodyLabel 可见:根据主题强制设置前景色
4069
try:
@@ -45,14 +74,11 @@ def update_content(self, widgets):
4574
fg = "#ffffff" if is_dark_theme(qconfig) else "#000000"
4675

4776
def apply_fg_to(w):
48-
# 如果是直接的 BodyLabel,设置样式
4977
if isinstance(w, QFBodyLabel):
5078
existing = w.styleSheet() or ""
5179
if "color:" not in existing:
52-
# 保留已有样式,追加颜色
5380
w.setStyleSheet(existing + f" color: {fg};")
5481
else:
55-
# 遍历子控件查找 BodyLabel
5682
for child in w.findChildren(QFBodyLabel):
5783
existing = child.styleSheet() or ""
5884
if "color:" not in existing:
@@ -64,7 +90,6 @@ def apply_fg_to(w):
6490
except Exception as e:
6591
logger.exception("应用前景色到内容控件时出错: {}", e)
6692
except Exception:
67-
# 忽略主题检测错误,保持原样
6893
pass
6994

7095

@@ -133,6 +158,9 @@ def __init__(self, parent=None):
133158
# 关闭动画
134159
self.hide_animation = None
135160

161+
# 缓存的标签,用于复用
162+
self.cached_student_labels = []
163+
136164
# 启动周期性置顶
137165
self._start_periodic_topmost()
138166

@@ -758,7 +786,7 @@ def update_content(
758786
font_settings_group=None,
759787
settings_group=None,
760788
):
761-
"""更新通知窗口的内容
789+
"""更新通知窗口的内容(优化版,复用控件避免闪烁)
762790
763791
Args:
764792
student_labels: 包含学生信息的BodyLabel控件列表
@@ -778,34 +806,59 @@ def update_content(
778806
elif font_settings_group == "lottery_settings":
779807
self.settings_group = "lottery_notification_settings"
780808

781-
# 清除现有内容
782-
while self.content_layout.count():
783-
item = self.content_layout.takeAt(0)
784-
widget = item.widget()
785-
if widget:
786-
widget.deleteLater()
787-
788-
# 添加新内容
789-
if student_labels:
790-
for label in student_labels:
791-
# 如果有字体设置,则应用到标签上
792-
if font_settings_group:
793-
# 检查是否使用全局字体
794-
use_global_font = readme_settings_async(
795-
font_settings_group, "use_global_font"
809+
if not student_labels:
810+
return
811+
812+
min_count = min(len(student_labels), len(self.cached_student_labels))
813+
814+
for i in range(min_count):
815+
old_widget = self.cached_student_labels[i]
816+
new_widget = student_labels[i]
817+
818+
if old_widget and new_widget:
819+
old_layout = old_widget.layout()
820+
new_layout = new_widget.layout()
821+
822+
if old_layout and new_layout:
823+
for j in range(min(old_layout.count(), new_layout.count())):
824+
old_item = old_layout.itemAt(j)
825+
new_item = new_layout.itemAt(j)
826+
827+
if old_item and new_item:
828+
old_label = old_item.widget()
829+
new_label = new_item.widget()
830+
831+
if old_label and new_label:
832+
old_label.setText(new_label.text())
833+
old_label.setStyleSheet(new_label.styleSheet())
834+
835+
for i in range(min_count, len(student_labels)):
836+
label = student_labels[i]
837+
# 如果有字体设置,则应用到标签上
838+
if font_settings_group:
839+
# 检查是否使用全局字体
840+
use_global_font = readme_settings_async(
841+
font_settings_group, "use_global_font"
842+
)
843+
custom_font = None
844+
if use_global_font == 1: # 不使用全局字体,使用自定义字体
845+
custom_font = readme_settings_async(
846+
font_settings_group, "custom_font"
796847
)
797-
custom_font = None
798-
if use_global_font == 1: # 不使用全局字体,使用自定义字体
799-
custom_font = readme_settings_async(
800-
font_settings_group, "custom_font"
848+
if custom_font and hasattr(label, "setStyleSheet"):
849+
# 获取当前样式表并添加字体设置
850+
current_style = label.styleSheet()
851+
label.setStyleSheet(
852+
f"font-family: '{custom_font}'; {current_style}"
801853
)
802-
if custom_font and hasattr(label, "setStyleSheet"):
803-
# 获取当前样式表并添加字体设置
804-
current_style = label.styleSheet()
805-
label.setStyleSheet(
806-
f"font-family: '{custom_font}'; {current_style}"
807-
)
808-
self.content_layout.addWidget(label)
854+
self.content_layout.addWidget(label)
855+
856+
for i in range(min_count, len(self.cached_student_labels)):
857+
widget = self.cached_student_labels[i]
858+
self.content_layout.removeWidget(widget)
859+
widget.deleteLater()
860+
861+
self.cached_student_labels = student_labels
809862

810863
# 确保颜色与当前主题同步
811864
try:

0 commit comments

Comments
 (0)