Kivy实现弹幕式时间滚动显示黑屏问题排查
问题分析与修复方案
核心问题及修复
- 根组件缺失:
DanmakuApp的build方法返回None,Kivy应用必须返回一个Widget作为界面根容器,否则窗口无任何可渲染内容,直接显示黑屏。需创建FloatLayout这类布局作为根组件,所有弹幕都要添加到该布局中。 - 弹幕未加入布局:创建的
Danmaku实例仅存于列表,未添加到根布局的子控件列表,无法被Kivy渲染显示。 - 颜色值超出范围:Kivy中颜色参数要求是0-1之间的浮点数,代码中
(200,255,255)是RGB整数,会被判定为超出范围,导致文字不可见(或完全透明),需转换为浮点数格式。 - 窗口resize事件未绑定:
on_resize方法已定义但未绑定到Window的on_resize事件,窗口大小变化时弹幕不会同步更新。
修改后的完整代码
from kivy.app import App from kivy.uix.label import Label from kivy.uix.floatlayout import FloatLayout from kivy.core.window import Window from kivy.clock import Clock from datetime import datetime class Danmaku(Label): def __init__(self, **kwargs): super(Danmaku, self).__init__(**kwargs) self.x = Window.width # 从屏幕右侧起始 self.y = Window.height // 2 # 垂直居中 self.speed = 100 self.text = datetime.now().strftime("%H:%M") # 转换为0-1区间的浮点数颜色,最后一位为透明度 self.color = (200/255, 255/255, 255/255, 1) self.font_size = int(0.5 * Window.height) self.font_name = "Arial" self.size_hint = (None, None) self.size = self.texture_size def update_text(self): self.text = datetime.now().strftime("%H:%M") self.font_size = int(0.9 * Window.height) self.color = (200/255, 255/255, 255/255, 1) self.size = self.texture_size # 更新尺寸匹配新文本 def shift(self, dt): self.x -= dt * self.speed class DanmakuApp(App): def build(self): self.root_layout = FloatLayout() # 创建根布局容器 self.danmaku_list = [] self.add_new_danmaku() # 添加第一个弹幕 Clock.schedule_interval(self.update, 1.0 / 60.0) # 绑定窗口尺寸变化事件 Window.bind(on_resize=self.on_resize) return self.root_layout # 返回根布局供Kivy渲染 def add_new_danmaku(self): danmaku = Danmaku() self.danmaku_list.append(danmaku) self.root_layout.add_widget(danmaku) # 将弹幕加入布局 def update(self, dt): # 标记需要移除的已移出屏幕的弹幕 to_remove = [] for danmaku in self.danmaku_list: danmaku.shift(dt) # 弹幕完全移出屏幕左侧时标记移除 if danmaku.x < -danmaku.width: to_remove.append(danmaku) # 清理已移出的弹幕,释放资源 for danmaku in to_remove: self.danmaku_list.remove(danmaku) self.root_layout.remove_widget(danmaku) # 当前弹幕移动到屏幕中间位置时,添加新弹幕 if not self.danmaku_list or self.danmaku_list[-1].x < Window.width * 0.5: self.add_new_danmaku() def on_resize(self, window, width, height): for danmaku in self.danmaku_list: danmaku.update_text() danmaku.y = height // 2 # 重置弹幕垂直居中位置 if __name__ == '__main__': DanmakuApp().run()
额外优化说明
- 添加弹幕清理逻辑:移除完全移出屏幕的弹幕,避免内存占用过高。
- 调整新弹幕触发条件,防止短时间内弹幕堆积过多。
- 修复窗口resize时弹幕的垂直位置重置,保证窗口尺寸变化后弹幕仍居中显示。
内容的提问来源于stack exchange,提问作者Mark K
相关产品推荐
相关产品推荐

