2

我对 Kivy 比较陌生,需要做一些看似简单的事情,但我仍然无法做到:我需要根据代码设置行的位置。我遇到的问题是,我当前的代码是围绕未来支持手势的需求构建的,并且由于基于 Kivy 包含的展示示例应用程序而继承了一些复杂性。

我需要做的是在加载“前”屏幕时定义 ID 为“测试”的线的点。而已。由于积分是可变的,我知道我需要在 Front.kv 之外执行此操作

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

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()

前线.kv

HomeScreen:
    name: 'Front'

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

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

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))

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

    if str(self.screens[index].name) == 'Front':
        self.ids.test.points = (100, 100, -300, 300)

感谢您的阅读,感谢您的宝贵时间!

4

1 回答 1

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之外,您无法对其进行任何操作。把它想象成 MsPaint,你的橡皮擦基本上是& 。Ctrl+Adelete

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

然后id为该小部件设置一个并使用以下代码:

with <your id>.canvas:  # or canvas.before / canvas.after
    # instructions here e.g.:
    SmoothLine(points=<variable>)
于 2016-06-27T16:37:04.750 回答