NSView 中的多线程绘制

2024-02-07

在我的代码中,我子类化了NSView并在其drawRect方法中,我生成三个线程来执行绘图。

-(void)drawRect:(NSRect)dirtyRect
{
    [[self window] setAllowsConcurrentViewDrawing:YES];
    [self setCanDrawConcurrently:YES];

    [NSThread detachNewThreadSelector:@selector(DrawText) toTarget:self withObject:nil];
    [NSThread detachNewThreadSelector:@selector(DrawRectangle) toTarget:self withObject:nil];
    [NSThread detachNewThreadSelector:@selector(DrawGradient) toTarget:self withObject:nil];

    //Wherease these functions DrawText, DrawRectangle and DrawGradient performs their task as suggested by name.

    //In DrawText, DrawRectangle, and DrawGradient lockFocus and unlockFocus is being
    // used for multithreaded drawing.

}

When I run the same program from Xcode, it is running fine. Output is shown below. Single threaded

But when I run it from the outside, there is problem and output is shown below. Multithreaded

首先,我想知道从辅助线程绘制是否正确?或者从辅助线程中绘制的另一种方法是什么?

这个问题背后的原因是什么?


Ken Aspeslagh 对于从辅助线程进行绘制有些不正确(他是正确的,这通常是一个坏主意)。从我所看到的你的代码来看,你没有一个很好的用例来在辅助线程上绘图。您能解释一下为什么要这样做吗?

你自己已经发现了setCanDrawConcurrently:其中明确谈到调用drawRect:来自后台线程。请注意,视图窗口必须具有allowsConcurrentViewDrawing设置为 YES 才能正常工作(这是默认值)。

苹果自己的可可绘图指南 https://developer.apple.com/library/mac/documentation/cocoa/conceptual/CocoaDrawingGuide/GraphicsContexts/GraphicsContexts.html有一个关于从辅助线程绘图的部分。我强调了一些我认为与您相关的部分。

应用程序工具包为每个窗口和线程组合维护一个独特的图形上下文。由于每个线程对于给定窗口都有自己的图形上下文对象,因此可以使用辅助线程来绘制该窗口。不过,也有一些注意事项。

在窗口的正常更新周期中,所有绘图请求都会发送到应用程序的主线程进行处理。当用户事件触发用户界面的更改时,就会发生正常的更新周期。在这种情况下,您可以从应用程序的主线程调用 setNeedsDisplay: 或 setNeedsDisplayInRect: 方法(或显示方法系列)以使视图中需要重绘的部分无效。您不应从任何辅助线程调用这些方法。

如果要从辅助线程更新窗口或视图,则必须手动将焦点锁定在窗口或视图上并自行启动绘制。锁定焦点会配置该窗口的图形上下文的绘图环境。锁定后,您可以配置绘图环境,照常发出绘图命令,然后将图形上下文的内容刷新到窗口缓冲区。

为了定期在辅助线程上绘图,您必须自己通知该线程。发送定期通知的最简单方法是使用 NSTimer 或 NSAnimation 对象。有关如何制作内容动画的更多信息,请参阅“高级绘图技术”。

Cocoa 线程编程指南 https://developer.apple.com/library/mac/documentation/cocoa/conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html还这样说:

如果要使用线程绘制视图,请将所有绘制代码​​放在 NSView 的 lockFocusIfCanDraw 和unlockFocus 方法之间

顺便说一句,GCD 块调用可能是一种比在后台执行少量操作更好的方法NSThread.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    // you can put each of these calls in their own queue if you want
    [self DrawText];
    [self DrawRectangle];
    [self DrawGradient];
});

但是,这可能与您的问题无关;我提到它只是因为我认为使用 GCD 队列会更好地为你服务。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NSView 中的多线程绘制 的相关文章

随机推荐

  • 如果所有子域都指向网站根目录,是否需要通配符 SSL 证书

    我对 SSL 证书完全陌生 需要很快购买一个 当子域名发挥作用时 价格似乎会大幅上涨 我的问题是这样的 我已经设置了我的网站 以便用户名 domain com通过 htaccess 重写为域名 com user 用户名 如果我将网站设置为所
  • Java ASM 字节码修改-更改方法体

    我有一个罐子里的类的方法 我想与我自己的主体交换 在这种情况下 我只想让该方法将 GOT IT 打印到控制台并返回 true 我正在使用系统加载器来加载 jar 的类 我使用反射使系统类加载器能够通过字节码加载类 这部分似乎工作正常 我正在
  • 如何将列与 Flexbox 对齐?

    我目前正在学习 Flexbox 布局 但找不到解决我的问题的方法 我尝试使用 justify content 和 flex basis 但它不起作用 有人有解决办法吗 The result I would like section disp
  • .NET Core RC2 中的登录声明

    我正在将 NET 4 6 版本移植到 NET Core RC2 并想知道如何在 NET Core RC2 中执行以下操作 public async Task
  • 如何在 SQL Server 中将多行转换为列?

    如何将存储为多行的字段转换为列 我也在下面列出了代码 下面是所需内容的示例 但实际上最多可以包含 20 列 谢谢 COL1 COL2 COL3 TEST 30 NY TEST 30 CA TEST2 10 TN TEST2 10 TX 我希
  • DialogFragment 行为异常

    您好 我已使用此 DialogFragment 在我的应用程序中显示日期选择器 public class DateDialogFragment extends DialogFragment implements DatePickerDial
  • 如何在linux中用C设置IP地址

    通过使用strace and ifconfig 我发现可以这样设置IP地址 include
  • 无模式、无父的 wxDialog 仍然始终位于 z 顺序中的 wxFrame 窗口之上?

    我的程序打开一个基于 wxFrame 的窗口和多个无模式且无父的基于 wxDialog 的窗口 除了基于 wxDialog 的窗口坚持始终位于基于 wxFrame 的窗口之上之外 这一切都工作得很好 我知道关于wxDIALOG NO PAR
  • 安装 Mac Homebrew 时遇到问题

    我尝试了各种论坛和谷歌 但没有成功 我正在尝试在 OS X 10 6 8 上安装 Mac Homebrew 当我尝试从 Homebrew 主页执行安装命令时 ruby lt curl fsSkL raw github com mxcl ho
  • 当包含的控件获得焦点时防止自动滚动

    我有一个Panel有两个Button其上有一个 其中一个部分被隐藏 当部分隐藏的按钮获得焦点时 例如当单击另一个按钮然后单击它 原始按钮 时 面板会滚动 我需要垂直滚动条 但不需要auto滚动 并且如果没有自动滚动 似乎无法获得有效的滚动条
  • 过滤 CollectionViewSource

    我想做一个ComboBox绑定到我的数据 带有filter 为此我创建了一个TextBox and a ComboBox 在后面的代码中 我读取一个文件并生成 Channel 类的对象 这些对象存储为ComboBox 尽管编译器不会抛出任何
  • Javascript 中最快的类/对象访问/实例化是什么

    在探索构建类的几种不同方法时 我很好奇实例化和访问类的最快方法是什么 基于另一个问题的输入 Javascript 作用域和 self this this this that this https stackoverflow com ques
  • 克隆 git 存储库并保留无法访问的提交

    有没有办法克隆远程 git 存储库 同时保留该存储库中可能存在的任何无法访问的提交 场景是这样的 我需要恢复从我维护的服务器上的裸 git 存储库中删除的分支 我有这个分支的最后一次提交的哈希值 但是常规的 git 命令似乎无法在裸存储库上
  • 实体框架数据上下文与数据库不同步?

    所以 情况是这样的 我调用 AddtoObject 在数据库中插入一个项目 然后调用 SaveChanges 然后 我调用存储过程来更新当前插入的记录 然后 我再次调用 Save Changes 当我查询数据库时它具有正确的更新值 但是实体
  • 使用 EGIT 获取时存储凭据失败

    最初我遇到了与中描述的相同的问题egit 未授权 https stackoverflow com questions 14259265 egit not authorized 首先 我成功从 Bitbucket 克隆了存储库 然后 我尝试获
  • 是否可以在 ScrollView 中添加 ViewPager?

    我正在尝试使用ViewPager里面的一个ScrollView 但是ViewPager没有出现 如果我删除ScrollView the ViewPager看起来不错 我创建了一个简单的测试项目 内容如下 main xml布局
  • 将引用类型和值类型作为参数传递给方法之间的区别

    一整天都在我的脑海中萦绕着这种困惑 我对传递给方法的引用类型和值类型感到非常困惑 假设我有 2 节课Class A and Class B分别对应于引用类型和值类型 public Class A public static void mai
  • 通过 websocket 的 SIP 到真正的 SIP

    我正在尝试实现一个 sip 服务器用于从HTMLsip客户端 使用sipml5制作 在我研究这样做的过程中 我遇到了 sip over web sockets 这可能对我有用 但是 我不确定用户代理是否通过 sip over 连接web s
  • 从 FlinkML 多元线性回归中提取权重

    我正在运行 Flink 0 10 SNAPSHOT 的示例多元线性回归 我不知道如何提取权重 例如斜率和截距 beta0 beta1 无论你想怎么称呼它们 我对 Scala 不太熟悉 这可能是我问题的一半 感谢任何人可以提供的任何帮助 ob
  • NSView 中的多线程绘制

    在我的代码中 我子类化了NSView并在其drawRect方法中 我生成三个线程来执行绘图 void drawRect NSRect dirtyRect self window setAllowsConcurrentViewDrawing