Kivy Popup reagiert nicht

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
DMD-OL
User
Beiträge: 315
Registriert: Samstag 26. Dezember 2015, 16:21

Hallo Leute.
Ich habe ein großes Problem in nur einer Zeile in meinem Code.
Ich verzweifele langsam, weil sich mein Popup nach NICHT erteilten Berechtigungen nicht öffnet.
Den Code kann man kopieren und selbst testen. Wenn man auf ein Android übertragen hat und der User beide (oder auch nur eine) Berechtigung nicht erteilt, soll ein Popup geöffnet werden,
in dem ich dann eine kleine Erklärung reinschreiben will.
Die fehlerhafte Zeile habe ich in meiner py-Datei makiert. Es ist nur diese Zeile, die nicht funktioniert!
Eine Fehlermeldung gibt es auch nicht und wenn ich es auf meinem Rechner laufen lasse, ist das Popup hinter den beiden grossen Buttons auf dem FirstScreen? Öffne ich das Popup zu früh,
so dass es zwar geöffnet ist, aber im Hintergrund nicht gesehen wird?
WHY???

Code: Alles auswählen

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.properties import StringProperty
from kivy.core.window import Window
from kivy.utils import platform
if platform == "android":
    from android.permissions import request_permissions, Permission


class PopupErrors(Popup):
    error_text = StringProperty()

    def __init__(self, title, text, **kwargs):
        super(PopupErrors, self).__init__(**kwargs)
        self.title = title
        self.error_text = text
        self.size_hint = (None, None)
        self.size = (Window.width * 0.8, Window.height * 0.6)


class FirstScreen(Screen):
    def __init__(self, **kwargs):
        super(FirstScreen, self).__init__(**kwargs)

        self.request = None
        if platform == "android":

            def callback(_, results):
                if all(res for res in results):
                    self.request = True
                else:
                    self.request = False
                self.check_permission()

            request_permissions(
                [
                    Permission.ACCESS_COARSE_LOCATION,
                    Permission.ACCESS_FINE_LOCATION,
                    Permission.WRITE_EXTERNAL_STORAGE,
                    Permission.READ_EXTERNAL_STORAGE,
                ],
                callback,
            )
        else:
            self.check_permission()

    def check_permission(self):
        if self.request is True:
            self.ids.lbl_status.text = f"Alle Berechtigungen vorhanden."
        else:
            self.ids.lbl_status.text = f"Popup wird geöffnet...?"
            self.show_popup("FirstScreen")                                  #  <- Diese Zeile funktioniert nicht. Wenn ich einen Button benutze, läuft alles einwandfrei?!

    @staticmethod
    def show_popup(screen):
        text = f"(1) This is the content\nof the custom popup!"
        PopupErrors(title=screen, text=text).open()

    def switch_to_screen(self):
        self.manager.transition.direction = "left"
        self.manager.current = "second_screen"


class SecondScreen(Screen):
    def __init__(self, **kwargs):
        super(SecondScreen, self).__init__(**kwargs)

    def change_label_text(self):
        self.ids.my_label.text = "Neuer Text!"

    def switch_to_screen(self):
        self.manager.transition.direction = "right"
        self.manager.current = "first_screen"

    def on_leave(self):
        self.ids.my_label.text = "This is the Second Screen"

    @staticmethod
    def show_popup(screen):
        text = f"(2) This is the content\nof the custom popup!"
        PopupErrors(title=screen, text=text).open()


class ScreenManagerApp(App):
    def build(self):
        Builder.load_file("main.kv")

        if platform == "android":
            Window.fullsize = True
        else:
            Window.size = (600, 800)
            Window.top = 150
            Window.left = 500

        screen_manager = ScreenManager()
        screen_manager.transition = FadeTransition()
        screen_manager.add_widget(FirstScreen(name="first_screen"))
        screen_manager.add_widget(SecondScreen(name="second_screen"))
        return screen_manager


if __name__ == "__main__":
    ScreenManagerApp().run()

Code: Alles auswählen

<PopupErrors>:
    BoxLayout:
        orientation: 'vertical'

        Label:
            text: root.error_text
            font_size: '14sp'
            pos_hint: {"x": dp(0), "top": dp(1)}

        Button:
            text: "Schließen"
            font_size: '16sp'
            size_hint_y: None
            height: self.texture_size[1] + dp(40)
            pos_hint: {"x": dp(0), "y": dp(.1)}
            on_press: root.dismiss()


<FirstScreen>:
    BoxLayout:
        orientation: 'vertical'

        Label:
            id: lbl_status

        Button:
            text: 'Show Popup'
            on_press: root.show_popup("FirstScreen")

        Button:
            text: "To SecondScreen"
            font_size: '25sp'
            on_release:
                root.switch_to_screen()


<SecondScreen>:
    BoxLayout:
        orientation: 'vertical'

        Label:
            id: my_label
            text: 'This is the Second Screen'

        Button:
            text: 'Change label text'
            on_press: root.change_label_text()

        Button:
            text: 'Show Popup'
            on_press: root.show_popup("SecondScreen")

        Button:
            text: "To FirstScreen"
            font_size: '25sp'
            on_release: root.switch_to_screen()
