You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,提问作者Никита Титков

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 09:27:03