Kivy中random_answer函数执行后Submit按钮未禁用问题排查
问题:Kivy应用中「Принять ответ」按钮无法禁用
我是Kivy新手,开发了一款带任务切换功能的Python-Kivy应用。希望点击「Принять ответ」(Submit)按钮触发random_answer函数后,该按钮会被禁用,但实际按钮并未按预期禁用,控制台也没有报错。相关代码如下:
Config.set('graphics', 'resizable', '0') class MyApp(App): list_of_tasks=['Задание №1: составьте структурную формулу бутена-1', 'Задание №2: составьте структурную формулу 3-этилгексена-1', 'Задание №3: составьте структурную формулу 2,3-диметилгексена-1', 'Задание №4: составьте структурную формулу метилпропена-1', 'Задание №5: составьте структурную формулу 5-метилгексена-2', 'Задание №6: составьте структурную формулу 2-метилгексена-3', 'Задание №7: составьте структурную формулу 2,3-диметилбутена-2', 'Задание №8: составьте структурную формулу пентена-1', 'Задание №9: составьте структурную формулу 2-метилбутена-2', 'Задание №10: составьте структурную формулу 3-диметилбутен-1'] answers=['Верный ответ!','Неверный ответ!'] label=Label(text='Задание №1: составьте структурную формулу бутена ',pos=(0,200)) answer_label = Label(text=random.choice(answers)) i=0 iii=0 ii=str(iii) label_0_10=Label(text='0/10',pos=(300,250)) submit=Button(text='Принять ответ',pos=(200,100))#,size_hint=(.5,.15),on_press=self.random_answer) completed_tasks=[] def new_task(self, *args): if self.i==9: self.label.text=self.list_of_tasks[0] self.i=0 else: self.label.text=self.list_of_tasks[self.i+1] self.i+=1 self.ii = str(self.iii) self.label_0_10.text = self.ii + '/10' self.root.clear_widgets() self.root.add_widget(self.label) self.root.add_widget(self.label_0_10) self.root.add_widget(Button(text='Принять ответ', pos=(200, 100), size_hint=(.5, .15), on_press=self.random_answer)) anchor_for_button = AnchorLayout(anchor_x='right', anchor_y='bottom') anchor_for_button.add_widget(Button(text='Перейти к следующей задаче>', size_hint=[.35, .05], on_press=self.new_task)) self.root.add_widget(anchor_for_button) anchor_for_button2 = AnchorLayout(anchor_x='left', anchor_y='bottom') anchor_for_button2.add_widget(Button(text='<Перейти к предыдущей задаче', size_hint=[.35, .05], on_press=self.not_new_task)) self.root.add_widget(anchor_for_button2) def not_new_task(self, *args): if self.i==0: self.label.text=self.list_of_tasks[9] self.i=9 else: self.label.text=self.list_of_tasks[self.i-1] self.i-=1 self.ii = str(self.iii) self.label_0_10.text = self.ii + '/10' self.root.clear_widgets() self.root.add_widget(self.label) self.root.add_widget(self.label_0_10) self.root.add_widget(Button(text='Принять ответ', pos=(200, 100), size_hint=(.5, .15), on_press=self.random_answer)) anchor_for_button = AnchorLayout(anchor_x='right', anchor_y='bottom') anchor_for_button.add_widget(Button(text='Перейти к следующей задаче>', size_hint=[.35, .05], on_press=self.new_task)) self.root.add_widget(anchor_for_button) anchor_for_button2 = AnchorLayout(anchor_x='left', anchor_y='bottom') anchor_for_button2.add_widget(Button(text='<Перейти к предыдущей задаче', size_hint=[.35, .05], on_press=self.not_new_task)) self.root.add_widget(anchor_for_button2) def random_answer(self,*args): random_choice=random.choice(self.answers) self.answer_label = Label(text=random_choice) if self.list_of_tasks[self.i] in self.completed_tasks: self.submit.disabled=True else: print(self.list_of_tasks[self.i]) print(self.completed_tasks) self.submit.disabled=False if random_choice=='Верный ответ!': self.iii+=1 self.completed_tasks.append(self.list_of_tasks[self.i]) else: self.completed_tasks.append(self.list_of_tasks[self.i]) self.root.add_widget(self.answer_label) def build(self): fl=FloatLayout(size=(300,300)) anchor_for_button=AnchorLayout(anchor_x='right', anchor_y='bottom') anchor_for_button2=AnchorLayout(anchor_x='left', anchor_y='bottom') label=Label(text='Задание №1: составьте структурную формулу бутена ',pos=(0,200)) label_0_10=Label(text=self.ii+'/10',pos=(300,250)) submit=Button(text='Принять ответ',pos=(200,100),size_hint=(.5,.15),on_press=self.random_answer) fl.add_widget(self.label) fl.add_widget(submit) anchor_for_button.add_widget(Button(text='Перейти к следующей задаче>',size_hint=[.35,.05],on_press=self.new_task)) anchor_for_button2.add_widget(Button(text='<Перейти к предыдущей задаче',size_hint=[.35,.05],on_press=self.not_new_task)) fl.add_widget(label_0_10) fl.add_widget(anchor_for_button) fl.add_widget(anchor_for_button2) return fl if __name__=="__main__": MyApp().run()
问题原因
- 类初始化时定义的
self.submit是一个未添加到界面的空Button实例,并非用户实际点击的按钮。 - 在
build、new_task、not_new_task方法中,每次都是创建新的局部Button对象并添加到布局,但未将这些实例赋值给self.submit,导致random_answer中修改的是一个无效对象的属性,对界面按钮无影响。
解决方法
确保每次创建的Submit按钮都赋值给self.submit,让random_answer操作的是界面上的实际按钮;同时切换任务时,根据当前任务是否已完成设置按钮初始禁用状态。
修改后的完整代码:
import random from kivy.app import App from kivy.uix.floatlayout import FloatLayout from kivy.uix.label import Label from kivy.uix.button import Button from kivy.uix.anchorlayout import AnchorLayout from kivy.config import Config Config.set('graphics', 'resizable', '0') class MyApp(App): list_of_tasks=['Задание №1: составьте структурную формулу бутена-1', 'Задание №2: составьте структурную формулу 3-этилгексена-1', 'Задание №3: составьте структурную формулу 2,3-диметилгексена-1', 'Задание №4: составьте структурную формулу метилпропена-1', 'Задание №5: составьте структурную формулу 5-метилгексена-2', 'Задание №6: составьте структурную формулу 2-метилгексена-3', 'Задание №7: составьте структурную формулу 2,3-диметилбутена-2', 'Задание №8: составьте структурную формулу пентена-1', 'Задание №9: составьте структурную формулу 2-метилбутена-2', 'Задание №10: составьте структурную формулу 3-диметилбутен-1'] answers=['Верный ответ!','Неверный ответ!'] label=Label(text='Задание №1: составьте структурную формулу бутена ',pos=(0,200)) answer_label = Label(text=random.choice(answers)) i=0 iii=0 ii=str(iii) label_0_10=Label(text='0/10',pos=(300,250)) submit = None completed_tasks=[] def new_task(self, *args): if self.i==9: self.label.text=self.list_of_tasks[0] self.i=0 else: self.label.text=self.list_of_tasks[self.i+1] self.i+=1 self.ii = str(self.iii) self.label_0_10.text = self.ii + '/10' self.root.clear_widgets() self.root.add_widget(self.label) self.root.add_widget(self.label_0_10) # 创建按钮并赋值给self.submit,设置初始禁用状态 self.submit = Button(text='Принять ответ', pos=(200, 100), size_hint=(.5, .15), on_press=self.random_answer) self.submit.disabled = self.list_of_tasks[self.i] in self.completed_tasks self.root.add_widget(self.submit) anchor_for_button = AnchorLayout(anchor_x='right', anchor_y='bottom') anchor_for_button.add_widget(Button(text='Перейти к следующей задаче>', size_hint=[.35, .05], on_press=self.new_task)) self.root.add_widget(anchor_for_button) anchor_for_button2 = AnchorLayout(anchor_x='left', anchor_y='bottom') anchor_for_button2.add_widget(Button(text='<Перейти к предыдущей задаче', size_hint=[.35, .05], on_press=self.not_new_task)) self.root.add_widget(anchor_for_button2) def not_new_task(self, *args): if self.i==0: self.label.text=self.list_of_tasks[9] self.i=9 else: self.label.text=self.list_of_tasks[self.i-1] self.i-=1 self.ii = str(self.iii) self.label_0_10.text = self.ii + '/10' self.root.clear_widgets() self.root.add_widget(self.label) self.root.add_widget(self.label_0_10) # 创建按钮并赋值给self.submit,设置初始禁用状态 self.submit = Button(text='Принять ответ', pos=(200, 100), size_hint=(.5, .15), on_press=self.random_answer) self.submit.disabled = self.list_of_tasks[self.i] in self.completed_tasks self.root.add_widget(self.submit) anchor_for_button = AnchorLayout(anchor_x='right', anchor_y='bottom') anchor_for_button.add_widget(Button(text='Перейти к следующей задаче>', size_hint=[.35, .05], on_press=self.new_task)) self.root.add_widget(anchor_for_button) anchor_for_button2 = AnchorLayout(anchor_x='left', anchor_y='bottom') anchor_for_button2.add_widget(Button(text='<Перейти к предыдущей задаче', size_hint=[.35, .05], on_press=self.not_new_task)) self.root.add_widget(anchor_for_button2) def random_answer(self,*args): random_choice=random.choice(self.answers) # 移除旧的答案标签避免重叠 if self.answer_label in self.root.children: self.root.remove_widget(self.answer_label) self.answer_label = Label(text=random_choice) # 操作界面上的实际按钮 if self.list_of_tasks[self.i] not in self.completed_tasks: if random_choice=='Верный ответ!': self.iii+=1 self.completed_tasks.append(self.list_of_tasks[self.i]) # 提交后直接禁用按钮 self.submit.disabled=True self.root.add_widget(self.answer_label) def build(self): fl=FloatLayout(size=(300,300)) anchor_for_button=AnchorLayout(anchor_x='right', anchor_y='bottom') anchor_for_button2=AnchorLayout(anchor_x='left', anchor_y='bottom') self.label_0_10.text = self.ii+'/10' # 创建按钮并赋值给self.submit,设置初始禁用状态 self.submit = Button(text='Принять ответ',pos=(200,100),size_hint=(.5,.15),on_press=self.random_answer) self.submit.disabled = self.list_of_tasks[self.i] in self.completed_tasks fl.add_widget(self.label) fl.add_widget(self.submit) anchor_for_button.add_widget(Button(text='Перейти к следующей задаче>',size_hint=[.35,.05],on_press=self.new_task)) anchor_for_button2.add_widget(Button(text='<Перейти к предыдущей задаче',size_hint=[.35,.05],on_press=self.not_new_task)) fl.add_widget(self.label_0_10) fl.add_widget(anchor_for_button) fl.add_widget(anchor_for_button2) return fl if __name__=="__main__": MyApp().run()
关键修改点
- 移除类初始化时的空
submit按钮定义,改为submit = None,后续动态赋值界面上的实际按钮。 - 在
build、new_task、not_new_task中创建Submit按钮时,都赋值给self.submit,并根据当前任务是否已完成设置初始禁用状态。 - 在
random_answer中直接操作self.submit的disabled属性,提交后直接禁用按钮避免重复点击。 - 添加移除旧
answer_label的逻辑,解决文字重叠问题。
内容的提问来源于stack exchange,提问作者Никита Титков
相关产品推荐
相关产品推荐

