Kivy点击按钮报TypeError: object.__init__()错及按钮图标异常
问题修复方案
崩溃问题 TypeError: object.__init__() takes no arguments
你代码里有4个直接导致崩溃的问题:
- Kivy属性写法错误:你用
变量名: 属性类()的Python类型注解语法写Kivy属性是错的,这种写法不会给类属性赋值,Kivy根本注册不了note_index/note_title/note_content这些属性,你初始化组件传这些参数的时候,会被当成未知参数一路透传到最顶层的object基类,直接触发参数不接受的报错。必须改成变量名 = 属性类()的类属性赋值写法。 - 字典键名大小写不统一:你新增笔记的时候存的内容键是大写开头的
'Content',但_get_data_for_widget方法和edit_note方法里取内容用的是小写的'content',直接触发KeyError: 'content'前置错误,连锁导致后续组件初始化逻辑异常。 - 文件读写逻辑笔误:
load_notes方法里你写的文件路径是self.note_fn,但你定义的路径属性是self.notes_fn,差了个s;而且打开模式错写为'w'写入模式,读文件应该用'r'模式,不然会直接清空本地存的笔记文件。 - 缺失方法定义:
MutableTextInput类的__init__里调用了self.prepare,但你根本没写这个方法,用到这个组件的时候会直接抛属性不存在的错误。
按钮图标只显示白色矩形问题
这个问题基本是以下几个原因导致的,按顺序排查就行:
- 图标文件路径写错,Kivy找不到对应资源,渲染成空白块
- 没有给按钮/图标设置有效尺寸,组件尺寸为0或者比例不对导致显示异常
- 图标格式不被Kivy支持,优先用png格式,不要用ico、webp等需要额外依赖的格式
- 相对路径的工作目录和你预期不一致,Kivy加载资源是按程序启动的工作目录找的,不是按代码文件所在目录找,最好拼绝对路径加载图标。
修复后的可运行代码
from os.path import join, exists import json from kivy.app import App from kivy.uix.screenmanager import Screen, ScreenManager, SlideTransition from kivy.clock import Clock from kivy.uix.boxlayout import BoxLayout from kivy.uix.floatlayout import FloatLayout from kivy.properties import ListProperty, StringProperty, NumericProperty, AliasProperty class NoteView(Screen): # Kivy属性必须用=赋值定义,不能用:类型注解 note_index = NumericProperty() note_title = StringProperty() note_content = StringProperty() class NoteListItem(BoxLayout): note_index = NumericProperty() note_title = StringProperty() note_content = StringProperty() class Notes(Screen): data = ListProperty() def _get_data_for_widget(self): return [{ 'note_index': index, 'note_content': item.get('content', ''), 'note_title': item.get('title', '')} for index, item in enumerate(self.data)] data_for_widgets = AliasProperty(_get_data_for_widget, bind=['data']) class MutableTextInput(FloatLayout): def __init__(self, **kwargs): super().__init__(**kwargs) Clock.schedule_once(self.prepare, 0) # 补全缺失的prepare方法 def prepare(self, *args): pass class MainApp(App): def build(self): self.notes = Notes(name='Notes') self.load_notes() self.transition = SlideTransition(duration=.3) root = ScreenManager(transition=self.transition) root.add_widget(self.notes) return root def load_notes(self): if not exists(self.notes_fn): return # 修正文件名笔误,读模式打开文件,指定编码避免中文乱码 with open(self.notes_fn, 'r', encoding='utf-8') as fd: data = json.load(fd) self.notes.data = data def save_notes(self): # 补全保存笔记的逻辑,不然退出后笔记会丢失 with open(self.notes_fn, 'w', encoding='utf-8') as fd: json.dump(self.notes.data, fd, ensure_ascii=False, indent=2) def edit_note(self, note_index): note = self.notes.data[note_index] name = f'note{note_index}' if self.root.has_screen(name): self.root.remove_widget(self.root.get_screen(name)) view = NoteView( name=name, note_index=note_index, note_title=note.get('title', ''), # 统一用小写content键 note_content=note.get('content', '')) self.root.add_widget(view) self.transition.direction = 'left' self.root.current = view.name def add_note(self): # 统一用小写content键,和读取逻辑保持一致 self.notes.data.append({'title': 'New note', 'content': ''}) note_index = len(self.notes.data) - 1 self.edit_note(note_index) @property def notes_fn(self): return join(self.user_data_dir, 'notes.json') if __name__ == '__main__': MainApp().run()
内容的提问来源于stack exchange,提问作者PythonRookie
相关产品推荐
相关产品推荐