Ich verstehe es nicht! Bitte um eure Hilfe.
Benutzeravatar
Dennis89
User
Beiträge: 1156
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

wieso hast du die Klasse für Popup geschrieben?
https://kivy.org/doc/stable/api-kivy.ui ... l#examples

Wo nimmst du dir denn deine Infos her?

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
DMD-OL
User
Beiträge: 315
Registriert: Samstag 26. Dezember 2015, 16:21

Die Klasse habe ich Kivy like geschrieben. Da gibt es viele Infoseiten. Es funktioniert auch alles, wenn ich z.B. self.show_popup() mit einem Button anspreche. Dann öffnet sich das Popup wunderbar.
Nur nicht, wenn ich es aus der Funktion self.check_permission() anspreche, passiert nix?!
Aber ich habe es auch schon so wie in deinem Link versucht, da funktioniert es auch mit Button, aus der Funktion heraus aber auch nicht :(
Keine Ahnung warum.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich kann das Problem nicht nachvollziehen, weil ich weder Android noch Kivy nutze. Aber wenn es so klar ist, dass diese Methode irgendwie nicht geht - wofür es meiner Meinung nach diverse Gründe geben kann - muss man es eben anders programmieren, und statt das Popup direkt zu starten, einfach eine Flagge + zB einem Timer benutzen, um das ganze ein paar Hundertstel später auf “normalem” Weg zu machen.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hier sieht man ein Beispiel: https://github.com/Android-for-Python/c ... ons.py#L62

Das macht sowohl was ich vorgeschlagen habe, und gibt auch einen Hinweis auf die Ursache: das scheint in einem anderen thread zu laufen, darum hat der da den @mainthread dekorator.
DMD-OL
User
Beiträge: 315
Registriert: Samstag 26. Dezember 2015, 16:21

Ich werde es mal dann anders versuchen, aber erst nachdem ich @mainthread mal ausprobiert habe. Da war irgendwas als ich damit angefangen habe. Ich glaube, im Laufe ... ist das irgendwie abhanden gekommen... :)
Mal sehn... THX
DMD-OL
User
Beiträge: 315
Registriert: Samstag 26. Dezember 2015, 16:21

ICH DREH AM RAD. DU HATTEST RECHT.

Das hier funktioniert jetzt. Ohne @mainthread funktionierte es nicht.
Die .kv-Datei ist unverändert.

Code: Alles auswählen

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.clock import mainthread
from kivy.properties import StringProperty
from kivy.core.window import Window
from kivy.utils import platform

if platform == "android":
    from android.permissions import request_permissions, Permission


class PopupErrors(Popup):
    error_text = StringProperty()

    def __init__(self, title, text, **kwargs):
        super(PopupErrors, self).__init__(**kwargs)
        self.title = title
        self.error_text = text
        self.size_hint = (None, None)
        self.size = (Window.width * 0.8, Window.height * 0.6)

    def close(self):
        self.dismiss()
        # App.get_running_app().stop()


class FirstScreen(Screen):
    def __init__(self, **kwargs):
        super(FirstScreen, self).__init__(**kwargs)

        self.ids.lbl_status.text = "Hier eine kleine Erklärung..."

    @mainthread
    def request_permissions(self):
        if platform == "android":

            @mainthread
            def callback(_, results):
                if all(res for res in results):
                    self.ids.lbl_status.text = f"Alle Berechtigungen vorhanden."
                else:
                    self.show_popup("FirstScreen")

            request_permissions(
                [
                    Permission.ACCESS_COARSE_LOCATION,
                    Permission.ACCESS_FINE_LOCATION,
                    Permission.WRITE_EXTERNAL_STORAGE,
                    Permission.READ_EXTERNAL_STORAGE,
                ],
                callback,
            )
        else:
            self.show_popup("FirstScreen")

    @staticmethod
    def show_popup(screen):
        text = f"(1) This is the content\nof the custom popup!"
        PopupErrors(title=screen, text=text).open()

    def switch_to_screen(self):
        self.manager.transition.direction = "left"
        self.manager.current = "second_screen"


class SecondScreen(Screen):
    def __init__(self, **kwargs):
        super(SecondScreen, self).__init__(**kwargs)

    def change_label_text(self):
        self.ids.my_label.text = "Neuer Text!"

    def switch_to_screen(self):
        self.manager.transition.direction = "right"
        self.manager.current = "first_screen"

    def on_leave(self):
        self.ids.my_label.text = "This is the Second Screen"

    @staticmethod
    def show_popup(screen):
        text = f"(2) This is the content\nof the custom popup!"
        PopupErrors(title=screen, text=text).open()


class ScreenManagerApp(App):
    def build(self):
        Builder.load_file("main.kv")

        if platform == "android":
            Window.fullsize = True
        else:
            Window.size = (600, 800)
            Window.top = 150
            Window.left = 500

        screen_manager = ScreenManager()
        screen_manager.transition = FadeTransition()
        screen_manager.add_widget(FirstScreen(name="first_screen"))
        screen_manager.add_widget(SecondScreen(name="second_screen"))
        return screen_manager


if __name__ == "__main__":
    ScreenManagerApp().run()
Antworten