Kivy添加和清除Widgets时的布局问题

-1 投票
1 回答
3401 浏览
提问于 2025-04-17 14:54

在使用添加小部件和清除小部件的命令时,我发现我的小部件本身看起来没问题,但在屏幕的左下角却变得非常小。

我会在这里详细说明我的步骤,请耐心听我讲。

我有一个系统可以在不同的小部件之间切换。这个“小部件”基本上就是整个表单、基础画布和布局。

据我了解,这些小部件必须有一个基础布局。所以我首先放了一个根元素,然后用这个根元素初始化我的用户界面管理器。

class MyApp(App):
    rootForm = BoxLayout()
    ui = UserInterface(rootForm)
    return rootForm

我的用户界面管理器负责小部件的切换。它在创建时会把所有小部件放在一个列表里。它还会给自己一个指向用户界面的引用,以便进行回调。

class UserInterface():
    __WidgetDictionary = {}
    __RootWidget = None

    def __init__(self, inRootWidget):
        self.__RootWidget = inRootWidget # Keep track of our root
        # Generate two forms to be swapped in/out
        self.__WidgetDictionary["form1"] = FirstWidget()
        self.__WidgetDictionary["form1"].SetUIreference(self)

        self.__WidgetDictionary["form2"] = SecondWidget()
        self.__WidgetDictionary["form2"].SetUIReference(self)

        self.ChangeWidget("MainMenu")

ChangeWidget是这里的核心,它会清空根小部件并添加一个新的小部件。

def ChangeWidget(self, inWidgetName):
    self.__RootWidget.clear_widgets() # Clear out the widgets
    self.__RootWidget.add_widget( self.__WidgetDictionary[inWidgetName] ) # Add our new widget

这样可以正常显示我的表单,并且有一个按钮。当点击这个按钮时,它会触发一个回调,把表单从Form1切换到Form2。

#FirstWidget.py
class FirstWidget(BoxLayout):
    __UserInterfaceReference = None

    def SetUIReference(self, inUserInterface):
        self.__UserInterfaceReference = inUserInterface

    def ChangeWidget(self, inWidgetName):
        self.__UserInterfaceReference.ChangeWidget(inWidgetName)

对应的.kv文件

#FirstWidget.kv
<FirstWidget>:      
    BoxLayout:
        orientation: 'vertical'
        padding: 50
        spacing: 10
    Button:
        on_release: root.ChangeWidget('form2')

一旦点击按钮,就会出现错误。Form1和Form2几乎一模一样,Form2比Form1多了一个按钮。Form1和Form2的代码完全相同,唯一的区别是类名。再说一次,在自己的环境中,Form2看起来完美。

这里有一个错误的截图: AddedWidgetMessedUp

编辑:目前我已经切换到使用屏幕管理器:http://kivy.org/docs/api-kivy.uix.screenmanager.html

1 个回答

1

把上面的代码合并到一个文件里。如果我运行以下代码:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder

Builder.load_string(
'''
<FirstWidget>:      
    BoxLayout:
        orientation: 'vertical'
        padding: 50
        spacing: 10
    Button:
        text: 'change to form 2'
        on_release: root.ChangeWidget('form2')

<SecondWidget>:
    TextInput:
    BubbleButton:
        text: 'change to form 1'
        on_release: root.ChangeWidget('form1')
''')

class UserInterface():
    __WidgetDictionary = {}
    __RootWidget = None

    def __init__(self, inRootWidget):
        self.__RootWidget = inRootWidget # Keep track of our root
        # Generate two forms to be swapped in/out
        self.__WidgetDictionary["form1"] = FirstWidget()
        self.__WidgetDictionary["form1"].SetUIReference(self)

        self.__WidgetDictionary["form2"] = SecondWidget()
        self.__WidgetDictionary["form2"].SetUIReference(self)
        self.ChangeWidget("form1")

    def ChangeWidget(self, inWidgetName):
         # Clear out the widgets
        self.__RootWidget.clear_widgets()
         # Add our new widget
        self.__RootWidget.add_widget(self.__WidgetDictionary[inWidgetName])


class FirstWidget(BoxLayout):
    __UserInterfaceReference = None

    def SetUIReference(self, inUserInterface):
        self.__UserInterfaceReference = inUserInterface

    def ChangeWidget(self, inWidgetName):
        self.__UserInterfaceReference.ChangeWidget(inWidgetName)

class SecondWidget(BoxLayout):
    __UserInterfaceReference = None

    def SetUIReference(self, inUserInterface):
        self.__UserInterfaceReference = inUserInterface

    def ChangeWidget(self, inWidgetName):
        self.__UserInterfaceReference.ChangeWidget(inWidgetName)


class MyApp(App):

    def build(self):
        rootForm = BoxLayout()
        ui = UserInterface(rootForm)
        return rootForm


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

一切都按预期工作。因为你没有提供完整的代码,所以很难判断你哪里出错了,也不好给出解释。你可以对比一下我发的代码和你自己的代码,看看你们有什么不同。

希望这能帮到你。

撰写回答