Kivy: Popup can have only one widget as content

2019-07-19 01:09发布

I am having an issue with using a popup in my .kv file. I understand that a popup can only have one widget as it's content, however if I am only passing a GridLayout as a child that includes a Label and Button, shouldn't this work?

Here is my Python code:

import kivy, LabelB
from kivy.app import App
from kivy.graphics import Color, Rectangle
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.properties import ObjectProperty, StringProperty
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition

Builder.load_file('main.kv')

class CustomPopup(Popup):
    pass

class MenuScreen(Screen):

    def open_popup(self):
        the_popup = CustomPopup()
        the_popup.open()

class SurveyScreen(Screen):
    pass

sm = ScreenManager(transition=FadeTransition())
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(SurveyScreen(name='survey'))

class MainApp(App):

    def build(self):
        return sm

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

Here is my .kv file:

<CustomPopup>:
    title: 'Terms of Service'
    size_hint: .5, .5
    auto_dismiss: False
    GridLayout:
        cols: 1
        Label:
            size_hint: .9, .9
            halign: 'center'
            valign: 'middle'
            text: 'Insert terms of service text here'
            text_size: self.width, None
        Button:
            text: 'Close'
            on_release: root.dismiss()

<MenuScreen>:

    FloatLayout:

        canvas.before:
            Rectangle:
                source: 'menu.png'
                size: self.size
                pos: self.pos

        Label:
            pos_hint: {'x': .7, 'y': .85}
            text_size: self.size
            font_name: 'Arial'
            font_size: 26
            text: 'Sample'
            bold: True

        Button:
            text: 'Take Survey'
            size_hint: .2, .1
            pos_hint: {'x': .15, 'y': .1}
            on_release:
                root.manager.transition.duration = 0.5
                root.manager.current = 'survey'

        Button:
            text: 'Terms of Service'
            size_hint: .2, .1
            pos_hint: {'x': .6-self.size_hint_x, 'y': .1}
            on_release: root.open_popup()

        Button:
            text: 'Quit'
            size_hint: .2, .1
            pos_hint: {'x': .85-self.size_hint_x, 'y': .1}
            on_release: app.stop()

<SurveyScreen>:

    GridLayout:
        cols: 1
        padding: 20
        spacing: 10

        Label:
            text: 'WELCOME!'
            font_size: 20

        Label:
            text: 'Some boring text'

The error is as follows: 'Popup can have only one widget as content'

Am I missing something obvious here? Thanks in advance.

1条回答
贼婆χ
2楼-- · 2019-07-19 01:31

Yes, it should work as you say, your code is correct.

The problem is that the loading of the .kv file is duplicated. As your App subclass is called MainApp, main.kv is loaded automatically if it is in same directory (Doc: How to load kv). On the other hand, you explicitly upload the file using Builder.load_file ('main.kv').

You must remove the call to Builder or rename MainApp/main.kv.

If you delete the call to Builder.load_file you must create the ScreenManager instance once the .kv is loaded. You can do something like:

class MainApp (App):

     def build (self):
         sm = ScreenManager (transition = FadeTransition ())
         sm.add_widget (MenuScreen (name = 'menu'))
         sm.add_widget (SurveyScreen (name = 'survey'))
         return sm
查看更多
登录 后发表回答