Cocoa 使用invalidate命令重复使窗口无效的最佳方法是什么?

Cocoa 使用invalidate命令重复使窗口无效的最佳方法是什么?,cocoa,winapi,paint,wm-paint,Cocoa,Winapi,Paint,Wm Paint,我需要反复重画一个窗口,显示某种形式的连续分析。现在: 1) 如果我在画完后在WM_PAINT中这样做,我基本上会杀死其他人的画,所以它不可用 2) 如果我在计时器中这样做,它有点滞后 因此,最好的方法是什么,以便频繁地重新绘制窗口,但当操作系统忙于处理某些数据或绘制其他应用程序时,会降低速率。我一直认为,操作系统应该注意在离开图形辅助系统的进程之间分配CPU功率,以确保实际处理有足够的时间,但在Windows或Mac上,情况并非如此。通常,您会创建一个计时器,并在每个计时器滴答声时使窗口无效。

我需要反复重画一个窗口,显示某种形式的连续分析。现在:

1) 如果我在画完后在WM_PAINT中这样做,我基本上会杀死其他人的画,所以它不可用

2) 如果我在计时器中这样做,它有点滞后


因此,最好的方法是什么,以便频繁地重新绘制窗口,但当操作系统忙于处理某些数据或绘制其他应用程序时,会降低速率。我一直认为,操作系统应该注意在离开图形辅助系统的进程之间分配CPU功率,以确保实际处理有足够的时间,但在Windows或Mac上,情况并非如此。

通常,您会创建一个计时器,并在每个计时器滴答声时使窗口无效。如果存在延迟,则可能是更新频率太高,或者在绘制方法中执行的处理成本太高

请记住,具有复杂3D场景的游戏通常可以达到60帧(甚至更高)。因此,高帧率更新当然是可能的

请注意,在Windows下,
WM_TIMER
事件的不一致性是出了名的。如果需要超过1秒的分辨率,您可能需要探索其他高分辨率计时器

在Mac电脑上,您可以创建一个
NSTimer
并在
NSView
上调用
setNeedsDisplay:YES
。大概是这样的:

// in your init... method
NSTimer* repaintTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
    target:self
    selector:@selector(timerTickHandler:)
    userInfo:nil
   repeats:YES];

// ...

-(void)timerTickHandler(NSTimer*)timer {
    [self.view setNeedsDisplay:YES];
}
Cocoa中的
NSTimer
非常可靠,因此即使对于非常快速的更新,上述操作也应该可以正常工作


如果需要以帧速率(即25fps)进行更新,请查看
CVDisplayLink
支持。这实际上仅适用于视频应用程序等。

如果更改显示它的视图后面的数据,
invalidate()
触发绘制位应该是正常的。但是,除了更新的区域之外,您不需要使任何区域无效,因此您可能需要采取额外的措施来实现这一点。但是,在你完成一个
WM_绘画之后,千万不要使它无效(也就是说,在你的
EndPaint
之后。这太疯狂了。相反,将一个线程事件或用户事件从你的数据计算代码发布到你的队列中,并将该处理程序放在你的窗口proc
invalidate竖立
,可能还有
UpdateWindow
。这或多或少就是我现在正在做的。我尝试过的wm_paint中的失效的极端做法只是为了“好玩”,这真的没有多大意义。虽然如果操作系统能够很好地分配cpu,这将是在不填充请求队列的情况下获得最大帧速率的理想选择。cocoa标签是因为我对Mac上的相同内容感兴趣。谢谢,这就是我现在想尝试的。顺便说一句,真的是1秒分辨率吗?嗯,
WM_TIMER
是有问题的由于多个事件在
GetMessage()
中作为一个标志实现时可以合并。如果您需要精确的计时器,有几个选项。例如,看看多媒体计时器。您没有提到正在使用的框架,但这个比较值得一读。