Xamarin.Mac 尽管有 NeedsDisplay,但未调用 NSView DrawRect
Xamarin.Mac NSView DrawRect not called despite NeedsDisplay
我正在尝试创建一个视图,表示在另一个视图中水平移动的垂直线。
我有以下 ViewController 和自定义视图。
using System;
using System.Timers;
using AppKit;
using CoreGraphics;
namespace CustomControlExperiment
{
public partial class ViewController : NSViewController
{
private Timer _timer;
private LineControl _lineControl;
public ViewController(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
var frame = new CGRect { X = 0, Y = 0, Height = ContentView.Frame.Height, Width = 1 };
_lineControl = new LineControl(frame);
ContentView.AddSubview(_lineControl);
_timer = new Timer(500);
_timer.Elapsed += _timer_Elapsed;
_timer.Start();
}
private void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
_lineControl.Position++;
}
}
public class LineControl : NSView
{
private float _position;
public LineControl(CGRect frameRect) : base(frameRect)
{
Initialize();
}
private void Initialize()
{
WantsLayer = true;
}
public override void DrawRect(CGRect dirtyRect)
{
Console.WriteLine("DrawRect");
base.DrawRect(dirtyRect);
var context = NSGraphicsContext.CurrentContext?.CGContext;
if (context == null)
{
return;
}
var height = Frame.Height;
context.SetStrokeColor(new CGColor(.5f, .6f, .7f));
context.SetLineWidth(1f);
context.SetLineDash(0, new nfloat[] { 3, 3 });
context.MoveTo(0, 0);
context.AddLineToPoint(0, height);
context.StrokePath();
}
public float Position
{
get => _position;
set
{
_position = value;
Console.WriteLine("Position = " + _position);
NeedsDisplay = true;
}
}
}
}
DrawRect 在程序第一次运行时被调用一次运行。之后它不再被调用,尽管 Position 被增加并且 NeedsDisplay 被设置。
我做错了什么?
System.Timers.Timer
elapsed 事件在线程池线程上 运行 - 在主线程外设置 needsDisplay
是非法的。如果您在 Xcode 中尝试此操作,这是线程清理程序的 运行 时间错误。
您需要修改您的代码,以便从主线程更新 Position
,或者将设置 needsDisplay
的调用编组到主线程。
在 .NET 和 Xamarin 中有多种方法 - here 是一份建议使用 InvokeOnMainThread
的文档(它适用于 iOS,但我相信它也适用于 macOS) .
我正在尝试创建一个视图,表示在另一个视图中水平移动的垂直线。
我有以下 ViewController 和自定义视图。
using System;
using System.Timers;
using AppKit;
using CoreGraphics;
namespace CustomControlExperiment
{
public partial class ViewController : NSViewController
{
private Timer _timer;
private LineControl _lineControl;
public ViewController(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
var frame = new CGRect { X = 0, Y = 0, Height = ContentView.Frame.Height, Width = 1 };
_lineControl = new LineControl(frame);
ContentView.AddSubview(_lineControl);
_timer = new Timer(500);
_timer.Elapsed += _timer_Elapsed;
_timer.Start();
}
private void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
_lineControl.Position++;
}
}
public class LineControl : NSView
{
private float _position;
public LineControl(CGRect frameRect) : base(frameRect)
{
Initialize();
}
private void Initialize()
{
WantsLayer = true;
}
public override void DrawRect(CGRect dirtyRect)
{
Console.WriteLine("DrawRect");
base.DrawRect(dirtyRect);
var context = NSGraphicsContext.CurrentContext?.CGContext;
if (context == null)
{
return;
}
var height = Frame.Height;
context.SetStrokeColor(new CGColor(.5f, .6f, .7f));
context.SetLineWidth(1f);
context.SetLineDash(0, new nfloat[] { 3, 3 });
context.MoveTo(0, 0);
context.AddLineToPoint(0, height);
context.StrokePath();
}
public float Position
{
get => _position;
set
{
_position = value;
Console.WriteLine("Position = " + _position);
NeedsDisplay = true;
}
}
}
}
DrawRect 在程序第一次运行时被调用一次运行。之后它不再被调用,尽管 Position 被增加并且 NeedsDisplay 被设置。
我做错了什么?
System.Timers.Timer
elapsed 事件在线程池线程上 运行 - 在主线程外设置 needsDisplay
是非法的。如果您在 Xcode 中尝试此操作,这是线程清理程序的 运行 时间错误。
您需要修改您的代码,以便从主线程更新 Position
,或者将设置 needsDisplay
的调用编组到主线程。
在 .NET 和 Xamarin 中有多种方法 - here 是一份建议使用 InvokeOnMainThread
的文档(它适用于 iOS,但我相信它也适用于 macOS) .