Kivy - 在 .py 文件中的另一个屏幕中使用来自一个屏幕的 TextInput 的文本

Kivy - Use text from TextInput of one screen in another screen in .py file

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

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

总览:

我知道这里有一个类似的案例,但它对我的 .py 文件没有帮助:

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()

您的代码有几个问题:

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

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

第二个问题可以通过将 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 语言。