FloatWidget 在创建时移动

FloatWidget shifted when created

我正在尝试创建菜单。 我用鼠标右键单击它会调用什么 它将位于单击鼠标按钮的位置。 但它总是在某些值上发生变化。

我想做的是创建一个根小部件和包含气泡的菜单小部件。当我单击右键时,通过在构造函数中传递 touch.pos 在当前位置创建新的菜单小部件实例。 正如我发现它在相同距离上移动菜单小部件

Builder.load_string('''
<main_window_menu>:
    size_hint: (None, None)
    size: (160, 80)
    pos_hint: {'center_x': .5, 'y': .3}
    BubbleButton:
        text: 'New'
        on_press: root.new()
''')

class main_window_menu(Bubble):
    def __init__(self, **kwargs):
        super().__init__()
        self._new = kwargs["new"]


def new(self):
    self._new()

class Menu(FloatLayout):

    def __init__(self, pos, **kwargs):
    super().__init__(pos=pos)
    self.show_bubble(**kwargs)

    def show_bubble(self, **kwargs):
        self.bubb = main_window_menu(**kwargs)
        self.add_widget(self.bubb)

    def on_touch_down(self, touch):
        self.bubb.on_touch_down(touch)

class Frame(FloatLayout):
    def __init__(self):
        super().__init__()

    def on_touch_down(self, touch):
        print(touch.pos)
        super().on_touch_down(touch)
        print(touch.pos)
        if touch.button == 'right':
            menu = Menu(pos=touch.pos, new=self.new_operation)
            self.add_widget(menu)

    def new_operation(self):
        pass

class MyApp(App):
    def build(self):
        tt = Frame()
        return tt

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

我认为你的代码有两个问题。

首先,使用

pos_hint: {'center_x': .5, 'y': .3}

Menu 实例内的 main_window_menu 定位到右侧 ('center_x':0.5) 并向上一点 ('y':.3)。 Menu Widget 位于 touch 坐标,因此 main_window_menu 及其 BubbleButton 位于 touch 的右侧和上方.

其次,使用 FloatLayout 作为 Menu 的基数 class 意味着您要么使用其子项的绝对定位,要么使用 pos_hint.

因此,我建议删除 pos_hint 并使用 RelativeLayout 作为 Menu 的基础,然后 (0,0) 的默认 pos 将放置touch 位置的 BubbleButton

这是您的代码的修改版本,它采纳了我的建议:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.bubble import Bubble
from kivy.uix.floatlayout import FloatLayout

Builder.load_string('''
<main_window_menu>:
    size_hint: (None, None)
    size: (160, 80)
    BubbleButton:
        text: 'New'
        on_press: root.new()
''')

class main_window_menu(Bubble):
    def __init__(self, **kwargs):
        super().__init__()
        self._new = kwargs["new"]

    def new(self):
        self._new()

class Menu(RelativeLayout):

    def __init__(self, pos, **kwargs):
        super().__init__(pos=pos)
        self.show_bubble(**kwargs)

    def show_bubble(self, **kwargs):
        self.bubb = main_window_menu(**kwargs)
        self.add_widget(self.bubb)

    def on_touch_down(self, touch):
        return self.bubb.on_touch_down(touch)

class Frame(FloatLayout):
    def __init__(self):
        super().__init__()

    def on_touch_down(self, touch):
        print(touch.pos)
        if touch.button == 'right':
            menu = Menu(pos=touch.pos, new=self.new_operation)
            self.add_widget(menu)
        return super(Frame, self).on_touch_down(touch)

    def new_operation(self):
        pass

class MyApp(App):
    def build(self):
        tt = Frame()
        return tt

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