【问题标题】:How to draw digital signal in WPF?如何在 WPF 中绘制数字信号?
【发布时间】:2014-03-04 22:29:56
【问题描述】:

我需要绘制数字信号并能够在 WPF 中移动线条的每一部分。

如下图所示,箭头指示线的一部分可以移动到哪个方向。单击并拖动“可点击区域”将向左或向右移动整个正方形。

我想了几种方法:

  1. Polyline 对象。但我无法控制生产线的每一部分。
  2. Line 对象。每次更改时,所有行都应调整其位置。难以控制“可点击区域”。也许也很复杂。
  3. Border 对象。每个部分实际上都是一个边框,它将显示/隐藏适当的边框。我不确定使边框的可移动边有多容易。
  4. 其他选项...

我的问题是,最正确的开始方法是什么?

【问题讨论】:

  • 我想我会从 Rectangles 开始并收集一组点,从中绘制 GraphicsPath。这是我对从哪里开始的建议。以前没有做过这样的事情。
  • 如果我是你,我会编辑你的问题,使其不那么主观,更实用,除非你希望它因主要基于意见而被关闭。
  • @Sheridan,你有什么建议? “如何画数字……”更好?
  • 您可以创建一个由线条和矩形组成的混合对象,可点击区域。
  • 我喜欢边框或矩形的想法,每个脉冲一个。不知道为什么要提高/降低数字信号的高低。当你提高低点时,你会提高所有的低点吗?您可以通过在 Canvas 上设置它的 XY 来放置边框,脉冲的宽度就是边框的宽度。

标签: c# .net wpf user-interface


【解决方案1】:

需要考虑的几件事...

  • Thumb 是一个很好的控件来启动您的可拖动事物,因为它已经提供了可以处理的适当事件来移动它。通过模板化,你可以给它任何你喜欢的形状。

  • 您可以通过巧妙地使用Grid 和适当放置的网格拆分器免费获得可拖动的线条。如果这不起作用,那么 4 个矩形可以很好地工作。您将它们放在一个DockingPanel 中,放置顶部、左侧、右侧和最后一个填充,并且您有足够的基元来响应所有需要的事件。

【讨论】:

  • Thumb 真的很有帮助。谢谢!
【解决方案2】:

如果你愿意,我可以编写代码,但我会这样做......

维护一对列表 按X 排序。在自定义控件中执行此操作。

在 for 循环中绘制它。通过搜索列表来确定点击次数。处理一些鼠标拖动,更新屏幕。

for 循环会查看 mylist[i] 和 mylist[i+1]。使用该信息绘制矩形。

我通常不会在 WPF 中编写代码,但如果您愿意,我可以在半小时内搞定。

这是一些代码............将代码添加到命名空间,构建然后将组件添加到表单:

 public class Pair
{
    public Pair()
    {
    }

    public Pair(float first, float second)
    {
        this.First = first;
        this.Second = second;
    }

    public float First { get; set; }
    public float Second { get; set; }
};

public class ImageButton :  FrameworkElement
{
    List<Pair> items;
    Boolean dragDown = false;
    bool dragVert = false;
    int dragSeg = -1;


    public ImageButton()  {
        items = new List<Pair>();
        items.Add(new Pair(0, 0));
        items.Add(new Pair(40, 40));
        items.Add(new Pair(60, 0));
        items.Add(new Pair(100, 20));
        items.Add(new Pair(115, 0));
        items.Add(new Pair(185, 20));
        items.Add(new Pair(215, 0));
        items.Add(new Pair(300, 0));

    }

    protected override void OnMouseDown(MouseButtonEventArgs e)
    {
        int seg;
        bool vert;

        if (getSegment(e.GetPosition(this).X, e.GetPosition(this).Y, out seg, out vert))
        {
            dragDown = true;
            dragSeg = seg;
            dragVert = vert;
            //We are dragging now
        }

        base.OnMouseDown(e);
    }
    protected override void OnMouseUp(MouseButtonEventArgs e)
    {
        dragDown = false;
        base.OnMouseUp(e);
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        double basey = RenderSize.Height - 10;

        int seg;
        bool vert;
        if (!dragDown)
        {

            if (getSegment(e.GetPosition(this).X, e.GetPosition(this).Y, out seg, out vert))
            {
                if (vert)
                {
                    Cursor = Cursors.SizeWE;
                }
                else
                {
                    Cursor = Cursors.SizeNS;
                };

            }
            else
            {
                Cursor = Cursors.No;
            }
        }
        else
        {
            //Must be dragging.
            if (dragVert)
            {
                //This will change the X position of the segment...........
                items[dragSeg].First = (int) e.GetPosition(this).X;
                InvalidateVisual();
            }
            else
            {
                items[dragSeg].Second = (int)(basey - ((int)e.GetPosition(this).Y));
                //Change vertical
                InvalidateVisual();
            }
        }
        base.OnMouseMove(e);
    }

    protected override void OnRender(DrawingContext dc)
    {
        Brush b = new SolidColorBrush(Color.FromRgb(40,40,40));
        dc.DrawRectangle(b, new Pen(b, 2), new Rect(0, 0, this.RenderSize.Width, RenderSize.Height));
        Pen p = new Pen(new SolidColorBrush(Color.FromRgb(240, 240, 240)), 2);
        double basey = RenderSize.Height - 10;
        for (int i = 0; i < items.Count-1; i++)
        {
            Brush br = new SolidColorBrush(Color.FromRgb(240, 40, 40));
            Rect t = new Rect(items[i].First,basey-items[i].Second, items[i+1].First-items[i].First,items[i].Second);
            dc.DrawRectangle(br, p, t);
        }
    }
    /// <summary>
    /// Returns if over a segment, and how.  
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <returns></returns>
    bool getSegment(double x, double y, out int index, out bool vert)
    {
        double basey = RenderSize.Height - 10;
        index = 0;
        vert = false;

        for (int i = 0; i < items.Count - 1; i++)
        {
            //Check for vertical section going up
            if ((x >= (items[i].First - 3)) && ( x <= (items[i].First + 3))) {
                // x is hovering close to segment, check Y
                if ((y < (basey)) && (y>=(basey-items[i].Second))) {
                    index = i;
                    vert = true;
                    return true;
                }
            }

            //Check vertical going down.
            if ((x >= (items[i + 1].First - 3)) && (x <= (items[i + 1].First + 3)))
            {
                if ((y < (basey)) && (y >= (basey - items[i].Second)))
                {
                    index = i+1;
                    vert = true;
                    return true;
                }
            }

            //In the middle section
            if ((x >= (items[i].First) && (x <= (items[i+1].First)))) {
                //Check for close to line seg.
                if ((y < (basey - items[i].Second + 3)) && (y > (basey - items[i].Second - 3)))
                {
                    index = i;
                    vert = false;
                    return true;
                }
            }

        }
        return false;
    }
}

拖动段时,不要将它们重叠 - 我没有为此编写代码。但这允许看到信号并移动信号。

用鼠标调整大小后:

PS:我没有尝试优化或尝试生产代码,只是为你猛烈抨击。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-26
    • 2014-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 1970-01-01
    相关资源
    最近更新 更多