【问题标题】:How to inherit NSPanel in Python/PyObjC?如何在 Python/PyObjC 中继承 NSPanel?
【发布时间】:2013-02-27 07:12:27
【问题描述】:

我正在将一个小的 Objective-C/Cocoa 库移植到 Python/PyObjC 中。 而且我对实施方式感到困惑。

原代码如下:

@implementation HUDWindow
- (id)initWithContentRect:(NSRect)contentRect 
                styleMask:(unsigned int)styleMask 
                  backing:(NSBackingStoreType)bufferingType 
                    defer:(BOOL)flag 
{
    if (self = [super initWithContentRect:contentRect 
                                styleMask:NSBorderlessWindowMask 
                                  backing:bufferingType 
                                    defer:flag]) {
        // initialize code here
             :
             :
             :
             :
             :
             :
        return self;
    }
}

并且在头文件中说 HUDWindow 类继承了 NSPanel。 据我阅读代码,初始化是这样的:

  1. HUDWindow 的 initContentRect 会覆盖 NSPanel 的 initContentRect。
  2. 在 HUDWindow 的 initContentRect 内部,NSPanel 的 initContentRect 被调用并得到结果为“self”。

首先,我这样写python代码。这是一个字一个字的翻译:

class HUDWindow(NSPanel):
    def initWithContentRect_styleMask_backing_defer_(self, rect, style, buf, flag):
        self = NSPanel.initWithContentRect_styleMask_backing_defer_(
            rect, NSBorderlessWindowMask, buf, flag)
        # initialize code here
             :
             :
             :
             :
             :
             :
        return self

它不起作用,因为self 只是NSPanel 的一个实例。我不能调用我从原始 obj-c 代码移植的任何令人上瘾的函数。

所以我像这样更改了我的代码:

class HUDWindow(NSPanel):
    def initWithContentRect_styleMask_backing_defer_(self, rect, style, buf, flag):
        self.window = NSPanel.initWithContentRect_styleMask_backing_defer_(
            rect, NSBorderlessWindowMask, buf, flag)
        # initialize code here
             :
             :
             :
             :
             :
             :
        return self.window

效果好一点。至少,我可以在这个初始化函数中调用其他函数。 但是在初始化函数之外,我不能调用从原始代码移植的其他函数。

所以我这样尝试:

class HUDWindow(NSPanel):
    def initWithContentRect_styleMask_backing_defer_(self, rect, style, buf, flag):
        self.window = NSPanel.initWithContentRect_styleMask_backing_defer_(
            rect, NSBorderlessWindowMask, buf, flag)
        # initialize code here
             :
             :
             :
             :
             :
             :
         self.window.setTitle_ = self.setTitle_
         return self.window

没有用。创建实例后无法覆盖或添加函数。

现在我觉得我做错了。有没有什么常见的方式来继承像 NSPanel 或 NPWindow 这样的类?

【问题讨论】:

    标签: python pyobjc


    【解决方案1】:

    您的第一个解决方案是正确的。在第二种情况下,您需要使用NSProxy 或编写自己的显式委托,这很痛苦(第三种方法不是这样做的——你可以做类似的事情通过 swizzling,但不要)。

    但是,也有一些问题。

    首先,这段代码:

    self = NSPanel.initWithContentRect_styleMask_backing_defer_(rect, NSBorderlessWindowMask, buf, flag)
    

    …等价于这个 ObjC 代码:

    self = [NSPanel initWithContentRect:rect 
                              styleMask:NSBorderlessWindowMask
                                backing:buf
                                  defer:flag]
    

    …当你想要的是:

    self = [super initWithContentRect:rect 
                            styleMask:NSBorderlessWindowMask
                              backing:buf
                                defer:flag]
    

    后者的 PyObjC 等价物是:

    self = super().initWithContentRect_styleMask_backing_defer_(rect, NSBorderlessWindowMask, buf, flag)
    

    或者,在 2.x 中:

    self = super(HUDWindow, self).initWithContentRect_styleMask_backing_defer_(rect, NSBorderlessWindowMask, buf, flag)
    

    在 ObjC 中,super 不是超类,而是一个特殊的魔法对象,它实际上是“作为超类的实例的自我”。它几乎与 Python 3 的 super() 或不那么神奇的 Python 2 super 完全一样,PyObjC 做了额外的工作,意味着您可以“几乎”忽略它。

    你正在做的是(试图)初始化NSPanel类对象(或者可能是PyObjC桥的类对象到NSPanel,我不确定是哪个),或者甚至可能试图初始化@ 987654333@ 好像是NSPanel。无论您在做什么,它都无法初始化您的 self 实例。 (并且将结果分配给 self 在 Python 中与在 ObjC 中的作用不同。在 PyObjC 中它通常仍然是惯用的风格,但不要被它误导;它的唯一效果是如果你使用 @987654337 @ 再次在初始化方法中。无论如何,充其量只能掩盖 ObjC 中的问题,而不是修复它......)所以,从这个方法返回后,你的 self 仍然是分配但未初始化的 NSPanel 实例那是在你打电话之前。

    这在本教程的早期大部分都在 Two Phase Instantiation 中进行了解释。

    【讨论】:

    • 谢谢@abamert!您的答案包含我想要(和需要)知道的一切!我忍不住说“尤里卡!”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-10
    • 2018-03-10
    • 1970-01-01
    • 1970-01-01
    • 2019-01-04
    • 2011-03-15
    相关资源
    最近更新 更多