【问题标题】:Kivy - Use text from TextInput of one screen in another screen in .py fileKivy - 在 .py 文件中的另一个屏幕中使用来自一个屏幕的 TextInput 的文本
【发布时间】:2020-07-12 13:59:36
【问题描述】:

我的第一个屏幕上有一个 TextInput,我想在第二个屏幕的标签中使用接收到的文本。我怎样才能做到这一点?由于可以有不同的玩家,我创建了一个类 Players ,它为每个玩家存储一个名字和他/她的分数。在第二个屏幕中,我还尝试创建一个可以编辑点(标签文本)的按钮,但是当我单击它时,什么也没有发生。 (我也是新手。)

在下面的代码中,我标记了相关的行。

所以概述:

  • 第一个屏幕:使用 textInput 提取用户名 + 使用 Player 类创建播放器实例

  • 第二个屏幕:在标签中使用玩家名称 + 在标签中使用玩家点 + 创建 2 个按钮,从这个“点”标签中添加/减去点

我知道这里有类似的情况,但它对我的 .py 文件没有帮助:How to ref a TextInput from one screen in another screen in Kivy/Python?

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.textinput import TextInput
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.properties import ObjectProperty, NumericProperty


class Player:
    def __init__(self, name):
        self.name = name
        self.points = 0

    def reset_points(self):
        self.points = 0

    def add_point(self, *args):
        self.points += 1

    def subtract_point(self, *args):
        self.points -= 1


class WelcomeWindow(Screen):
    # Introduce names of the 4 players

    def __init__(self, **kwargs):
        super(WelcomeWindow, self).__init__(**kwargs)
        self.name = "welcomewindow"
        self.layout = "layout_welcome_window"

        global_layout = GridLayout(rows=3)
        self.add_widget(global_layout)

        label_player_i = Label(text="Name Player ")
        global_layout.add_widget(label_player_i)

        name_input_player_i = TextInput(id="player ", text="player", multiline=False) # <--- user inputs name here
        global_layout.add_widget(name_input_player_i)

        self.player1 = Player(name_input_player_i.text) # <--- name is assigned to player here

        # Create button to go to next screen
        go_further_button = Button(text="Go to first round")
        go_further_button.bind(on_release=self.go_further)
        global_layout.add_widget(go_further_button)

    def go_further(self, *args):
        self.manager.current = "firstround"
        self.manager.transition.direction = "left"

class FirstRound(Screen):
    #Give explanation of first round + option to add points for every player

    def __init__(self, **kwargs):
        super(FirstRound, self).__init__(**kwargs)
        self.name = "firstround"
        self.layout = "layout_first_round"

        #Create layout
        global_layout = GridLayout(rows=4)
        self.add_widget(global_layout)

        #Create Labels
        label_player_name_i = Label(text=WelcomeWindow().player1.name) # <--- Label should get the name of the player here
        global_layout.add_widget(label_player_name_i)

        label_player_points_i = Label(text=str(WelcomeWindow().player1.points)) # <--- Label should get points of player
        global_layout.add_widget((label_player_points_i))

        #Create Buttons
        button_minus = Button(text="-", font_size=100, id="minus_button")
        button_minus.bind(on_release=WelcomeWindow().player1.subtract_point) # <--- When button pushed: should subtract point
        global_layout.add_widget(button_minus)

        button_plus = Button(text="+", font_size=100, id="plus_button")
        button_plus.bind(on_release=WelcomeWindow().player1.add_point) # <--- When button pushed: should add point
        global_layout.add_widget(button_plus)


WindowManager = ScreenManager()
WindowManager.add_widget(WelcomeWindow())
WindowManager.add_widget(FirstRound())

class KingenApp(App):

    def build(self):
        return WindowManager

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

