Kivy - 在 .py 文件中的另一个屏幕中使用来自一个屏幕的 TextInput 的文本
Kivy - Use text from TextInput of one screen in another screen in .py file
我的第一个屏幕上有一个 TextInput,我想在第二个屏幕上的标签中使用接收到的文本。我怎样才能做到这一点?由于可以有不同的玩家,我创建了一个 class 玩家,它为每个玩家存储了一个名字和 his/her 分。在第二个屏幕中,我还尝试创建一个可以编辑点(标签文本)的按钮,但是当我单击它时,没有任何反应。 (我也是 classes 的新手。)
在下面的代码中,我标记了相关行。
总览:
第一个屏幕:使用 textInput 提取用户名 + 使用 Player 创建播放器实例 class
第二个屏幕:在标签中使用玩家名称 + 在标签中使用玩家点数 + 创建 2 个 add/subtract 指向此 'point' 标签的按钮
我知道这里有一个类似的案例,但它对我的 .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__()
方法。那时 WelcomeWindow
的 TextInput
中无法输入任何文字
, 所以你无法获取到当时的玩家名字。
- 创建
Player
实例 (self.player1 = Player(name_input_player_i.text)
) 在用户有机会输入玩家名称之前创建 Player
实例。
- 在
FirstRound
的 __init__()
方法中使用 WelcomeWindow()
会创建一个与您的 GUI 中的实例无关的 WelcomeWindow
的新实例。因此从该实例中提取的任何信息都没有用。
- 在您的
FirstRound
中,玩家点数标签在创建 Label
时从 Player
class 实例获取数据。之后更改 Player
的 points
属性将不会影响 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 语言。
我的第一个屏幕上有一个 TextInput,我想在第二个屏幕上的标签中使用接收到的文本。我怎样才能做到这一点?由于可以有不同的玩家,我创建了一个 class 玩家,它为每个玩家存储了一个名字和 his/her 分。在第二个屏幕中,我还尝试创建一个可以编辑点(标签文本)的按钮,但是当我单击它时,没有任何反应。 (我也是 classes 的新手。)
在下面的代码中,我标记了相关行。
总览:
第一个屏幕:使用 textInput 提取用户名 + 使用 Player 创建播放器实例 class
第二个屏幕:在标签中使用玩家名称 + 在标签中使用玩家点数 + 创建 2 个 add/subtract 指向此 'point' 标签的按钮
我知道这里有一个类似的案例,但它对我的 .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__()
方法。那时WelcomeWindow
的TextInput
中无法输入任何文字 , 所以你无法获取到当时的玩家名字。 - 创建
Player
实例 (self.player1 = Player(name_input_player_i.text)
) 在用户有机会输入玩家名称之前创建Player
实例。 - 在
FirstRound
的__init__()
方法中使用WelcomeWindow()
会创建一个与您的 GUI 中的实例无关的WelcomeWindow
的新实例。因此从该实例中提取的任何信息都没有用。 - 在您的
FirstRound
中,玩家点数标签在创建Label
时从Player
class 实例获取数据。之后更改Player
的points
属性将不会影响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 语言。