我希望在具有动态高度的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()
将弹出窗口的大小设置为仅适合一个窗口小部件,使第二个按钮(以及可能包括的所有其他按钮)浮动到弹出窗口边界之外。
我应该如何更改代码,以使所有小部件都适合弹出窗口的范围?我正在尝试通过动态设置弹出窗口的高度来做到这一点,但是事实证明这并不有效。
答案 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()
通过查看Popup
和style.kv
文件的代码,看看Popup
的显示方式,我有点作弊。因此,如果其中任何一项发生更改,则可能无法正常工作。
答案 1 :(得分:0)
我已经找到了受约翰·安德森(John Anderson)回答影响的原始问题的解决方案。我将在下面提供有关如何使用此解决方案的演练。
1)这是我的原始问题的照片;我需要根据分配给它的小部件动态设置弹出高度。在找到以下解决方案之前,我的弹出窗口看起来像这样,其中包含OP中的代码:
如您所见,这些小部件超出了弹出窗口的边界。
2)在使用检查器工具查看弹出窗口小部件时,我发现了一些有趣的东西。
python '/path/to/your/file.py' -m inspector
使用control-e,我可以单击小部件并检查其属性。我单击了弹出按钮,并循环浏览了父窗口小部件,直到找到弹出窗口小部件。
正如您在照片中看到的那样,弹出窗口小部件有一个孩子:网格布局。以下是该网格布局的子级:
有趣的是,网格布局包含:
一个标签,高度为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()
。
这是固定的弹出窗口: