繁体   English   中英

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

[英]Drawing to an NSView while inside an event handler

我已经尝试了所有我能想到的,但是没有运气。

我有一个项目,本质上是编程语言的“解释器”。 因此,事件被传递到解释器循环,解释后的代码执行任何操作(在这种情况下,将更新内存位图),然后解释器循环返回并且事件处理程序返回。 最终,应用程序的drawRect被调用,内存位图被绘制到NSView。 这是所有时间中最好的。

但是...在某些情况下,解释的“代码”想要引起简短的动画,并且通过更新内存位图,usleep()持续数毫秒,更新内存位图,usleep()来实现此目的等等。动画花费的时间不到一秒钟,因此线程阻塞不应该成为问题。

问题在于动画没有显示,并且直到解释的“代码”结束之后屏幕才更新,并且事件返回。

当解释后的代码指示其要休眠时,调用该睡眠函数如下所示:

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 *。 注意:是的,上面的某些代码是多余的,我只是将其包括在内,以表明我已经尝试了多种组合尝试向OS指示视图是否脏污并进行更新。 他们都没有工作。

drawRect代码(删除所有对位图进行普通处理的代码)如下所示:

-(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)解释器看到“ sleep”调用后,调用Ksleep()(如上)。
4)Ksleep锁定焦点,这似乎创建了一个上下文,因为没有焦点,调试器会在drawRect()函数期间吐出0x0上下文的警告,而使用lockFocus则不会,并且似乎具有有效的上下文值。
5)Ksleep将视图标记为需要更新,并(始终)调用“ display”和/或“ drawRect”等。
6)drawRect例程确实得到控制(断点表明在这方面一切正常。) 正确设置了“ inSleep”。 它按预期方式逐步完成了drawRect中的所有内容。 但是直到显示器上没有任何显示。
7)drawRect返回到Ksleep,睡眠超时,解释器继续解释,解释的代码执行更多绘制并进行更多睡眠,大约10次(因此重复步骤2-7大约10次)。

从程序启动到鼠标动作引起“动画”尝试的时间,视图中将绘制一个黄色矩形。 导致“动画”的鼠标单击发生后,窗口中的内容将没有更新,直到动画完全完成(即使drawRect在整个动画尝试中执行了多次),然后矩形也会变为蓝色。 但是断点表明,每次调用KSleep()例程时,执行IS都会通过drawRect(“ inSleep”为true)传递。

这是一件线事吗? (该程序未明确创建任何线程。)

我并不是特别在寻找有关如何避免使用动画/ KSleep结构的建议,我意识到这不是Macos的首选处理方法,但这是一种尝试从其他地方移植旧项目并修改“解释的”代码的尝试。避免这种情况是不可能的。

感谢您的任何想法或建议。

我发现的解决方案是将所有解释器代码放入第二个线程,释放主线程以能够更新显示。 即使drawRect例程正在运行并进行绘制,也要等到当前的“命令解释”循环完成并返回后,它才会刷新到显示。 该页面包含有关此主题的大量信息: https : //developer.apple.com/library/content/technotes/tn2133/_index.html

另外,所有“无效”调用/语句都必须保存/缓冲到一个公共的“最小矩形,其中包括所有无效”,然后在“命令解释”返回AND / OR后再执行一次无效操作( ) 已经完成。

皮塔饼

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM