Kivy eigenes Widget & events die nicht durchgereicht werden

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
debian-sid
User
Beiträge: 1
Registriert: Donnerstag 2. November 2017, 20:13

Donnerstag 2. November 2017, 20:33

Hi,

neu und gleich mal ne Frage ^^.

Ich brauche in Kivy auf mehreren Screens die in multiple kv files aufgeteilt sind ein ErrorWidget. Dieses Widget soll nur dann angezeigt werden, wenn eine anfrage zu einen Rest Service fehlschlägt oder ein Error Response zurück kommt. Bei einen Click auf einen Button sollte dann der letzte Request wieder ausgeführt werden. Soweit so gut, das Widget habe ich gebaut und die Texte lassen sich auch alle befüllen. Nur der Click oder das on_press kommen nicht zum Button durch. Diese verschwinden dann irgendwo im Nirvana.

Das Widget sieht so aus:

Code: Alles auswählen

from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.graphics import Color, Rectangle
from iconfonts.iconfonts import icon
from kivy.properties import StringProperty, ObjectProperty

class ErrorComponent(Widget):

    title = StringProperty()
    err_msg = StringProperty()
    btn_event = ObjectProperty()
    btn_text = StringProperty()

    def __init__(self, **kwargs):
        super(ErrorComponent, self).__init__(**kwargs)

        # Add and init Widgets
        self.__exec_command = None
        self.__title = Label()
        self.__reason = Label()
        self.__err_msg = TextInput()
        self.__btn_action = Button()
        self.__init_widgets()
        self.add_widget(self.__title)
        self.add_widget(self.__reason)
        self.add_widget(self.__err_msg)
        self.add_widget(self.__btn_action)

        # Binding Widgetupdate
        self.bind(pos=self.__update_widgets)
        self.bind(size=self.__update_widgets)
        self.bind(title=self.__set__title)
        self.bind(err_msg=self.__set_err_msg)
        self.bind(btn_text=self.__set_btn_text)
        self.bind(btn_event=self.__set_btn_action)
        self.__btn_action.bind(on_press=self.btn_action_on_press)
        self.__update_widgets()

    def __set__title(self, obj, value):
        self.__title.text = "%s     %s     %s" % (icon('fa-exclamation-triangle'),
                                                  value, icon('fa-exclamation-triangle'))

    def __set_err_msg(self, obj, value):
        self.__err_msg.text = value

    def __set_btn_text(self, obj, value):
        self.__btn_action.text = str(value)

    def __set_btn_action(self, obj, value):
        self.__exec_command = value
        self.__update_widgets()

    def __update_widgets(self, *args):
        self.canvas.before.clear()
        with self.canvas.before:
            Color(0.3, 0, 0, 0.7)
            Rectangle(pos=self.pos, size=self.size)
        # Update Title
        self.__title.pos = (self.x, self.top - 50)
        self.__title.size = (self.width, 50)
        # Reason
        self.__reason.pos = (self.x + 20, self.top - 70)
        # Update Error Message
        self.__err_msg.pos = (self.x + 20, self.y + 60)
        self.__err_msg.size = (self.width - 40, self.height - 130)
        # Update Error Dto
        self.__btn_action.pos = (self.x + 20, self.y + 10)
        self.__btn_action.size = (self.width - 40, 40)

    def __init_widgets(self):
        # Init Title
        self.__title.markup = True
        self.__title.color = (1, 1, 1, 1)
        self.__title.font_size = 40

        # Reason
        self.__reason.text = "Reason:"
        self.__reason.size = (100, 30)
        self.__reason.color = (1, 1, 1, 1)
        self.__reason.font_size = 16

        # Init Error Message
        self.__err_msg.text = self.err_msg
        self.__err_msg.background_color = (0.3, 0, 0, 0.7)
        self.__err_msg.foreground_color = (1, 1, 1, 1)
        self.__err_msg.readonly = True
        self.__err_msg.font_size = 13

        # Init Action Button
        self.__btn_action.font_size = 20
        self.__btn_action.disabled = False

    def btn_action_on_press(self):
        print self
Im Kv habe ich das dann einmal so eingebunden:

Code: Alles auswählen

        ErrorComponent:
            id: error
            pos: 1000, 20
            size: root.width, root.height - 100
            title: "Error"
            btn_event: root.request_nagios
            btn_text: "Retry Nagios Request"
Kann mir jemand sagen woran das liegt?
Astorek
User
Beiträge: 72
Registriert: Samstag 24. Januar 2009, 15:06
Kontaktdaten:

Sonntag 10. Dezember 2017, 18:10

Ohne jetzt alles genau durchgesehen zu haben, aber eine Vermutung meinerseits: Du hast

Code: Alles auswählen

        self.__btn_action.bind(on_press=self.btn_action_on_press)
und

Code: Alles auswählen

    def btn_action_on_press(self):
Laut Kivy-Dokumentation wird bei der Methode "bind" stets das Objekt mitgegeben, was du aber in der Methodendefinition nicht angegeben hast. Das heißt, du müsstest eigentlich zu 100% eine Fehlermeldung vom Python-Interpreter erhalten, wenn du versuchst, den Button zu drücken.

Also entweder

Code: Alles auswählen

    def btn_action_on_press(self, kivyobj):
(oder irgendein anderer passender Name; der muss ja nicht verwendet werden)

...oder (eine in diesem Fall eher unschöne Methode, trotzdem solls der Vollständigkeit halber erwähnt werden):

Code: Alles auswählen

        self.__btn_action.bind(on_press=lambda x: self.btn_action_on_press())
(Zur genaueren Erklärung bitte in die Python-Doku, Stichwort "Lambda-Operator", ansehen)
Antworten