Kivy Popup动态高度

时间:2018-11-05 04:00:15

标签: python kivy

我希望在具有动态高度的python端弹出一个窗口。

到目前为止,我在屏幕__init__类中拥有此功能。 kv文件还有另一个名为pop_on_release的小部件。无论如何,我发现这会产生一个弹出窗口,格式非常奇怪:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import Screen, ScreenManager

kv = '''

ScreenManagement:
    id: 'manager'
    BrokenPopup:
        name: 'broken'
        manager: 'manager'

<BrokenPopup>:
    BoxLayout:
        Button:
            text: 'Test'
            on_release: root.p.open()

'''

class ScreenManagement(ScreenManager):
    pass

class BrokenPopup(Screen):

    def __init__(self, **kwargs):
        super(BrokenPopup,self).__init__(**kwargs)

        self.p = Popup(auto_dismiss=False, size_hint_x=.6, size_hint_y=None, title='A popup')
        self.g = GridLayout(cols=1, spacing=10)
        self.g.add_widget(Button(text='Test1', size_hint_y=None, height=32))
        self.g.add_widget(Button(text='Test2', size_hint_y=None, height=32))
        self.g.bind(minimum_height=self.g.setter('height'))
        self.p.add_widget(self.g)
        self.p.bind(height=self.g.setter('height')) #<- this does not work to change the popup height!

class TheApp(App):

    def build(self):
        return Builder.load_string(kv)

TheApp().run()

将弹出窗口的大小设置为仅适合一个窗口小部件,使第二个按钮(以及可能包括的所有其他按钮)浮动到弹出窗口边界之外。

我应该如何更改代码,以使所有小部件都适合弹出窗口的范围?我正在尝试通过动态设置弹出窗口的高度来做到这一点,但是事实证明这并不有效。

2 个答案:

答案 0 :(得分:1)

我已修改您的代码以执行我认为您想要的操作。基本上,它会将minimum_height中的GridLayout(添加到您的Popup中)添加到计算出的title和分隔条的高度中。 Button中的第一个GridLayout现在会向Button添加另一个GridLayout进行测试。

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import Screen, ScreenManager

kv = '''

ScreenManagement:
    id: 'manager'
    BrokenPopup:
        name: 'broken'
        manager: 'manager'

<BrokenPopup>:
    BoxLayout:
        Button:
            text: 'Test'
            on_release: root.p.open()

'''


class ScreenManagement(ScreenManager):
    pass


class BrokenPopup(Screen):

    def __init__(self, **kwargs):
        super(BrokenPopup,self).__init__(**kwargs)

        self.popup_title_height = None
        self.p = Popup(auto_dismiss=False, size_hint_x=.6, size_hint_y=None, title='A popup')
        self.g = GridLayout(cols=1, spacing=10)
        self.g.bind(minimum_height=self.fix_size)
        self.g.add_widget(Button(text='Test1', size_hint_y=None, height=32, on_release=self.add_one))
        self.g.add_widget(Button(text='Test2', size_hint_y=None, height=32))
        self.p.add_widget(self.g)


    def add_one(self, *args):
        self.g.add_widget(Button(text='Another', size_hint_y=None, height=32))


    def get_popup_title_height(self):
        height = 0
        popupGrid = self.p.children[0]
        height += popupGrid.padding[1] + popupGrid.padding[3]
        for child in popupGrid.children:
            if isinstance(child, BoxLayout):
                continue
            else:
                height += child.height + popupGrid.spacing[1]
        self.popup_title_height = height


    def fix_size(self, *args):
        if self.popup_title_height is None:
            self.get_popup_title_height()
        self.p.height = self.g.minimum_height + self.popup_title_height


class TheApp(App):

    def build(self):
        return Builder.load_string(kv)

TheApp().run()

通过查看Popupstyle.kv文件的代码,看看Popup的显示方式,我有点作弊。因此,如果其中任何一项发生更改,则可能无法正常工作。

答案 1 :(得分:0)

我已经找到了受约翰·安德森(John Anderson)回答影响的原始问题的解决方案。我将在下面提供有关如何使用此解决方案的演练。

1)这是我的原始问题的照片;我需要根据分配给它的小部件动态设置弹出高度。在找到以下解决方案之前,我的弹出窗口看起来像这样,其中包含OP中的代码:

Original popup with a height error.

如您所见,这些小部件超出了弹出窗口的边界。

2)在使用检查器工具查看弹出窗口小部件时,我发现了一些有趣的东西。

python '/path/to/your/file.py' -m inspector

使用control-e,我可以单击小部件并检查其属性。我单击了弹出按钮,并循环浏览了父窗口小部件,直到找到弹出窗口小部件。

enter image description here

正如您在照片中看到的那样,弹出窗口小部件有一个孩子:网格布局。以下是该网格布局的子级:

enter image description here

有趣的是,网格布局包含:

  • 一个标签,高度为33

  • 一行,高度为4

  • 一个框布局,其中包含弹出窗口的内容

  • 这三个小部件之间的
  • 2个间距单位

  • 全方位填充12个单位;因此要考虑另外24个单位的高度

3)在我的解决方案中,我用手写了标签的默认高度,行小部件以及所有默认的弹出间距和填充。然后,我在方框布局中循环浏览这些子项,并添加其高度。我还将这些孩子的身高增加了10,因为包含所有这些小部件的网格布局使用的间距为10。


解决方案:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import Screen, ScreenManager

kv = '''

ScreenManagement:
    id: 'manager'
    BrokenPopup:
        name: 'broken'
        manager: 'manager'

<BrokenPopup>:
    BoxLayout:
        Button:
            text: 'Test'
            on_release: root.p.open()

'''

class ScreenManagement(ScreenManager):
    pass

class BrokenPopup(Screen):

    def __init__(self, **kwargs):
        super(BrokenPopup,self).__init__(**kwargs)

        self.p = Popup(auto_dismiss=False, size_hint_x=.6, size_hint_y=None, title='A popup')
        self.g = GridLayout(cols=1, spacing=10, padding=[0,10,0,-5])
        self.g.bind(minimum_height=self.fix_popup_height) # <- here's the magic
        self.g.add_widget(Button(text='Test1', size_hint_y=None, height=32))
        self.g.add_widget(Button(text='Test2', size_hint_y=None, height=32))
        self.p.add_widget(self.g)


    def fix_popup_height(self, grid, *args):
        # a generalized function that, when bound to minimum_height for a grid with popup widgets,
        # this will set the height of the popup
        height = 0
        height += 33    # for popup label
        height += 4     # for popup line widget
        height += 24    # for popup padding
        height += 2     # for spacing between main popup widgets
        for child in grid.children:
            height += child.height + 10 # adds 10 for the spacing between each child
        grid.parent.parent.parent.height = height # sets popup height
        pass


class TheApp(App):

    def build(self):
        return Builder.load_string(kv)

TheApp().run()

OP中的重要更改:

  • 将小部件容器的minimum_height绑定到fix_popup_height()函数;每次将小部件添加到弹出窗口时都会触发此操作。

  • 在屏幕类中声明fix_popup_height()

这是固定的弹出窗口:

enter image description here