如何通过'on_<属性>'回调将文本插入TextInput
我正在用kivy做一个简单的计算器,想用TextInput
来显示屏幕上的内容。我不太确定用TextInput
还是Label
更好,不过我觉得TextInput
可能更合适(也许我错了?)。现在界面基本搭建好了,所有的按钮和它们对应的文本框('0', '1', '2', '+', '='
等等)都已经准备好了。每次用户按下一个按钮,那个按钮上的文本就会被添加到calc_string
中,当按下'='按钮时,这个字符串会被计算。基本上,功能都正常,但我的输出全都打印在控制台上,因为我无法把字符串插入到TextInput
的显示区域。我尝试在一个回调函数(screen_callback
)中设置TextInput
的文本,这个回调是通过一个绑定到TextInput
的on_property
方法触发的,但没有成功。我该怎么做才能实现这个功能?这是可能的吗?
main.py:
#!/usr/bin/env python
import kivy
kivy.require('1.8.0')
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.properties import ListProperty, ObjectProperty, StringProperty, NumericProperty
class Screen(TextInput):
pass
class Calculator(BoxLayout):
function_btns = ListProperty(['+', '-', '*', '/', '^', 'Mem <-', 'Mem ->', 'Clear'])
digit_btns = ListProperty(['7', '8', '9', '4', '5', '6', '1', '2', '3', '0', '.', '+/-'])
eval_string = StringProperty() # one of these strings is probably unnecessary
calc_string = StringProperty()
result = NumericProperty(0)
def build_calc(self):
# add screen textinput
self.add_widget(Screen(text='0', multiline=False, on_calc_string=self.screen_callback))
#create inner boxlayout to hold 2 button gridlayouts
main_buttons_box = BoxLayout(orientation='horizontal', size_hint=(1, 0.75))
# create 2 button gridlayouts
digit_grid = GridLayout(cols=3, rows=4, size_hint=(0.5, 1))
function_grid = GridLayout(cols=1, size_hint=(0.5, 1))
# populate grids with buttons
for i in self.digit_btns:
digit_grid.add_widget(Button(text=str(i), on_press=self.button_callback))
for f in self.function_btns:
function_grid.add_widget(Button(text=str(f), on_press=self.button_callback))
# add grids to inner boxlayout
main_buttons_box.add_widget(digit_grid)
main_buttons_box.add_widget(function_grid)
# add inner boxlayout to main grid(root)
self.add_widget(main_buttons_box)
# finally, add boxlayout at bottom of main grid and insert equals btn
equals_box = BoxLayout(size_hint=(1, 0.25))
equals_box.add_widget(Button(text='=', on_press=self.button_callback))
self.add_widget(equals_box)
def button_callback(self, instance):
value = instance.text
if value == '=':
try:
self.result = eval(self.eval_string)
self.calc_string = str(self.result)
self.eval_string = ''
except SyntaxError:
self.calc_string = 'Error: Invalid Input'
else:
self.eval_string += value
self.calc_string = self.eval_string
print self.calc_string
def screen_callback(self, instance):
instance.text = self.calc_string # not working
print 'seeing this!!!' # not working
class CalcApp(App):
def build(self):
calc = Calculator()
calc.build_calc()
return calc
if __name__ == '__main__':
CalcApp().run()
kv文件:
#kivy: 1.0
<Screen>:
size_hint: 1, 0.25
<Calculator>:
orientation: 'vertical'
1 个回答
1
你的 Screen
组件没有 calc_string
这个属性,所以 on_calc_string
在这里没有任何作用:
self.add_widget(Screen(text='0', multiline=False, on_calc_string=self.screen_callback))
你需要把这个绑定到 Calculator
上。Kivy 提供了一个很方便的 setter
方法来帮助你实现这一点:
scr = Screen(text='0', multiline=False)
self.add_widget(scr)
self.bind(calc_string=scr.setter('text'))
而且,使用 kv 语言可以让这个过程变得简单得多。你可以在 kv 文件中定义整个组件的布局……我不会重构你整个组件,但这里有个例子:
<Calculator>:
orientation: 'vertical'
Screen:
text: root.calc_string
root
指的是规则中的根组件,这里是 Calculator
。每当 root.calc_string
被修改时,Screen
的 text
属性会自动更新。