【问题讨论】:

    标签: python class kivy kivy-language textinput


    【解决方案1】:

    你的代码有几个问题:

    • 当您创建Widget 的实例时,将调用任何Widget__init__() 方法。所以FirstRound__init__() 方法在WindowManager.add_widget(FirstRound()) 行被调用。那时,WelcomeWindowTextInput 中无法输入任何文字 ,因此您无法获得当时的玩家名称。
    • Player 实例 (self.player1 = Player(name_input_player_i.text)) 的创建会在用户有机会输入玩家姓名之前创建 Player 实例。
    • FirstRound__init__() 方法中使用WelcomeWindow() 会创建一个与GUI 中的实例无关的WelcomeWindow 新实例。所以从那个实例中提取的任何信息都是没有用的。
    • 在您的FirstRound 中,玩家积分标签在创建Label 时从Player 类实例中获取其数据。之后更改Playerpoints 属性将不会影响Label

    第一个问题可以通过将大部分代码从FirstRound__init__() 方法中移出,并将其放入在显示Screen 时运行的on_enter() 方法中。

    第二个问题可以通过将Player 实例的创建移到go_further() 方法中来处理,因为它在离开WelcomeWindow 时被执行。

    第三个问题可以通过将WelcomeWindow() 的这些用法替换为self.manager.get_screen('welcomewindow') 来访问GUI 中WelcomeWindow 的实际实例。

    这是您的代码的修改版本,它可以完成这三件事:

    from kivy.app import App
    from kivy.uix.screenmanager import ScreenManager, Screen
    from kivy.uix.textinput import TextInput
    from kivy.uix.gridlayout import GridLayout
    from kivy.uix.button import Button
    from kivy.uix.label import Label
    
    
    class Player:
        def __init__(self, name):
            self.name = name
            self.points = 0
    
        def reset_points(self):
            self.points = 0
    
        def add_point(self, *args):
            self.points += 1
    
        def subtract_point(self, *args):
            self.points -= 1
    
    
    class WelcomeWindow(Screen):
        # Introduce names of the 4 players
    
        def __init__(self, **kwargs):
            super(WelcomeWindow, self).__init__(**kwargs)
            self.name = "welcomewindow"
            self.layout = "layout_welcome_window"
    
            global_layout = GridLayout(rows=3)
            self.add_widget(global_layout)
    
            label_player_i = Label(text="Name Player ")
            global_layout.add_widget(label_player_i)
    
            self.name_input_player_i = TextInput(id="player ", text="player", multiline=False) # <--- user inputs name here
            global_layout.add_widget(self.name_input_player_i)
    
            # Create button to go to next screen
            go_further_button = Button(text="Go to first round")
            go_further_button.bind(on_release=self.go_further)
            global_layout.add_widget(go_further_button)
    
        def go_further(self, *args):
            self.player1 = Player(self.name_input_player_i.text) # <--- name is assigned to player here
            self.manager.current = "firstround"
            self.manager.transition.direction = "left"
    
    
    class FirstRound(Screen):
        #Give explanation of first round + option to add points for every player
    
        def __init__(self, **kwargs):
            super(FirstRound, self).__init__(**kwargs)
            self.name = "firstround"
            self.layout = "layout_first_round"
    
        def on_enter(self, *args):
            #Create layout
            global_layout = GridLayout(rows=4)
            self.add_widget(global_layout)
    
            #Create Labels
            welcome_window = self.manager.get_screen('welcomewindow')  # get a reference to the WelcomeWindow instance
            label_player_name_i = Label(text=welcome_window.player1.name) # <--- Label should get the name of the player here
            global_layout.add_widget(label_player_name_i)
    
            label_player_points_i = Label(text=str(welcome_window.player1.points)) # <--- Label should get points of player
            global_layout.add_widget((label_player_points_i))
    
            #Create Buttons
            button_minus = Button(text="-", font_size=100, id="minus_button")
            button_minus.bind(on_release=welcome_window.player1.subtract_point) # <--- When button pushed: should subtract point
            global_layout.add_widget(button_minus)
    
            button_plus = Button(text="+", font_size=100, id="plus_button")
            button_plus.bind(on_release=welcome_window.player1.add_point) # <--- When button pushed: should add point
            global_layout.add_widget(button_plus)
    
    
    WindowManager = ScreenManager()
    WindowManager.add_widget(WelcomeWindow())
    WindowManager.add_widget(FirstRound())
    
    
    class KingenApp(App):
    
        def build(self):
            return WindowManager
    
    
    if __name__ == "__main__":
        KingenApp().run()
    

    第四个问题值得自己提出一个问题,但可能涉及使用 kivy 语言。

    【讨论】:

    • 感谢您的回答,对我帮助很大!关于第四个问题,我同意它本身可能是一个问题。首先,我将尝试自己创建一个“update_label”方法,每次按下 + 或 - 按钮时都会触发该方法。这个方法只是把当前的Label文本去掉,用之前的文本+或-1代替,你觉得可行吗?
    • 是的,你可以这样做。使用 kivy 语言就可以为您做到这一点。
    • 到目前为止,我故意避免使用 Kivy 语言和 .kv 文件,因为我非常不清楚如何将 .kv 文件中的项目链接到 .py 文件中的项目。此外,我想在其他标签/按钮之间创建一些带有 for 循环的标签/按钮,但无法弄清楚如何在 .kv 文件中执行此操作,因此我决定将所有内容都转换为 .py 文件。
    • 您不必为整个应用程序使用 Kivy 语言。您可以为某些小部件创建规则。看看Introducing kv language 及其后续版本 (008)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多