如何在Python的pyglet中向已有ScrollableTextLayout添加文本?
问题:如何在Pyglet的ScrollableTextLayout中动态追加日志文本?
我希望在游戏运行时创建操作日志,但查阅pyglet文档和示例后,仍不清楚如何向已显示初始文本的ScrollableTextLayout添加新文本。
现有代码可正常显示初始文本,滚动功能也能正常工作,但在游戏中通过actionLog = actionLog + "Player moved to " + str(x) + "," + str(y) + "\n"追加文本时,新内容不显示。尝试重新创建progressDocument和progressLayout会覆盖原有内容,多次绘制后旧文本出现重影。
原代码片段:
import pyglet # width of window progressWidth = 500 # height of window progressHeight = 800 # caption i.e title of the window progressTitle = "Game Progress" # creating a window gameProgress = pyglet.window.Window(progressWidth, progressHeight, progressTitle) # text actionLog = "Welcome to ALIEN SURVIVAL" + "\n" # batch object progressBatch = pyglet.graphics.Batch() # creating a formatted document # unlike unformatted document it is formatted progressDocument = pyglet.text.document.FormattedDocument(actionLog) # setting style to the document progressDocument.set_style(0, len(progressDocument.text), dict(font_name='Helvetica', font_size=14, color=(255, 255, 255, 255))) # creating a incremental text layout progressLayout = pyglet.text.layout.ScrollableTextLayout(progressDocument, progressWidth, progressHeight, multiline=True, batch=progressBatch) # on draw event @gameProgress.event def on_draw(): # clear the window gameProgress.clear() # draw the batch progressBatch.draw() pyglet.app.run()
解决方案
核心问题是你修改的actionLog变量和progressDocument没有绑定关系,progressDocument初始化后只会读取初始文本内容,后续修改actionLog不会同步到文档中。正确的做法是直接操作progressDocument的text属性追加内容,同时为新文本设置样式,避免出现无样式的空白内容。
修改后的代码示例
import pyglet from pyglet.window import key # 窗口参数 progressWidth = 500 progressHeight = 800 progressTitle = "Game Progress" # 创建窗口 gameProgress = pyglet.window.Window(progressWidth, progressHeight, progressTitle) # 初始化文档和布局 progressBatch = pyglet.graphics.Batch() initial_text = "Welcome to ALIEN SURVIVAL\n" progressDocument = pyglet.text.document.FormattedDocument(initial_text) # 定义全局样式 style = dict(font_name='Helvetica', font_size=14, color=(255, 255, 255, 255)) progressDocument.set_style(0, len(progressDocument.text), style) progressLayout = pyglet.text.layout.ScrollableTextLayout(progressDocument, progressWidth, progressHeight, multiline=True, batch=progressBatch) # 通用日志追加函数 def add_log_entry(text): # 记录追加前的文本长度,用于定位新内容的样式范围 current_length = len(progressDocument.text) # 直接向文档追加文本 progressDocument.text += f"{text}\n" # 为新追加的文本设置样式 progressDocument.set_style(current_length, len(progressDocument.text), style) # 自动滚动到日志底部(可选,不需要可删除此行) progressLayout.view_y = 0 # 用键盘事件模拟游戏操作(按M键触发移动日志) @gameProgress.event def on_key_press(symbol, modifiers): if symbol == key.M: # 模拟玩家移动坐标 x, y = 100, 200 add_log_entry(f"Player moved to {x},{y}") @gameProgress.event def on_draw(): gameProgress.clear() progressBatch.draw() pyglet.app.run()
关键说明
- 直接操作
progressDocument.text:这是动态更新文本的正确方式,修改该属性会自动通知关联的ScrollableTextLayout刷新显示,无需重新创建文档或布局。 - 为新文本设置样式:追加的新文本不会自动继承原有样式,必须通过
set_style方法为新增片段设置样式,起始位置为追加前的文本长度,结束位置为追加后的总长度。 - 自动滚动到最新内容(可选):设置
progressLayout.view_y = 0可让视图自动定位到最底部,显示最新日志;若需保留手动滚动功能,可删除此行。
内容的提问来源于stack exchange,提问作者GerfnitAuthor
相关产品推荐
相关产品推荐

