Kivy多屏幕猜单词游戏中单词显示字段失效问题求助
Kivy猜单词游戏单词显示字段异常问题解决求助
本人使用Kivy框架开发Python猜单词游戏,遇到以下问题:单独显示游戏屏幕时功能完全正常,但整合包含其他屏幕的完整游戏后,选中的字母可以正常显示,但单词字段(下划线占位的区域)无内容显示。本人学习Python不足半年,代码可能存在疏漏,望得到解决方案。
相关代码
Python代码
from kivymd.app import MDApp from kivy.uix.screenmanager import ScreenManager, Screen from kivy.lang import Builder from kivy.core.audio import SoundLoader from kivy.core.window import Window from kivy.properties import StringProperty from kivy.uix.widget import Widget from random import * Window.size = (400,600) class Meneger(ScreenManager): def __init__(self, **kwargs): super().__init__(**kwargs) class Menu(Screen): def click(self): click = SoundLoader.load('click.wav') click.play() class Play(Screen): def click(self): click = SoundLoader.load('click.wav') click.play() class Mod(Screen): def click(self): click = SoundLoader.load('click.wav') click.play() class HangmanGame(Screen, Widget): def __init__(self, **kwargs): super().__init__(**kwargs) display_word = StringProperty() wrong_guess = 0 correct_guess = 0 def playsound(self): self.sound = SoundLoader.load('button.wav') self.sound.volume = 0.5 self.sound.play() def FindHangmanWord(self): word_list = ['arrow', 'arson', 'artery', 'artful', 'artier', 'artist', 'arts', 'artsy', 'arty', 'ascend', 'ascent', 'ascot', 'ashcan', 'ashed', 'ashen', 'ashes', 'ashier', 'ashing', 'ashore', 'ashram', 'ashy', 'aside', 'askew', 'asking', 'asks'] word = choice(word_list) return word.upper() def check_in_word(self, btn): count = 0 for i, letter in enumerate(wow): if btn.text == letter.upper(): self.display_word = self.display_word[:i * 2] + btn.text + self.display_word[i * 2 + 1:] self.correct_guess += 1 count += 1 if self.correct_guess >= len(wow): print('GAME OVER, YOU WIN') btn.disabled = True if count == 0: self.wrong_guess += 1 if self.wrong_guess >= 6: print('GAME OVER, YOU LOSE!') def init_display_word(self, word): tmp_display_word = '' for letter in word: tmp_display_word += '_ ' self.display_word = tmp_display_word[:len(tmp_display_word) - 1] class Info(Screen): def click(self): click = SoundLoader.load('click.wav') click.play() presentation = Builder.load_file('my.kv') class MyApp(MDApp): def build(self): game = HangmanGame() game.init_display_word(wow) self.playsound() sm = ScreenManager() sm.add_widget(Menu(name='menu')) sm.add_widget(Play(name='play')) sm.add_widget(Info(name='info')) sm.add_widget(Mod(name='mod')) sm.add_widget(HangmanGame(name='hangmangame')) return sm def playsound(self): self.sound = SoundLoader.load('glav.wav') self.sound.volume = 0.5 self.sound.play() if __name__ == '__main__': wow = HangmanGame().FindHangmanWord() MyApp().run()
KV代码片段
Label: id: display_word_id text: root.display_word font_size: 40 color: (1, 1, 1, 1) pos_hint: {'center_x': 0.5}
截图情况
- 单屏幕效果:单词字段正常显示下划线占位符,字母交互正常
- 多屏幕整合后:单词字段无内容,选中字母可显示但下划线区域不出现
已尝试的无效方案
- 将代码拆分到第二个文件后导入,无效果
- 在
init_display_word方法中用HangmanGame类名替代self,单词字段显示但选中字母失效;反之则字母生效但字段消失 - 尝试在
build方法中加入check_in_word,但因需要第二个参数无法自动传入
解决方案
核心问题分析
- 重复创建
HangmanGame实例:build方法中先创建了一个game实例并初始化了display_word,但实际添加到屏幕管理器的是另一个全新的HangmanGame实例,导致屏幕上的实例未被初始化 - 全局变量
wow的冲突:全局变量存储目标单词,导致实例间状态混乱
修复步骤
- 重构
HangmanGame类,移除全局变量依赖
class HangmanGame(Screen): # 无需继承Widget,Screen本身是Widget子类 display_word = StringProperty() wrong_guess = 0 correct_guess = 0 def __init__(self, **kwargs): super().__init__(**kwargs) self.target_word = self.FindHangmanWord() # 实例内部存储目标单词 self.init_display_word(self.target_word) # 初始化显示字段 # 其余方法不变,仅将check_in_word中的wow替换为self.target_word def check_in_word(self, btn): count = 0 for i, letter in enumerate(self.target_word): if btn.text == letter.upper(): self.display_word = self.display_word[:i * 2] + btn.text + self.display_word[i * 2 + 1:] self.correct_guess += 1 count += 1 if self.correct_guess >= len(self.target_word): print('GAME OVER, YOU WIN') btn.disabled = True if count == 0: self.wrong_guess += 1 if self.wrong_guess >= 6: print('GAME OVER, YOU LOSE!')
- 修正
MyApp.build方法,避免重复创建实例
class MyApp(MDApp): def build(self): self.playsound() sm = ScreenManager() sm.add_widget(Menu(name='menu')) sm.add_widget(Play(name='play')) sm.add_widget(Info(name='info')) sm.add_widget(Mod(name='mod')) # 仅创建一次HangmanGame实例并添加到屏幕管理器 hangman_game = HangmanGame(name='hangmangame') sm.add_widget(hangman_game) return sm
- 移除全局变量定义
if __name__ == '__main__': MyApp().run()
额外优化建议
- 将
Meneger类名改为Manager(修正拼写错误) - 音效加载可做缓存处理,避免每次点击重复读取文件
- 将单词列表移至类内部或单独配置文件,便于后续维护
内容的提问来源于stack exchange,提问作者zukor
相关产品推荐
相关产品推荐

