在Kivy中按id设置画布对象属性

时间:2016-06-21 19:01:56

标签: kivy kivy-language

我对Kivy来说相对较新,需要做一些看似简单的事情,但这仍然让我难以理解:我需要根据代码设置一条线的位置。我遇到的问题是我当前的代码是围绕未来支持手势的需求而构建的,并且由于基于Kivy附带的展示示例应用程序而继承了一些复杂性。

我需要做的是在加载'Front'屏幕时定义id为'test'的行的点。而已。由于这些点是可变的,我知道我需要在Front.kv之外做这个。

这是我的代码(或参见https://github.com/blyncsync/bs-user-app/

<form name="userForm" ng-submit="addRowToGrid()">
    <label>phone number</label>
    <input type="text" name="pidm" 
           class="form-control" 
           ng-model="create.pidm">
    <label>phone number</label>
    <input type="text" name="areaCode" 
           class="form-control" 
           ng-model="create.areaCode">
    <label>phone number</label>
    <input type="text" name="phoneNumber" 
           class="form-control" 
           ng-model="create.phoneNumber">
    <label>phone number</label>
    <input type="text" name="sequenceNumber" 
           class="form-control" 
           ng-model="create.sequenceNumber">
    <label>phone number</label>
    <input type="text" name="phoneCode" 
           class="form-control" 
           ng-model="create.phoneCode">
    <label>phone number</label>
    <input type="text" name="comment" 
           class="form-control" 
           ng-model="create.comment">
    <label>phone number</label>
    <input type="text" name="dataOrigin" 
           class="form-control" 
           ng-model="create.dataOrigin">
    <label>phone number</label>
    <input type="text" name="userId" 
           class="form-control" 
           ng-model="create.userId">
    <button type="submit" class="btn btn-primary">
        Submit
    </button>
</form>

Front.kv

from time import time
from kivy.app import App
from kivy.config import Config
Config.set('graphics', 'width', '480')
Config.set('graphics', 'height', '800')
from os.path import dirname, join
from kivy.lang import Builder
from kivy.properties import NumericProperty, StringProperty, BooleanProperty, ListProperty
from kivy.clock import Clock
from kivy.animation import Animation
from kivy.uix.textinput import TextInput
from kivy.uix.screenmanager import Screen
from kivy.gesture import Gesture, GestureDatabase
from kivy.graphics import Color, Ellipse, Line

#This database can compare gestures the user makes to its stored gestures 
#and tell us if the user input matches any of them.
gestures = GestureDatabase()

top_to_bottom_line = gestures.str_to_gesture('eNq1l0tu2zAQQPe6SLypwflzLpBuC+QARZoIidE2EWz3d/uSQ9uSU6deCNJG9njm8fMomlptvm5+/lk/9bv9j23ffTzch9StHgfo7m5e7r/3N92A5WO5Ube7u9ntt69f+135yt3q2yDd6iLkLtK6QSvKSv3wunnZ17Jcy/ydsk81qxug9aB24U8pAexu01rcJbEyuWLmLLU3v+uvVH9NAMAikDKJA2blbvfl/v+tcLQi3dOhAVHQ5J4MMBmXBp4O7MQuJJrIQEAl5evsGDjYiY0Z3RBIEdELdmRDFpMsQE7lY+Ffh+eA+xHOJqqixGrsBX/s+YfAI2XylByzlZlTuYrHmH2EpfAYeDriyetsUyJOIlbuM/FhFWUpfIjFk1jktiosoZVFV5fGiGciJhVCSVYc03V6mEVfhk4hlmAhenglWogeWkkWoodVOlkFb/sIEaA6+Tx4SCVfBM7hlE9OgTJOKELz6OGUT07LLlu7zJ5ZMJUR2Dx8SGVZCh9W2ZbCh1f2hfASZuVgtjJMGMyPm7HwvJ1Mwq3QYvyQK7IYP+yKnfggx3oULYy5/NArvhRfw6/CYvzwq6NfBMuEGaysTFZINpMfflUW44dfHf2i5JRPRzHNM//JNfzq6BfNTZAQPAMj+cz+W/i10S/RlIE0s/8Wfm30S5JcxiHgTHzotVEvWc5Igs4Aplwev2v8+rrwsO37l9Ph37Se/s261S0jr1N3y7mUd/vBcndfg1Rgk0tLhknL8JbRykwjmFMLYgRV1j69uGZAy4DIEGtl2IIpgpzeNloyaJoB1Mo4guD/dJKUW4a8m8H5Qiv6bjrBhXR7Lx2zXxh6nowBFVsPfRokOUdRyfA0zYA20Q7TYKILZdM5BT+UTacRcpt952nQvAXlLNgm3HUa1HyhVTvLaBY8nwXbwH068LLXRhBSOovavy1AgjcpZxNtkVLG3hb8c795et7X19JSfEt1PdcX1V+bx/1zRLkspzeq4sV6//qt396/PPSRJXGWq/HD0/l52L4+/nho5Cp8be6kVJ5zES7n4PLArf8CZ84KGA==',)
bottom_to_top_line = gestures.str_to_gesture('eNq1WMFuIzcMvc+PJJcaIimS0g+k1wL5gCJNjCTYbWI43rb79+VQmhmpme0UNcaHN84z+STx0ZKc29cvr398PzwfPy7fzsfh5/o8heH26QTD/c3bw+/Hm+GE9tYeNHzc33xczu9fjh/2Zxxuv554uF0Vufew4SSjlFr+6f317TKmpTEt/yDtlzFqOEGZwTiF75YCONz9FA6SOWXCCX06f40f03AXDgFZjJ8Qkgwfvz38+zDRh+HheRqBIoBiRTKF50kckqlOSITb4r500H3Ek4vnWZxJOVtuxUUbNCvghMi6qY1efIRdtNG1aRdtdxMXN6MlCoYJQa5SdztRd1J3PzHvo07uKC2OEjKS5IqRrxJ3S4n2EXdPifcRd0tpsRQx5JTThFequ6WU91GPbmmEndTd07h4CszEqBWjYqNu+5l1aEGKIW6ru6mRd1J3V+PiKmCMYqIFSdJV6u5qXFwNWSOpVLSebNQDRtvVHENm3hRnN5UXUwPHLCIThhwX9SCUzOiCduhtu8ruKtNe8m4rL7aGEFVJJoxtT9ppjYoVIcXtyrP7ytVXN4/JrCvIwbq1qPvIdopSqojBV7al785ynvUXVw3TvAO7PEOOacIktKkubq3ArC6JE8eK1iWteg7MaUKF7YuMuLNCs3rOUSk6stW6nTtgBkkV6T9sBuK+Ck/iQIEEeEKJ103dbZXZVjvw7ALHFRWuM1XcVJlNhZwTZ3aUsOyS/1Ne3VWdXUWUlEQqasRrGl7dVJ1NtY1bNUrFhPHKubutOtuKyXrZeqIg45ar42+Bx/Px+Dbf7FXGq73qcHtHiQ9huAMZH5eTpuFhJGNH5o5UJ1PoyGSDNy8aI6CNUDjk9qVjBLYRKaxEUImgEpHK0LEhbedbGZrbCJKSJi0p0KfJGKFtxDRaLQmOJIVSkpRbEuizVq71AY/A4Gm5liQ4SStTyNhFyEpEKYlmj4jUFy2OEaU+mkpELkNzSzIWspREtZBlbVk7stidSxVUnJS6nNyR4CSE0LFUWehY/rwwO3+7EK2Jdb1c2FTZ2LG5styyCmuDSBeCNVE7NlY2dSxXtlu1luayi0nHps+2AHQlSLUwgG250yRHrV05rMl1NudaLuCmPWIIKyUA6ULqYkE7VtdGTM2IdgupiblloVYUQ8eutKndcbuQWl5s6xFBVxaA1BQyQm0JjP9gV0bkNqR+KQGlY2sbo3bstKy2JSLS2uxqPeKPQyh0IdUBgk1t+w33ULb0l+Pr88vF/6limz/yaIbRf74+XV6cjbZhQiEv71+P54e3x6N/wH6+jnw9b349nd+fvj0WMbFeOrDNyY5G+wZJGm/idowc/gbsOJ0Z',)
left_to_right_line = gestures.str_to_gesture('eNq1mE1y3DYQhfe8iLXRFPofuICyTZUOkFLsKVllR5qSxkl8+zS7ZWWaFYfYaDajeQQf8PUDAVBXD18e/vx+uD++nL89H5dfXr9Pbbn6dILl9sPj3R/HD8sJ/U//ouXl9sPL+fnpy/HFf/Jy9fUky9V/mtxGs+Wkq5X5/aenh8fzeltfbxs/ue3XtdVyghzBOoTvfgvgctMOrQFpgz6odeEm1Nfx/L1ep+Xmuh2MGzJAM8HBXWV5+f3u/7vh6EaW+5/3cP/DvHU1Q0W2gebtd80DHSzNr+3AQm0gNGC3aXS8bvKvvWqXJm1oEzBk3bfvYT8m7QmVrI1GgJ3Jdu0xEkCYtG/aAQEVeus89iuPGPY0Zy8ioAjDBmjX1vftI1iUOXseStTfEoCJ6kS2aO/mH+HiZLiso1kfnYFJWPftKcKlyXAZGoqwsBFYh0H7/pEu0bv5R7w0GS+JzxkRVC+NDb931z7SJXsv+wiXJsMlAJRh0vvwpaftLwwc4fJkuL4aNP/YayPYLz5HuDwZLjLSIOjWjTxb3F8aOMLlyXCxIfo1BGZFvz4x/kiX7d38I16ejNcfWRrGAxuxNBu79hLxCryXfaQrk+m+7bU4RFHH/tIjka5Mpuvbiu+2zafoMCXfBfb9I12ZTNc3WzHxChHjMLS+//RKxCuT8b5NHEH0rdcmFjeNgHUmYPf3w8IAMFITtS77y4NGwEpz9uzLjwJZb6aGfT9fjXxV5uxNwfXmxy1jJtzf2DXiVZuyh8a9DViH7se53vZnj0a4OubsyY9UPvFxLcx6wNq1t4jW5qIFVWnYzISHL6Iz9hGtzUULozeVgb65+PFkYuJbJGtzySIOXxO88MqjC1lMnPXt4ePz8fj49i5gur4M+NWrG6ZDW24Yzb/OJ+vLnWtatLFqCpdab6FJ0WDVxqufpoarBtCLSCEiF5FDJC2ihGhYRF1FhNqRhUhwGJcfu2gRaGj1tmDzel6KI+B8aSpi0NGPMryKgUejFTHwuDKPwPNdoYiBx1J7DzzupToj8AS898uPXrQIPMHaQeAJFy9owedHv6oGoBhUNQilb9pSqqOqwehTsqqS0werGpSKG9VSlaoGmtJmZDktqTpATsw6jQCCTbk6AKZqVaVUKxsk26ZmkGyyaZts2qqabFqrA8mmG99k00qBybZJCJPNas0w2ayyYbL1OjJMtr7xTba+8U22vvFNtrHxTbZR2TDZRnWgZBu9qsFmrfoSplrHS5Rq7Y041U1vkmrNjYLNYNObpVpzo57qpreRaq0Zt1QrGycb1DFwstXH2E+TqdbeONmwzhJONqzEnGy46S3ZNs8QJxttxpBsVNkk2TbPmyQbVWJJNqpjkGTjWnU/r97l1vX5+HD/+bz+t8lPrzdr5i7+9fDp/Dk0XwJzLrl6fvp6fL57/HiMKxbb7aq/bqy/nZ6fPn37mF7dO/NXYD9kNfa5I92P6utWf/gHjU3d+Q==',)
right_to_left_line = gestures.str_to_gesture('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'  )

gestures.add_gesture(top_to_bottom_line)
gestures.add_gesture(bottom_to_top_line)
gestures.add_gesture(left_to_right_line)
gestures.add_gesture(right_to_left_line)

def simplegesture(name, point_list):
    """
    A simple helper function
    """
    g = Gesture()
    g.add_stroke(point_list)
    g.normalize()
    g.name = name
    return g

class HomeScreen(Screen):
    fullscreen = BooleanProperty(False)

    def add_widget(self, *args):
        if 'content' in self.ids:
            return self.ids.content.add_widget(*args)
        return super(HomeScreen, self).add_widget(*args)

    def on_touch_down(self, touch):
        # start collecting points in touch.ud
        # create a line to display the points
        userdata = touch.ud
        with self.canvas:
            #Color(1, 1, 0)
            #d = 30.
            #Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
            userdata['line'] = Line(points=(touch.x, touch.y))

        event_handled = False
        for child in self.children:
            if not event_handled:
                if child.dispatch('on_touch_down', touch):
                    event_handled = True

        if not event_handled:
            print touch.x, touch.y

        #return True

    def on_touch_move(self, touch):
        # store points of the touch movement
        try:
            touch.ud['line'].points += [touch.x, touch.y]
            return True
        except (KeyError) as e:
            pass

    def on_touch_up(self, touch):
        # touch is over, check if it matches some known gesture.
        g = simplegesture('', list(zip(touch.ud['line'].points[::2],
                                       touch.ud['line'].points[1::2])))

        # use database to find the more alike gesture, if any
        g2 = gestures.find(g, minscore=0.70)

        print(g2)
        if g2:
            if g2[1] == left_to_right_line:
                print("left_to_right_line")
            if g2[1] == right_to_left_line:
                print("right_to_left_line")
            if g2[1] == top_to_bottom_line:
                print("top_to_bottom_line")
            if g2[1] == bottom_to_top_line:
                print("bottom_to_top_line")

class HomeApp(App):
    index = NumericProperty(-1)
    current_title = StringProperty()
    time = NumericProperty(0)
    show_sourcecode = BooleanProperty(False)
    sourcecode = StringProperty()
    screen_names = ListProperty([])
    hierarchy = ListProperty([])

    def build(self):
        self.title = 'BlyncSync'
        self.screens = {}
        self.available_screens = [
            'Login', 'Register', 'Forgot Password', 'Front']
        self.screen_names = self.available_screens
        curdir = dirname(__file__)
        self.available_screens = [join(curdir, 'data', 'screens',
            '{}.kv'.format(fn)) for fn in self.available_screens]
        self.index = (self.index + 1) % len(self.available_screens)
        screen = self.load_screen(self.index)
        sm = self.root.ids.sm
        sm.switch_to(screen, direction='left')
        self.current_title = screen.name

    def on_pause(self):
        return True

    def on_resume(self):
        pass

    def go_screen(self, idx):
        self.index = idx
        self.root.ids.sm.switch_to(self.load_screen(idx), direction='left')

    def load_screen(self, index):
        if index in self.screens:
            return self.screens[index]
        screen = Builder.load_file(self.available_screens[index].lower())
        self.screens[index] = screen
        return screen

if __name__ == '__main__':
    HomeApp().run()

具体来说,我想定义test.points:

HomeScreen:
    name: 'Front'

    FloatLayout:
        canvas:
            Color:
                rgba: 1, .1, .1, .9
            SmoothLine:
                id: test
                points: (100, 100, 200, 200)

我尝试将以下代码段添加到load_screen,但无济于事:

scale = 50 # 0 < scale < 100; arbitrary/defined programmatically
angle = scale/100*180 # convert a scale from 0-100 to an angle from 0-180
length = 100 # arbitrary
center_x = 100
center_y = 100
test.points = (center_x, center_y, center_x + length*cos(angle), center_y + length*sin(angle))

感谢您的阅读,感谢您的光临!

1 个答案:

答案 0 :(得分:0)

如果问题很有趣,通常很高兴看到更多的代码而不是更少的代码,但是......为什么要发布on_pause之类的空函数?如果它是空的,它只会使你的代码更长。

接下来,ids可能只是小部件,但即使不是,此代码也会向您显示Instructions没有这样的内容:

from kivy.lang import Builder
from kivy.base import runTouchApp
from kivy.uix.boxlayout import BoxLayout
Builder.load_string('''
<Test>:
    canvas:
        Color:
            rgba: 1, 0, 0, 1
        Rectangle:
            id: test
            size:self.size
            pos:self.pos
    Button:
''')
class Test(BoxLayout):
    def __init__(self, **kw):
        print '\n'*2, self.ids, '\n'*2
        super(Test, self).__init__(**kw)
runTouchApp(Test())

即使它有可能使用id,它仍然已被绘制,除了clearing canvas之外你无法做任何事情(这也会清除小部件)。想象一下这是MsPaint,你的橡皮擦基本上是Ctrl+A&amp; delete

你可以做的是使用另一个小部件及其画布(不知道你是否要将该FloatLayout用于除绘图之外的任何其他内容),例如StencilView(“裁剪”画布)或简单的Widget会做......甚至是FloatLayout。

然后为该小部件设置id并使用以下代码进行编码:

with <your id>.canvas:  # or canvas.before / canvas.after
    # instructions here e.g.:
    SmoothLine(points=<variable>)