MonoTouch -- SetNeedsDisplay 不会刷新我的自定义 UIView

发布于 2024-10-16 03:33:41 字数 3346 浏览 4 评论 0原文

简单的概念:我有一个自定义 UIView,它绘制一条路径(一系列线条)。这些线条由用户通过触摸来定义。触摸后,我希望 Draw 方法重新绘制更新的路径/线条。代码:

这是我的自定义 UIView,名为“Renderer”:

public partial class Renderer : MonoTouch.UIKit.UIView
{
    enum eClickMode
    {
        BeginPoint,
        ControlPoint,
        EndPoint
    }

    eClickMode _ClickMode = eClickMode.BeginPoint;
    CGPath _Path = new CGPath();
    PointF _ControlPoint, _EndPoint;
    UIImage _ImageRough;
    UIColor _Rough;

    public Renderer (IntPtr ptr)
    {
        _ImageRough = new UIImage("/Users/general/Desktop/deeprough.jpg");
        _Rough = UIColor.FromPatternImage(_ImageRough);

        UIColor.Black.SetStroke();

        // Set initial path to make sure something gets drawn
        _Path = new CGPath();
        _Path.MoveToPoint(100, 100);
        _Path.AddQuadCurveToPoint(200, 200, 100, 300);
    }

    public override void Draw (RectangleF rect)
    {
        base.Draw (rect);

        CGContext gfx = UIGraphics.GetCurrentContext();
        _Rough.SetFill();
        gfx.SetLineWidth(0);
        gfx.AddPath(_Path);
        gfx.DrawPath(CGPathDrawingMode.FillStroke);
    }

    public override void TouchesEnded (NSSet touches, UIEvent evt)
    {
        base.TouchesEnded (touches, evt);
        UITouch touch = touches.ToArray<UITouch>()[0];
        PointF pt = touch.LocationInView(this);

        switch (_ClickMode)
        {
            case Renderer.eClickMode.BeginPoint:
                _Path.MoveToPoint(pt);
                _ClickMode = Renderer.eClickMode.ControlPoint;
                break;
            case eClickMode.ControlPoint:
                _ControlPoint = pt;
                _ClickMode = Renderer.eClickMode.EndPoint;
                break;
            case eClickMode.EndPoint:
                _EndPoint = pt;
                _Path.AddQuadCurveToPoint(_ControlPoint.X, _ControlPoint.Y, _EndPoint.X, _EndPoint.Y);
                _Path.MoveToPoint(_EndPoint);
                this.SetNeedsDisplay();
                break;
        }
    }
}

这是我的 MainWindow.Designer 代码:

[MonoTouch.Foundation.Register("AppDelegate")]
public partial class AppDelegate {

    private MonoTouch.UIKit.UIWindow __mt_window;

    private Renderer __mt_renderer;

    #pragma warning disable 0169
    [MonoTouch.Foundation.Connect("window")]
    private MonoTouch.UIKit.UIWindow window {
        get {
            this.__mt_window = ((MonoTouch.UIKit.UIWindow)(this.GetNativeField("window")));
            return this.__mt_window;
        }
        set {
            this.__mt_window = value;
            this.SetNativeField("window", value);
        }
    }

    [MonoTouch.Foundation.Connect("renderer")]
    private Renderer renderer {
        get {
            this.__mt_renderer = ((Renderer)(this.GetNativeField("renderer")));
            return this.__mt_renderer;
        }
        set {
            this.__mt_renderer = value;
            this.SetNativeField("renderer", value);
        }
    }
}

// Base type probably should be MonoTouch.UIKit.UIView or subclass
[MonoTouch.Foundation.Register("Renderer")]
public partial class Renderer {
}

我确信在 TouchesEnded 方法中, this.SetNeedsDisplay() 会受到攻击。但 Draw 方法仅在最初被调用。

我见过其他线程指出 Objective-C 中存在类似问题,但解决方案似乎始终与线程有关。好吧,我没有线程(至少我没有尝试)。这似乎是一个简单的概念(它在 .Net 中)。非常感谢任何帮助。

