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

如何在Kivy Python的多个屏幕间实现数据共享?

Kivy 简化版IMDb应用:屏幕间数据传递解决方案

问题描述

我正在用Kivy开发一个简化版IMDb应用,遇到了屏幕间无法交换数据的问题。例如:

  • 点击第一个屏幕的按钮后,第二个屏幕的Label能接收并显示对应数据;
  • 根据第一个屏幕点击的按钮,在第二个屏幕生成对应数量的按钮。
    我是编程新手,经验不足,希望得到帮助!

解决方案

针对Kivy屏幕间数据传递,这里提供两种简单易懂的实现方式,以下是修改后的完整代码及关键说明:

修改后的完整代码

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.core.window import Window
from kivy.uix.screenmanager import *

class MovieInfo(Screen):
    def __init__(self, name="MovieInfo"):
        super(MovieInfo, self).__init__(name=name)
        # 导航栏
        alNavigationBar = AnchorLayout(anchor_x="center", anchor_y="top", padding=(25, 20, 25, 15))
        glNavigationBar = GridLayout(cols=2, rows=1, size_hint_y=None)
        backBtn = Button(text="<-", size_hint=(None, None), size=(100, 100), on_press=self.pressBackButton)
        glNavigationBar.add_widget(backBtn)
        alNavigationBar.add_widget(glNavigationBar)
        
        # 信息容器,设为实例属性方便外部访问
        self.informs = BoxLayout(orientation='vertical', spacing=15, size_hint_y=None, padding=(25, 25, 25, 10))
        self.informs.bind(minimum_height=self.informs.setter('height'))
        
        scrollInforms = ScrollView(size_hint=(1, None), size=(Window.width, Window.height - 100))
        scrollInforms.add_widget(self.informs)

        self.add_widget(alNavigationBar)
        self.add_widget(scrollInforms)

    def pressBackButton(self, instance):
        self.manager.current = "MovieList"
    
    # 新增:更新信息的方法
    def update_info(self, data):
        # 清空原有内容
        self.informs.clear_widgets()
        # 根据传入数据生成对应内容
        if isinstance(data, int):
            # 生成对应数量的详情条目
            for i in range(data):
                label = Label(text=f"电影详情条目 {i+1}", size_hint_y=None, font_size='18sp')
                self.informs.add_widget(label)
        else:
            # 显示传入的文本数据
            label = Label(text=data, size_hint_y=None, font_size='18sp')
            self.informs.add_widget(label)

class Movies(Screen):
    def __init__(self, name="MovieList"):
        super(Movies, self).__init__(name=name)
        # 导航栏
        alNavigationBar = AnchorLayout(anchor_x="center", anchor_y="top", padding=(25, 20, 25, 15))
        glNavigationBar = GridLayout(cols=2, rows=1, size_hint_y=None)
        backBtn = Button(text="<-", size_hint=(None, None), size=(100, 100), on_press=self.pressBackButton)
        glNavigationBar.add_widget(backBtn)
        alNavigationBar.add_widget(glNavigationBar)
        
        moviesList = BoxLayout(orientation='vertical', spacing=15, size_hint_y=None, padding=(25, 25, 25, 10))
        moviesList.bind(minimum_height=moviesList.setter('height'))
        for i in range(50):
            movieButton = Button(text=f"{i+1}", size_hint_y=None, height=140, on_press=self.pressMovieButton)
            moviesList.add_widget(movieButton)
        scrollMoviesList = ScrollView(size_hint=(1, None), size=(Window.width, Window.height - 120))
        scrollMoviesList.add_widget(moviesList)

        self.add_widget(alNavigationBar)
        self.add_widget(scrollMoviesList)

    def pressBackButton(self, instance):
        self.manager.current = "GenresList"

    def pressMovieButton(self, instance):
        # 获取MovieInfo屏幕实例
        movie_info_screen = self.manager.get_screen("MovieInfo")
        # 传递按钮上的数字,生成对应数量的详情条目
        movie_info_screen.update_info(int(instance.text))
        # 切换到详情屏幕
        self.manager.current = "MovieInfo"

class Genres(Screen):
    def __init__(self, name="GenresList"):
        super(Genres, self).__init__(name=name)
        alInputText = AnchorLayout(anchor_x="center", anchor_y="top", padding=(10, 20, 10, 0))
        inputText = TextInput(hint_text='Enter movie name', multiline=False, font_size=40, size_hint=(0.97, 0.05),
                          on_text_validate=self.inputMoviesName)
        alInputText.add_widget(inputText)
        
        genresList = GridLayout(cols=2, spacing=15, size_hint_y=None, padding=(25, 0, 25, 10))
        genresList.bind(minimum_height=genresList.setter('height'))
        for i in range(50):
            genreButton = Button(text=f"类型 {i+1}", size_hint_y=None, height=350, on_press=self.pressGenreButton)
            genresList.add_widget(genreButton)
        scrollGenresList = ScrollView(size_hint=(1, None), size=(Window.width, Window.height - 100))
        scrollGenresList.add_widget(genresList)

        self.add_widget(alInputText)
        self.add_widget(scrollGenresList)

    def inputMoviesName(self, instance):
        # 示例:传递搜索内容到Movies屏幕(可扩展更新电影列表逻辑)
        movies_screen = self.manager.get_screen("MovieList")
        print(f"搜索电影:{instance.text}")
        instance.text = ""
        self.manager.current = "MovieList"

    def pressGenreButton(self, instance):
        # 示例:传递选中类型到Movies屏幕(可扩展更新电影列表逻辑)
        movies_screen = self.manager.get_screen("MovieList")
        print(f"选择类型:{instance.text}")
        self.manager.current = "MovieList"

class Application(App):
    def build(self):
        self.title = "MyIMDb"
        scrManager = ScreenManager(transition=NoTransition())
        screens = [
            Genres(),
            Movies(),
            MovieInfo()
        ]
        for i in screens:
            scrManager.add_widget(i)
        return scrManager

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

关键修改说明

  1. 暴露需要更新的控件:在MovieInfo类中,将原本的局部变量informs改为实例属性self.informs,让外部屏幕可以直接访问该容器。
  2. 添加数据更新方法:在MovieInfo中新增update_info方法,负责清空原有内容并根据传入的数据生成新的Label,支持两种数据类型:整数(生成对应数量条目)、文本(直接显示内容)。
  3. 直接获取目标屏幕传递数据:在Movies的按钮点击方法中,通过self.manager.get_screen("MovieInfo")获取目标屏幕的实例,调用其更新方法传递数据后再切换屏幕,确保数据先更新再显示。
  4. 可扩展的其他场景:在Genres的输入和按钮点击方法中,同样可以用相同逻辑传递数据到Movies屏幕,只需给Movies类添加对应的更新方法即可。

内容的提问来源于stack exchange,提问作者Олексій Гродецкий

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 04:55:44