1

我第一次使用 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()

再次感谢大家!!!!

4

2 回答 2

3

showData 方法的第五行是layout = GridLayout(cols=1,rows=4,spacing=[2,0]). 这会覆盖您传递给函数的变量“布局” - python 忘记了第一个layout变量存在并且只知道您刚刚创建的新 GridLayout。在此之后,一切都被添加到新布局中就好了,但你不要告诉 kivy 对它做任何事情。

如果您只是删除该行,所有新布局都会像您想要的那样添加到您的根布局中,并且可见的主屏幕会更新以显示它们。

所以......这应该可以解决您的一般问题,但一般结构似乎有点不理想。为什么不创建一个新类,比如class HomeGrid(GridLayout):,然后给这个类你想要改变自己的方法,比如showData。这样您就不必跟踪类变量并传递它们,您将对象转换与对象本身正确关联。

我也强烈推荐阅读 kivy 语言,它确实让布局设计变得非常容易。您可以在那里非常轻松地为您的小部件制作基本模板,而不是b.bind在绑定许多功能后很快就会变得笨拙。

于 2013-07-23T23:08:53.340 回答
2

我完全同意@inclement。您应该使用Kivy 语言。我建议您使用ScreenManager。下面我发布了我之前给出的答案的简化示例。请注意,您可以拥有任意数量的屏幕,并在使用属性之间进行交换 current

on_press: root.current = 'screen2'

Kivy的属性(或此处)不仅仅是简单的属性。它们触发用于使界面保持最新的事件。正如@inclement 指出的那样,您还可以使用 Kivy 语言来绑定您的事件。您只需要执行以下操作即可调用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()
于 2013-07-24T04:38:01.203 回答