在属性更改时强制重绘自定义可可控件

发布于 2024-09-15 18:40:42 字数 152 浏览 4 评论 0原文

假设我有一个名为 FooBox 的自定义控件。它只是屏幕上的一个正方形。它有一些属性,如颜色、边框等。当我更改属性时,我希望 FooBox 重新绘制自身以反映其新属性。有没有办法做到这一点,而无需编写自定义设置器并将 [self setNeedsDisplay:YES] 放入所有设置器中?

Lets say I have a custom control called FooBox. It is just a square on the screen. It has some properties like color, border, etc. When I change the properties, I want the FooBox to redraw itself to reflect its new properties. Is there a way to do that without writing custom setters and putting [self setNeedsDisplay:YES] into all of them?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

岁吢 2024-09-22 18:40:43

编辑:彼得在评论中是正确的,该解决方案仅在为该属性注册了观察者的情况下才有效。我现在记得我是在具有 @dynamic 属性的 CALayer 上完成此操作的,在这种情况下,它可以按照您的意愿工作。但在一般情况下,这并不是解决您问题的好方法。

假设您的类对于要触发重新显示的属性符合 KVC 标准,我将重写 -didChangeValueForKey: 方法,以在键匹配时调用 [self setNeedsDisplay]您的财产。我认为这比 Peter 的重写 -setValue:forKey: 的方法稍好一些,因为它不会妨碍正常的 KVC 机制,也不需要他提到的拳击。

- (void)didChangeValueForKey:(NSString*)key {
    if ([@"propertyOne" isEqualToString:Key] ||
        ....) {
        [self setNeedsDisplay];
    }
    [super didChangeValueForKey:key]; // <- Don't forget this
}

EDIT: Peter is right in the comments, this solution only works if there is an observer registered for that property. I remember now that I had done this on a CALayer with @dynamic properties, in which case this works as you would like. In the general case though, this is not a good solution to your problem.

Assuming your class is KVC compliant for the properties which you want to trigger a redisplay, I would override the -didChangeValueForKey: method to call [self setNeedsDisplay] when the key matches one of your properties. I think this is slightly better than Peter's method of overriding -setValue:forKey: because it does not get in the way of the normal KVC machinery and doesn't require the boxing that he mentions.

- (void)didChangeValueForKey:(NSString*)key {
    if ([@"propertyOne" isEqualToString:Key] ||
        ....) {
        [self setNeedsDisplay];
    }
    [super didChangeValueForKey:key]; // <- Don't forget this
}
牵你手 2024-09-22 18:40:43

其他两种方法:

  1. 让任何发送视图的访问器消息在之后立即发送 setNeedsDisplay:YES 给它。并不总是可行,而且也同样麻烦。
  2. 重写 setValue:forKey: 以向其添加 setNeedsDisplay: 消息,并使用它来设置视图的属性。这将需要将任何数字或结构值装箱,这是一种麻烦。

所以,实际上,不。

Two other ways:

  1. Have whatever is sending the view the accessor message send setNeedsDisplay:YES to it immediately after. Not always possible, and no less of a hassle.
  2. Override setValue:forKey: to add the setNeedsDisplay: message to it, and use that to set the view's properties. This will require boxing up any numeric or structure values, which is trading one hassle for another.

So, effectively, no.

野味少女 2024-09-22 18:40:43

我不知道其中之一。如果这让我很烦恼的话,我会给自己写一些宏来实现这个目的。

I'm not aware of one. I'd write myself a few macros to do the trick if it bothered me enough.

陌伤浅笑 2024-09-22 18:40:43

如果通过 NSControl 更改属性,您始终可以放入

[theView setNeedsDisplay:YES]

NSControl 发送的操作。

If the properties are changed via an NSControl, you can always put

[theView setNeedsDisplay:YES]

in the action sent by the NSControl.

余生再见 2024-09-22 18:40:42

我不确定这是否是正确的方法,但您可以考虑使用 NSKeyValueObserving 并将对象注册为自身的观察者,并在 -observeValueForKeyPath:ofObject 中进行重绘:更改:上下文: 方法。

I am not certain if this is the right way to do it, but you could consider using NSKeyValueObserving and register the object as observer of itself, and do the redrawing in the -observeValueForKeyPath:ofObject:change:context: method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文