首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在事件处理程序中绘制到NSView

在事件处理程序中绘制到NSView
EN

Stack Overflow用户
提问于 2018-04-26 20:43:33
回答 1查看 112关注 0票数 0

我试过所有我能想到的,但没有运气。

我有一个项目,本质上是一种编程语言的“解释器”。因此,事件被传递给解释器循环,解释代码做任何事情(在本例中,更新内存位图),然后解释器循环返回,事件处理程序返回。最终,应用程序的drawRect被调用,内存位图被绘制到NSView。大部分时间都很好。

但是..。有几种情况下,被解释的“代码”想要产生一个简短的动画,并通过更新内存位图、usleep()进行几毫秒的更新、更新内存位图、usleep()'ing等等来实现这一点。动画所花费的时间略短于一秒钟,所以线程阻塞不应该是一个问题。

问题是没有任何动画显示,直到解释的“代码”结束后,屏幕才会更新,事件才会返回。

当解释的代码指示要睡觉时调用的睡眠函数如下所示:

代码语言:javascript
复制
void KSleep(DWORD tm) {

    if( [pView lockFocusIfCanDraw] ) {
        inSleep = true;
        [pView setNeedsDisplay:YES];
        [pView display];
        [pView drawRect:NSMakeRect(0, 0, pView.frame.size.width, pView.frame.size.height)];
        [pView unlockFocus];
    }
    usleep(tm*1000);
}

“inSleep”是我为测试目的而设置的全局变量,“pView”是指向窗口唯一视图的全局NSView*。注意:是的,上面的一些代码是多余的,我只是想说明我尝试过多种组合,试图向操作系统表示视图是脏的,并对其进行更新。他们都没有工作过。

drawRect代码(删除所有执行位图滚动操作的代码)如下所示:

代码语言:javascript
复制
-(void)drawRect:(CGRect)rect {

    CGContextRef context = [[NSGRaphicsContext currentContext] graphicsPort];
    CGContextSaveGState(context);
    if( inSleep ) CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
    else CGContextSetRGBFillColor(context, 1.0, 1.0, 0.0, 1.0);
    CGContextFillRect(context, CGRectMake(0,0,200,200));
    CGContextRestoreGState(context);
}

所以:

1)发生-mouseDown()事件,并使用该事件调用解释器。

2)解释的代码会绘制到位图(我在这里忽略了这一点,因为它对屏幕更新的工作或不工作并不重要),并调用“睡眠”。

3)看到“睡眠”调用的解释器调用Ksleep() (上面)。

4)睡眠锁定焦点,这似乎创建了一个上下文,因为没有它,调试器就会在drawRect()函数中发出0x0上下文的警告,而对于lockFocus,它没有并且似乎有一个有效的上下文值。

5)将视图标记为需要更新,并调用(不同的)“display”和/或“drawRect”等。

6) drawRect例程得到控制(断点表示在这方面一切正常)。“inSleep”设置正确。它像预期的那样在drawRect中完成了所有的事情。但在展览上什么也没有显示,直到.

7) drawRect返回睡眠,睡眠超时,解释器继续解释,解释代码做更多的绘图和更多的睡眠,大约10次(因此重复步骤2-7大约10次)。

从程序开始到鼠标操作导致“动画”尝试为止,视图中将绘制一个黄色的矩形。一旦鼠标点击“动画”,在动画完全完成之前,窗口中什么都不会更新(即使drawRect在整个动画尝试中多次执行),矩形就会变成蓝色。但是断点显示,每次调用drawRect ()例程时,执行都会通过inSleep( true)。

这是线程问题吗?(程序没有显式地创建任何线程。)

我并不是特别想知道如何避免动画/睡眠结构的建议,我意识到这不是一种首选的Macos方法,但这是试图从其他地方移植一个旧项目,并且修改“解释”代码以避免这种情况是不可能的。

谢谢你的意见和建议。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-04-27 22:21:31

我找到的解决方案是将所有解释器代码放到第二个线程中,释放主线程以更新显示。即使drawRect例程正在运行和绘图,直到当前的“命令解释”循环完成并返回之后,它才会被刷新到显示上。此页面包含大量有关主题的信息:index.html

此外,所有‘失效’调用/语句都必须保存/缓冲到一个公共的“包含所有无效日期的最小矩形”中,然后在执行“命令解释”返回和/或之前执行无效操作。

皮塔。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50051544

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档