【问题标题】:Extending widget bases dynamically动态扩展小部件库
【发布时间】:2019-10-23 01:54:55
【问题描述】:

我需要根据传递的参数更改一些小部件类的基础。

最简单的例子是:

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 类实例。)

现在我正在尝试使用 kivy 小部件来实现这一点

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'

【问题讨论】:

  • 您是否有理由使用该 extend_instance 函数而不是仅仅定义 B 以从 A 继承?例如,class B(A): 自动将 B 中的所有内容引入 A
  • 是的,让我解释一下。例如,假设我想要一个 MyLabel 类,然后 kivy,根据我传递的参数,导入并使用合适的小部件。它可以是一个在结构上与常规标签完全不同的小部件,但它们都具有标签固有的共同属性,例如文本、文本颜色等。我预先创建了这些小部件,但我希望 kivy 选择哪个更好用(我也规定了这些规则)。
  • @me2beats 阅​​读stackoverflow.com/questions/3308792/python-object-layoutstackoverflow.com/questions/13280680/…,在我看来,更简单的方法是实现工厂模式,因为最后一个问题的答案之一显示stackoverflow.com/questions/13280680/…
  • 哦,所以这可能是因为某些 Widget 库(例如 EventDispatcher)是用 cython 编写的,对吧?

标签: python python-3.x kivy


【解决方案1】:

看起来像这样工作:

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 编写的有关

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多