【问题标题】:Move widgets in Scatter individually in Python code在 Python 代码中单独移动 Scatter 中的小部件
【发布时间】:2022-01-22 06:55:45
【问题描述】:

我正在尝试创建一个自定义小部件,我想将多个实例添加到布局中。这些小部件应该是可拖动的。

获得所需结果的一种方法是使用我已经成功实现的DragBehavior Mixin。现在我想使用Scatter 获得相同的结果。

from kivy.app import App
from kivy.core.window import Window
from kivy.graphics import Color, Rectangle
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.uix.scatter import Scatter


class MyLabelWidget(Label):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        with self.canvas:
            Color(0, 1, 0, 0.25)
            self.background_rect = Rectangle(pos=self.pos, size=self.size)

        self.bind(pos=self.update)

    def update(self, *args):
        self.background_rect.pos = self.pos


class ScattererApp(App):
    def build(self):
        Window.size = 400, 400

        layout = FloatLayout()
        scatter = Scatter()

        widget_1 = MyLabelWidget(
            size_hint=(None, None),
            size=(100, 100),
            pos=(50, 50),
            text="Drag me",
        )
        widget_2 = MyLabelWidget(
            size_hint=(None, None),
            size=(100, 100),
            pos=(150, 150),
            text="Drag me, too",
        )

        layout.add_widget(scatter)
        scatter.add_widget(widget_1)
        scatter.add_widget(widget_2)

        return layout


ScattererApp().run()

但不幸的是,当我尝试拖动一个小部件时,所有小部件的位置都会发生变化:

我想要的是能够单独拖动小部件,就像我对 DragBehavior 实现所做的那样:

from kivy.app import App
from kivy.core.window import Window
from kivy.graphics import Color, Rectangle
from kivy.uix.behaviors import DragBehavior
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label


class DragLabel(DragBehavior, Label):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.drag_rectangle = (self.x, self.y, self.width, self.height)
        self.drag_timeout = 10000000
        self.drag_distance = 0

        with self.canvas:
            Color(0, 1, 0, 0.25)
            self.background_rect = Rectangle(pos=self.pos, size=self.size)

        self.bind(pos=self.update)

    def update(self, *args):
        self.drag_rectangle = (self.x, self.y, self.width, self.height)
        self.background_rect.pos = self.pos


class DraggerApp(App):
    def build(self):
        Window.size = 400, 400
        layout = FloatLayout()

        widget_1 = DragLabel(
            size_hint=(None, None),
            size=(100, 100),
            pos=(50, 50),
            text="Drag me",
        )
        widget_2 = DragLabel(
            size_hint=(None, None),
            size=(100, 100),
            pos=(150, 150),
            text="Drag me, too",
        )

        layout.add_widget(widget_1)
        layout.add_widget(widget_2)

        return layout


DraggerApp().run()

我的 update 回调方法似乎永远不会被调用,尽管我 bound 它位于 MyLabelWidget 对象的位置上,正如 Alexander Taylor 的 Updating canvas instructions declared in Python 文章中所述:

self.bind(pos=self.update)

有没有什么方法可以在不使用Kv language的情况下达到预期的效果?

【问题讨论】:

    标签: python python-3.x kivy draggable scatter


    【解决方案1】:

    好的,我似乎错误地使用了 Scatter 类。每个小部件本身都应该是一个 scatter,而不仅仅是添加到单个 scatter 实例中:

    from kivy.app import App
    from kivy.core.window import Window
    from kivy.graphics import Color, Rectangle
    from kivy.uix.floatlayout import FloatLayout
    from kivy.uix.label import Label
    from kivy.uix.scatter import Scatter
    
    
    class MyLabelWidget(Scatter, Label):
        def __init__(self, bgcolor, **kwargs):
            super().__init__(**kwargs)
    
            with self.canvas.before:
                Color(*bgcolor)
                self.background_rect = Rectangle(
                    pos_hint=(None, None),
                    pos=self.pos,
                    size_hint=(None, None),
                    size=self.size,
                )
    
    
    class Scatterer2App(App):
        def build(self):
            Window.size = 400, 400
    
            layout = FloatLayout()
    
            widget_1 = MyLabelWidget(
                size_hint=(None, None),
                size=(100, 100),
                pos=(50, 50),
                bgcolor=(1, 0, 0, 1),
                text="Drag me",
            )
            widget_2 = MyLabelWidget(
                size_hint=(None, None),
                size=(100, 100),
                pos=(150, 150),
                bgcolor=(0, 0, 1, 1),
                text="Drag me, too",
            )
    
            layout.add_widget(widget_1)
            layout.add_widget(widget_2)
            return layout
    
    
    Scatterer2App().run()
    

    但这会导致标签和标签背景定位不正确:

    为了解决这个问题,MyLabelWidget 不应该继承自 Scatter,而是添加到单个 Scatter 实例中:

    from kivy.app import App
    from kivy.core.window import Window
    from kivy.graphics import Color, Rectangle
    from kivy.uix.floatlayout import FloatLayout
    from kivy.uix.label import Label
    from kivy.uix.scatter import Scatter
    from kivy.uix.widget import Widget
    
    
    class MyLabelWidget(Label):
        def __init__(self, bgcolor, **kwargs):
            super().__init__(**kwargs)
    
            with self.canvas.before:
                Color(*bgcolor)
                self.background_rect = Rectangle(size=self.size)
    
    
    class MyScatterLabelWidget(Scatter):
        def __init__(self, bgcolor, text, **kwargs):
            super().__init__(**kwargs)
            self.label = MyLabelWidget(size=self.size, bgcolor=bgcolor, text=text)
            self.add_widget(self.label)
    
    
    class Scatterer3App(App):
        def build(self):
            Window.size = 400, 400
    
            layout = FloatLayout()
    
            widget_1 = MyScatterLabelWidget(
                size_hint=(None, None),
                size=(100, 100),
                pos=(50, 50),
                bgcolor=(1, 0, 0, 1),
                text="Drag me",
            )
            widget_2 = MyScatterLabelWidget(
                size_hint=(None, None),
                size=(100, 100),
                pos=(150, 150),
                bgcolor=(0, 0, 1, 1),
                text="Drag me, too",
            )
    
            layout.add_widget(widget_1)
            layout.add_widget(widget_2)
            return layout
    
    
    Scatterer3App().run()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-21
      • 2020-06-24
      • 2015-11-09
      • 2020-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多