我第一次与Kivy合作开发移动应用程序。我已经取得了一些进展,我希望有一个“主要”页面显示在其他任何内容之前。然后用户按下按钮,页面将变为更有用的东西。
此刻我收到一个巨大的按钮,当我点击它时没有任何反应......
我是kivy的新手,任何帮助都会很棒。
我试图用我“想”正在发生的事情来评论我的代码。
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.carousel import Carousel
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.graphics import Color
from kivy.app import App
from kivy.graphics.instructions import CanvasBase
CAROUSEL_OUTPUT = [0,1,2,3,4,5,6,7,8,9]
class MyApp(App):
def build(self):
#for starters just show a big button that will call
#showData when clicked.
b = Button(text='Click Me!!!')
self.layout = GridLayout(cols=1,rows=4,spacing=[2,0])
self.layout.add_widget(b)
#i pass the layout thinking that i can it
#not sure what i need to change to make it work
b.bind(on_press=(lambda e=1:self.showData(self.layout)))
return self.layout
def showData(self,layout):
self.Money = []
self.Trip = []
self.Gals = []
#set up the local layout
layout = GridLayout(cols=1,rows=4,spacing=[2,0])
row1 = BoxLayout(orientation='vertical')
row2 = BoxLayout(orientation='vertical')
row3 = BoxLayout(orientation='vertical')
w = self.makeCarousels(6,4,1)
l = Label(text='Please enter the total amount paid.')
row1.add_widget(l)
row1.add_widget(w)
layout.add_widget(row1)
w = self.makeCarousels(7,3,2)
l = Label(text='Please enter the total amount of gallons of gasoline purchased.')
row2.add_widget(l)
row2.add_widget(w)
layout.add_widget(row2)
w = self.makeCarousels(5,4,3)
b = Button(text='Click Me!!!')
b.bind(on_press=(lambda e=1: self.printCindexes()))
l = Label(text='Please enter the miles driven on your last tank.(Trip)')
row3.add_widget(l)
row3.add_widget(w)
layout.add_widget(row3)
layout.add_widget(b)
self.layout = layout
return layout
def makeCarousels(self,numOfCarous,placeHolder,row):
#this function just makes numOfCarous carousels
#and puts a '.' at placeHolder
check = False
layout = BoxLayout(orientation='horizontal')
for i in range(0,numOfCarous):
if i == (placeHolder - 1):
check = True
c = Carousel(direction = 'top')
else:
c = Carousel(direction = 'top')
if row == 1:
self.Money.append(c)
elif row == 2:
self.Gals.append(c)
elif row == 3:
self.Trip.append(c)
for num in CAROUSEL_OUTPUT:
l = Label(text=str(num))
c.add_widget(l)
if check:
l = Label(text='.')
layout.add_widget(c)
layout.add_widget(l)
check = False
else:
layout.add_widget(c)
return layout
def printCindexes(self):
self.calculateValues(self.Money,4,1)
self.calculateValues(self.Gals,3,2)
self.calculateValues(self.Trip,4,3)
print '\n'
def calculateValues(self,list,placeHolder,row):
numOfEntries = len(list)
total = 0.0
factor = 1.0
for n in range(0,placeHolder-1):
factor=factor*10.0
for n in list:
total += factor*n.index
factor = factor/10.0
if row == 1:
print 'Total Paid: $%6.2f' %(total)
elif row == 2:
print 'Total Gallons: %7.4f gallons' %(total)
elif row == 3:
print 'Total Trip: %5.1f miles' %(total)
if __name__ == '__main__':
MyApp().run()
再次感谢大家!!!!
答案 0 :(得分:3)
showData方法的第五行是layout = GridLayout(cols=1,rows=4,spacing=[2,0])
。这个覆盖你传递给函数的变量'layout' - python忘记了第一个layout
变量存在,只知道你刚刚创建的新GridLayout。在此之后,所有内容都被添加到新布局中,但是你不要告诉kivy用它做任何事情。
如果您只是删除该行,则会根据需要将所有新布局添加到根布局中,并更新可见的主屏幕以显示它们。
所以...应该解决你的一般问题,但一般结构似乎有点不理想。为什么不创建一个新的类,如class HomeGrid(GridLayout):
,然后给这个类提供你想要改变的方法,如showData
。这样你就不必跟踪类变量并传递它们,你正确地将对象变换与对象本身相关联。
我还强烈推荐阅读关于kivy语言的内容,这确实使布局设计变得非常容易。您可以非常轻松地为您的小部件制作基本模板,而不是像b.bind
这样的东西搞乱,一旦您绑定了许多函数,这些东西会很快变得难以处理。
答案 1 :(得分:2)
我不能同意@inclement。您应该使用Kivy Language。我建议你使用ScreenManager。下面我发布了一个previous answer的简化示例。请注意,您可以拥有任意数量的屏幕,并使用属性current
:
on_press: root.current = 'screen2'
Kivy的properties(或here)不仅仅是简单的属性。它们触发用于使接口保持最新的事件。您还可以使用Kivy语言绑定您的事件,如@inclement指出的那样。您只需要执行类似这样的操作即可调用Calc
类中定义的方法:
on_press: root.product(*args)
如果不复杂,甚至可以用Kivy语言执行。
on_press: _result.text = str(int(_a.text) + int(_b.text))
以下是您尝试实现的类似代码:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager
Builder.load_string("""
<Calc@ScreenManager>:
a: _a
b: _b
result: _result
Screen:
name: 'screen1'
Button:
size_hint: .3,.1
center: self.parent.center
text: 'Go to Screen 2'
on_press: root.current = 'screen2'
Screen:
name: 'screen2'
GridLayout:
cols: 2
Label:
text: 'Value 1'
TextInput:
id: _a
text: '3'
Label:
text: 'Value 2'
TextInput:
id: _b
text: '5'
Label:
text: 'Result'
Label:
id: _result
Button:
text: 'sum'
# You can do the opertion directly
on_press: _result.text = str(int(_a.text) + int(_b.text))
Button:
text: 'product'
# Or you can call a method from the root class (instance of calc)
on_press: root.product(*args)
Button:
text: 'Go to Screen 1'
on_press: root.current = 'screen1'
""")
class Calc(ScreenManager):
# define the multiplication of a function
def product(self, instance):
# self.result, self.a and self.b where defined explicitely in the kv
self.result.text = str(int(self.a.text) * int(self.b.text))
class TestApp(App):
def build(self):
return Calc()
if __name__ == '__main__':
TestApp().run()