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

Kivy多屏幕切换异常:非焦点屏幕无法生成切换按钮

Kivy多屏幕切换按钮异常问题解决

我用Python Kivy开发了一款GUI应用,初始屏幕包含一个按钮,点击该按钮可生成新屏幕,同时需生成用于快速切换屏幕的按钮。但当前功能存在异常:仅处于焦点状态的屏幕能生成切换按钮,新创建的非焦点屏幕无法生成对应按钮。

原代码如下:

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition

    
class ScreenManagement(ScreenManager):
    def __init__(self, **kwargs):
        super(ScreenManagement, self).__init__(**kwargs)

sm = ScreenManagement(transition=FadeTransition())        
         
      
class newtab(Screen):
    def __init__(self, **kwargs):
        super(newtab, self).__init__(**kwargs)
        
        self.bt1=(Button(text="New tab", size_hint =(.1, .1)          ,pos_hint ={'center_x':.1, 'center_y':.94}))
        self.add_widget(self.bt1)
        self.bt1.bind(on_release=self.new_tab)
        
        
        self.txt1 = TextInput(text='',size_hint =(.1, .1),        pos_hint ={'center_x':.2, 'center_y':.75}, multiline=True)
        self.add_widget(self.txt1)
        

            
    def transition(self, instance):
        self.manager.current = (instance.text)
        for item in sm.screen_names:
            
            self.bt2=(Button(text=item, size_hint =(.1, .1)          ,pos_hint ={'center_x':(.1*sm.screen_names.index(item)+.1), 'center_y':.84}))
            self.add_widget(self.bt2)
            self.bt2.bind(on_release=self.transition)
        
    def new_tab(self, *args):
                
        n = len(self.manager.screen_names)    ##number of screens+1
        screen = newtab(name="screen {}".format(n))      #make new screen and give it number
        self.manager.add_widget(screen)
        self.manager.current = "screen 0"
               
        for item in sm.screen_names:            
            self.bt2=(Button(text=item, size_hint =(.1, .1)          ,pos_hint ={'center_x':(.1*sm.screen_names.index(item)+.1), 'center_y':.84}))
            self.add_widget(self.bt2)
            self.bt2.bind(on_release=self.transition)

            
sm.add_widget(newtab(name='screen 0'))    
             
class Application(App):
    def build(self):       
        return sm

if __name__ == "__main__":
    Application().run()

问题分析

原代码仅在点击New tab或切换屏幕时,给当前操作的屏幕生成切换按钮,新创建的屏幕实例完全没执行生成按钮的逻辑;而且每次操作还会重复添加按钮,导致旧按钮堆积。

修复方案

  1. 抽离切换按钮生成逻辑为独立方法,支持清理旧按钮、生成新按钮
  2. 每个屏幕初始化时自动生成切换按钮
  3. 新增屏幕后,遍历所有已存在的屏幕,同步更新切换按钮

修改后的代码:

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition


class ScreenManagement(ScreenManager):
    def __init__(self, **kwargs):
        super(ScreenManagement, self).__init__(**kwargs)


sm = ScreenManagement(transition=FadeTransition())


class NewTab(Screen):
    def __init__(self, **kwargs):
        super(NewTab, self).__init__(**kwargs)

        # 新建屏幕按钮
        self.bt1 = Button(text="New tab", size_hint=(.1, .1), pos_hint={'center_x': .1, 'center_y': .94})
        self.add_widget(self.bt1)
        self.bt1.bind(on_release=self.new_tab)

        # 文本输入框
        self.txt1 = TextInput(text='', size_hint=(.1, .1), pos_hint={'center_x': .2, 'center_y': .75}, multiline=True)
        self.add_widget(self.txt1)

        # 初始化时生成切换按钮
        self.update_tab_buttons()

    def transition(self, instance):
        self.manager.current = instance.text

    def update_tab_buttons(self):
        # 先移除所有旧的切换按钮(通过group标记识别)
        for widget in self.children[:]:
            if isinstance(widget, Button) and widget.group == 'tab_button':
                self.remove_widget(widget)

        # 生成新的切换按钮
        for idx, screen_name in enumerate(self.manager.screen_names):
            tab_btn = Button(
                text=screen_name,
                size_hint=(.1, .1),
                pos_hint={'center_x': (.1 * idx + .1), 'center_y': .84},
                group='tab_button'
            )
            self.add_widget(tab_btn)
            tab_btn.bind(on_release=self.transition)

    def new_tab(self, *args):
        # 新建屏幕
        n = len(self.manager.screen_names)
        new_screen = NewTab(name=f"screen {n}")
        self.manager.add_widget(new_screen)
        self.manager.current = "screen 0"

        # 所有屏幕同步更新切换按钮
        for screen in self.manager.screens:
            screen.update_tab_buttons()


sm.add_widget(NewTab(name='screen 0'))


class Application(App):
    def build(self):
        return sm


if __name__ == "__main__":
    Application().run()

关键修改点

  • 类名改为大驼峰NewTab,符合Python编码规范
  • 新增update_tab_buttons方法,统一处理切换按钮的清理与生成,通过group标记区分切换按钮和其他按钮
  • 每个屏幕初始化时自动调用update_tab_buttons,保证所有屏幕初始就有切换按钮
  • 新增屏幕后遍历所有屏幕更新按钮,实现全屏幕同步
  • 移除原transition方法中重复生成按钮的逻辑,避免按钮堆积

内容的提问来源于stack exchange,提问作者humantrash

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 20:01:54