【问题标题】:Using and moving Widgets/Buttons in Kivy在 Kivy 中使用和移动小部件/按钮
【发布时间】:2014-08-12 19:58:53
【问题描述】:

我刚开始使用 Kivy,它与我习惯的不同,如果我犯了愚蠢的错误,请道歉!

现在我正在尝试创建一个执行以下操作的应用:

  • 允许创建节点(目前为省略号)。
  • 允许用户通过拖动来定位节点。
  • 允许用户用线连接节点。

到目前为止,我已经实现了第一个,并且在某种程度上实现了第二个。

现在我的拖动效果不太好。如果我移动鼠标太快,它会取消移动方法(因为它不再接触)。有没有更好的方法来产生拖动或者我只是增加刷新率(如果有的话怎么办?)。

def on_touch_move(self, touch):
   if self.collide_point(touch.x, touch.y):
       self.pos=[touch.x-25, touch.y-25]

我尝试使用 Buttons,使用 on_press 方法更好地跟踪移动。但是现在我很难更新按钮的位置(主要是语法)。

    class GraphNode(Button):
       background_disabled_down=1
       background_disabled_normal=1

       def moveNode(self):
           with touch:
               self.pos=[touch.x-25, touch.y-25]

我不知道如何使用触摸值,并不断收到一系列错误。 (显然目前的尝试是行不通的,我只是觉得很好笑)。

您可能会说,我也不知道如何摆脱按钮图形,因为我想使用椭圆。如果有人可以告诉我如何在按下按钮时更改椭圆的颜色,那将是一个额外的奖励!

kv 文件:

    <GraphNode>:
        size: 50, 50
        canvas:
            Ellipse:
                pos: self.pos
               size: self.size
        on_press:
            root.moveNode()

我希望能够使用触摸信息来更新位置,但这里不知道如何实现。

完整的核心python代码:

    from kivy.app import App
    from kivy.uix.widget import Widget
    from kivy.uix.button import Button
    from kivy.properties import NumericProperty, ReferenceListProperty,\
        ObjectProperty
    from kivy.graphics import Color, Ellipse, Line


    class GraphInterface(Widget):
        node = ObjectProperty(None)



    class GraphApp(App):

        def build(self):
            node = GraphNode()
            game = GraphInterface()

            createNodeButton = Button(text = 'CreateNode', pos=(100,0))
            createEdgeButton = Button(text = 'CreateEdge')
            game.add_widget(createNodeButton)
            game.add_widget(createEdgeButton)

            def createNode(instance):
                game.add_widget(GraphNode())
                print "Node Created"

            def createEdge(instance):
                game.add_widget(GraphEdge())
                print "Edge Created"

            createNodeButton.bind(on_press=createNode)
            createEdgeButton.bind(on_press=createEdge)
            return game

    class GraphNode(Button):

        def moveNode(self):
            with touch:
                self.pos=[touch.x-25, touch.y-25]


       #def onTouchMove(self, touch):
       #   if self.collide_point(touch.x, touch.y):
       #       self.pos=[touch.x-25, touch.y-25]
        pass

    class GraphEdge(Widget):

        def __init__(self, **kwargs):
            super(GraphEdge, self).__init__(**kwargs)
            with self.canvas:
                Line(points=[100, 100, 200, 100, 100, 200], width=1)
        pass

    if __name__ == '__main__':

        GraphApp().run()

如果您需要任何其他信息,或者有任何不清楚的地方,请告诉我!

编辑:第二个问题移至:Creating a dynamically drawn line in Kivy

【问题讨论】:

  • 您确实需要为此提出两个问题。 SO 的部分目标是为其他人构建一个参考库以供以后查找,因此每个问题都单独提出是很重要的。
  • 没问题,我会编辑并提出一个新问题。给我一分钟做出改变:)。

标签: python python-2.7 drawing kivy


【解决方案1】:

首先,您应该阅读 Kivy 中的 touch events。这里特别感兴趣的是关于抓取触摸事件的部分。基本上,您可以“抓取”一个触摸,以确保抓取小部件将始终从该触摸接收更多事件 - 换句话说,该触摸事件之后的 on_touch_moveon_touch_up 将被发送到您的小部件。

基本示例:

class MyWidget(Widget):
    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            touch.grab(self)
            # do whatever else here

    def on_touch_move(self, touch):
        if touch.grab_current is self:
            # now we only handle moves which we have grabbed

    def on_touch_up(self, touch):
        if touch.grab_current is self:
            touch.ungrab(self)
            # and finish up here

但是,更好!如果您希望能够拖动小部件,Kivy 已经有了:Scatter

只需将您的小部件包装在Scatter 中,您就可以将其拖动。您还可以使用多点触控来旋转和缩放Scatter,但您可以轻松禁用它 (kv):

FloatLayout:
    Scatter:
        do_scale: False
        do_rotation: False

        MyWidget:

旁注 - 这是不正确的:

class GraphNode(Button):
   background_disabled_down=1
   background_disabled_normal=1

background_disabled_downbackground_disabled_normalKivy properties - 您应该在 __init__ 中设置这些值。

强制这些值:

class GraphNode(Button):
    def __init__(self, **kwargs):
        super(GraphNode, self).__init__(background_disabled_down='',
                                        background_disabled_normal='', **kwargs)

建议这些值(更好的选择):

class GraphNode(Button):
    def __init__(self, **kwargs):
        kwargs.setdefault('background_disabled_down', '')
        kwargs.setdefault('background_disabled_normal', '')
        super(GraphNode, self).__init__(**kwargs)

最后,请注意这些属性是filenames pointing to the images used for the disabled Button。如果您删除这些值并禁用您的按钮,它将不会绘制任何背景。

【讨论】:

  • 真的很有帮助!您准确地解释了我需要什么,并提供了一些不错的选择。节点与抓取方法运行良好,但是我有一个问题。我还没有测试 Scatter,所以它可能不会出现在那里。但我目前能够重叠两个节点,然后将同时抓取两个节点。有没有简单的解决方法,还是我应该只依赖 Scatter?
  • 如果 Ryan P 没有回应:我自己找到了解决方案,通过查看这里:kivy.org/docs/api-kivy.uix.widget.html#widget-event-bubbling。添加超级返回会停止抓取两个小部件。
  • 事件传播通常可以通过从事件处理程序返回 True 来取消。
猜你喜欢
  • 1970-01-01
  • 2021-06-08
  • 1970-01-01
  • 2021-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多