Simple concept: I have a custom UIView which draws a path (series of lines). These lines are defined by the user via touches. After a touch, I want the Draw method to redraw the updated path/lines. Code:

Here is my custom UIView called "Renderer":

public partial class Renderer : MonoTouch.UIKit.UIView
{
    enum eClickMode
    {
        BeginPoint,
        ControlPoint,
        EndPoint
    }

    eClickMode _ClickMode = eClickMode.BeginPoint;
    CGPath _Path = new CGPath();
    PointF _ControlPoint, _EndPoint;
    UIImage _ImageRough;
    UIColor _Rough;

    public Renderer (IntPtr ptr)
    {
        _ImageRough = new UIImage("/Users/general/Desktop/deeprough.jpg");
        _Rough = UIColor.FromPatternImage(_ImageRough);

        UIColor.Black.SetStroke();

        // Set initial path to make sure something gets drawn
        _Path = new CGPath();
        _Path.MoveToPoint(100, 100);
        _Path.AddQuadCurveToPoint(200, 200, 100, 300);
    }

    public override void Draw (RectangleF rect)
    {
        base.Draw (rect);

        CGContext gfx = UIGraphics.GetCurrentContext();
        _Rough.SetFill();
        gfx.SetLineWidth(0);
        gfx.AddPath(_Path);
        gfx.DrawPath(CGPathDrawingMode.FillStroke);
    }

    public override void TouchesEnded (NSSet touches, UIEvent evt)
    {
        base.TouchesEnded (touches, evt);
        UITouch touch = touches.ToArray<UITouch>()[0];
        PointF pt = touch.LocationInView(this);

        switch (_ClickMode)
        {
            case Renderer.eClickMode.BeginPoint:
                _Path.MoveToPoint(pt);
                _ClickMode = Renderer.eClickMode.ControlPoint;
                break;
            case eClickMode.ControlPoint:
                _ControlPoint = pt;
                _ClickMode = Renderer.eClickMode.EndPoint;
                break;
            case eClickMode.EndPoint:
                _EndPoint = pt;
                _Path.AddQuadCurveToPoint(_ControlPoint.X, _ControlPoint.Y, _EndPoint.X, _EndPoint.Y);
                _Path.MoveToPoint(_EndPoint);
                this.SetNeedsDisplay();
                break;
        }
    }
}

Here is my MainWindow.Designer code:

[MonoTouch.Foundation.Register("AppDelegate")]
public partial class AppDelegate {

    private MonoTouch.UIKit.UIWindow __mt_window;

    private Renderer __mt_renderer;

    #pragma warning disable 0169
    [MonoTouch.Foundation.Connect("window")]
    private MonoTouch.UIKit.UIWindow window {
        get {
            this.__mt_window = ((MonoTouch.UIKit.UIWindow)(this.GetNativeField("window")));
            return this.__mt_window;
        }
        set {
            this.__mt_window = value;
            this.SetNativeField("window", value);
        }
    }

    [MonoTouch.Foundation.Connect("renderer")]
    private Renderer renderer {
        get {
            this.__mt_renderer = ((Renderer)(this.GetNativeField("renderer")));
            return this.__mt_renderer;
        }
        set {
            this.__mt_renderer = value;
            this.SetNativeField("renderer", value);
        }
    }
}

// Base type probably should be MonoTouch.UIKit.UIView or subclass
[MonoTouch.Foundation.Register("Renderer")]
public partial class Renderer {
}

I know for sure that in the TouchesEnded method, this.SetNeedsDisplay() is getting hit. But the Draw method only gets called initially.

I've seen other threads indicating a similar problem in Objective-C, but the solution seems to always be about threading. Well, I'm not threading (at least I'm not trying to anyway). This seems like a simple concept (and it is in .Net). Any help is GREATLY appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

策马西风 2024-10-23 03:33:41

您没有在 UIView 子类上调用正确的基本构造函数,您有:

public Renderer (IntPtr ptr)

您想要

public Renderer (IntPtr ptr) : base (ptr)

You aren't calling the correct base constructor on your UIView subclass, you have:

public Renderer (IntPtr ptr)

You want

public Renderer (IntPtr ptr) : base (ptr)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文