Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kivy: Popup can have only one widget as content

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.

like image 808
rahlf23 Avatar asked Oct 28 '25 13:10

rahlf23


1 Answers

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
like image 124
FJSevilla Avatar answered Oct 31 '25 04:10

FJSevilla



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!