Динамическое расширение баз виджетов - PullRequest
0 голосов
/ 23 октября 2019

Мне нужно изменить базы некоторых классов моего виджета, в зависимости от переданных аргументов.

Самый простой пример:

class A:
    def a(self):
        print (1)

class B:
    def __init__(self):
        self.extend_instance(A)
        self.a()

    def extend_instance(obj, cls):
        base_cls = obj.__class__
        base_cls_name = obj.__class__.__name__
        obj.__class__ = type(base_cls_name, (base_cls, cls),{})

B()

Возможно, это не оптимальный способ, потому что он изменяет базыкаждый раз, когда создается новый экземпляр B (если я правильно понимаю). Но похоже, что это работает.

Это очень упрощенный пример (без аргументов, в зависимости от того, какие экземпляры класса B с различными базами должны быть созданы.)

Теперь я пытаюсь реализовать этос кивыми виджетами

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label


class CoolLabel(Label):
    def a(self):
        print (1)


class MyLabel:
    def __init__(self, **kwargs):

        #self.__basses__ = CoolLabel

        self.extend_instance(CoolLabel)

        self.a()


    def extend_instance(obj, cls):
        base_cls = obj.__class__
        base_cls_name = obj.__class__.__name__
        obj.__class__ = type(base_cls_name, (base_cls, cls),{})


class MyApp(App):
    def build(self):
        self.root = MyLabel(text= '123456')


MyApp().run()

И я получаю эту ошибку:

   File "main.py", line 24, in extend_instance
     obj.__class__ = type(base_cls_name, (base_cls, cls),{})
 TypeError: __class__ assignment: 'MyLabel' object layout differs from 'MyLabel'

в чем причина? это может быть связано с Kivy Widget Metaclass? и есть ли способы обойти это?

Обновление:

Позвольте мне упростить мою проблему. Главный вопрос - почему это не работает?

from kivy.uix.widget import Widget

class MyWidget:
    def __init__(self, **kwargs):
        self.__class__ = type('MyWidget', (Widget,),{})

MyWidget()

Вот ошибка, которую я имею:

   File "main.py", line 7, in <module>
     MyWidget()
   File "main.py", line 5, in __init__
     self.__class__ = type('MyWidget', (Widget,),{})
 TypeError: __class__ assignment: 'MyWidget' object layout differs from 'MyWidget'

1 Ответ

0 голосов
/ 24 октября 2019

выглядит так:

from kivy.event import EventDispatcher

class SomeWidget(EventDispatcher):
    def a(self):
        print ('hi')

class MyWidget(EventDispatcher):
    def __init__(self, **kwargs):
        self.__class__ = type('MyWidget', (SomeWidget,),{})
        self.a()

MyWidget()

хотя я до сих пор не понимаю, с чем это связано. Я только что предположил (благодаря комментарию @eyllanesc), что ошибка произошла из-за несовместимости баз, как-то связанной с тем, что kivy EventDispatcher написан на cython

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...