Kivy-在.py文件中使用一个屏幕的TextInput来自另一个屏幕的文本 [英] Kivy - Use text from TextInput of one screen in another screen in .py file
问题描述
我在第一个屏幕上有一个TextInput,我想在第二个屏幕上的Label中使用接收到的文本.我怎样才能做到这一点?由于可以有不同的玩家,所以我创建了一个玩家"类,该类为每个玩家存储了姓名和他/她的得分.在第二个屏幕中,我还尝试创建一个可以编辑点(Label的文本)的按钮,但是当我单击它时,什么也没有发生.(我也是班上的新手.)
I have a TextInput on my first screen and I want to use the received text in a Label on my second screen. How can I do this? Since there can be different players, I created a class Players which stores for every player a name and his/her points. In the second screen, I also tried to create a button which can edit the points (text of Label), but when I click it, nothing happens. (I am also new to classes.)
在下面的代码中,我标记了相关的行.
In the code below, I marked the relevant lines.
所以概述:
-
第一个屏幕:使用textInput提取用户名+使用Player类创建播放器实例
First screen: extract user name(s) with textInput + create player instances with Player class
第二个屏幕:在标签中使用玩家名称+在标签中使用玩家点+创建2个按钮,可以从该点"标签中添加/减去点
Second screen: Use player name in a Label + use player points in Label + create 2 Buttons that add/subtract points from this 'point' Label
I know there is a similar case here, but it doesn't help me for my .py file: 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()
推荐答案
您的代码有几个问题:
- 创建任何
Widget
的实例时,将调用任何Widget
的__ init __()
方法.因此,在WindowManager.add_widget(FirstRound())
行处调用FirstRound
的__ init __()
方法.那时没有文本可以输入到WelcomeWindow
的TextInput
中,因此您当时无法获得播放器名称. -
Player
实例的创建(self.player1 = Player(name_input_player_i.text)
)在用户拥有之前创建了Player
实例输入玩家姓名的机会. - 在
FirstRound
的__ init __()
方法中使用WelcomeWindow()
会创建WelcomeWindow
与GUI中的那个无关.因此,从该实例中提取的任何信息都没有用. - 在您的
FirstRound
中,玩家点标签在创建Label
时从Player
类实例获取其数据.之后更改Player
的points
属性将不会对Label
产生影响.
- The
__init__()
method of anyWidget
is called when you create an instance of thatWidget
. So the__init__()
method ofFirstRound
is called at the lineWindowManager.add_widget(FirstRound())
. At that time no text can have been entered into theTextInput
ofWelcomeWindow
, so you cannot get the player name at that time. - The creation of the
Player
instance (self.player1 = Player(name_input_player_i.text)
) creates thePlayer
instance before the user has a chance to enter a player name. - The use of
WelcomeWindow()
in the__init__()
method ofFirstRound
creates a new instance ofWelcomeWindow
that is unrelated to the one in your GUI. So any info extracted from that instance is of no use. - In your
FirstRound
, the player points label gets its data from thePlayer
class instance at the time that theLabel
is created. Changing the thepoints
attribute ofPlayer
after that will have no effect on theLabel
.
可以通过将大多数代码从 FirstRound
的 __ init __()
方法中移出并将其放在 on_enter()中来解决第一个问题显示该
方法. Screen
时运行的
The first issue can be handled by moving most of your code out of the __init__()
method of FirstRound
, and place it in an on_enter()
method that is run when that Screen
is displayed.
第二个问题可以通过将 Player
实例的创建移到 go_further()
方法中来解决,因为它在离开 WelcomeWindow
.
The second issue can be handled by moving the creation of the Player
instance into the go_further()
method, since it gets executed when leaving the WelcomeWindow
.
可以通过使用 self.manager.get_screen('welcomewindow')
替换对 WelcomeWindow()
的那些使用来访问
The third issue can be handled by replacing those uses of WelcomeWindow()
with self.manager.get_screen('welcomewindow')
to access the actual instance of WelcomeWindow
that is in your GUI.
这是您代码的修改后的版本,可完成以下三件事:
Here is a modified version of your code that does those three things:
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()
第四个问题值得探讨,但可能涉及使用猕猴桃语言.
The fourth issue deserves a question of its own, but likely involves using kivy language.
这篇关于Kivy-在.py文件中使用一个屏幕的TextInput来自另一个屏幕的文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!