【问题标题】:Fastest way to draw shapes (Line, FilledRectangle, Rectangle etc)绘制形状的最快方法(线、FilledRectangle、矩形等)
【发布时间】:2012-07-17 00:00:22
【问题描述】:

我正在使用 C# 3.0 使用 .Net Compact Framework 3.5 开发一个项目。

我有一个用户控件,它每 15 毫秒接收一次数据,我必须绘制形状

像线条、矩形、用户控件上的填充矩形。

我想知道绘制这些形状的最快方法是什么,如果有一些提高性能和速度的方法,我也愿意使用 P/Invoke 方法。

我使用的代码如下:

     private void DrawThreeFunctions(Graphics g)
                {
                    // drawing back functions
                    if (DisplayFunction1.DrawOrder == DrawOrder.Back && GraphDataArray.Length > 0)
                    {
                        DrawFunction(g, DisplayFunction1, GraphDataArray[0]);
                    }
                    if (DisplayFunction2.DrawOrder == DrawOrder.Back && GraphDataArray.Length > 1)
                    {
                        DrawFunction(g, DisplayFunction2, GraphDataArray[1]);
                    }
                    if (DisplayFunction3.DrawOrder == DrawOrder.Back && GraphDataArray.Length > 2)
                    {
                        DrawFunction(g, DisplayFunction3, GraphDataArray[2]);
                    }
                    // drawing middle functions
                    if (DisplayFunction1.DrawOrder == DrawOrder.Middle && GraphDataArray.Length > 0)
                    {
                        DrawFunction(g, DisplayFunction1, GraphDataArray[0]);
                    }
                    if (DisplayFunction2.DrawOrder == DrawOrder.Middle && GraphDataArray.Length > 1)
                    {
                        DrawFunction(g, DisplayFunction2, GraphDataArray[1]);
                    }
                    if (DisplayFunction3.DrawOrder == DrawOrder.Middle && GraphDataArray.Length > 2)
                    {
                        DrawFunction(g, DisplayFunction3, GraphDataArray[2]);
                    }
                    // drawing front functions
                    if (DisplayFunction1.DrawOrder == DrawOrder.Front && GraphDataArray.Length > 0)
                    {
                        DrawFunction(g, DisplayFunction1, GraphDataArray[0]);
                    }
                    if (DisplayFunction2.DrawOrder == DrawOrder.Front && GraphDataArray.Length > 1)
                    {
                        DrawFunction(g, DisplayFunction2, GraphDataArray[1]);
                    }
                    if (DisplayFunction3.DrawOrder == DrawOrder.Front && GraphDataArray.Length > 2)
                    {
                        DrawFunction(g, DisplayFunction3, GraphDataArray[2]);
                    }
                } 


    private void DrawFunction(Graphics g, DisplayFunction function, int[] data)
            {
                Color color = Utils.GetColor(function.Color);
                switch (function.Shape)
                {
                    case FunctionShape.StepLine:
                        DrawStepLines(g, data, color);
                        break;
                    case FunctionShape.Rectangle:
                        DrawFilledRectangles(g, data, color);
                        break;
                    case FunctionShape.FramedRectangle:
                        DrawFramedRectangles(g, data, color);
                        break;
                    case FunctionShape.Line:
                        DrawLines(g, data, color);
                        break;
                    default:
                        break;
                }
            }

            #region Drawing methods
            // drawing lines
            private void DrawLines(Graphics g, int[] lineData, Color lineColor)
            {
                BarPositions = new List<int>();
                List<Point> linePoints = new List<Point>();
                int lineYPos = -1;
                int lineXPos = FirstBarDrawPosition;
                Point point = Point.Empty;

                using (Pen linePen = new Pen(lineColor, 2.0f))
                {
                    for (int i = FirstVisibleItemIndex, k = 0; i < _indexLimit; i++, k++)
                    {
                        if (base.GetBarEndPosition(k) > Width)
                            break;

                        lineXPos = GetTickPosition(k);
                        BarPositions.Add(lineXPos);

                        if (i < lineData.Length)
                            lineYPos = lineData[i];
                        else
                            continue;

                        point.X = lineXPos;
                        point.Y = lineYPos;

                        linePoints.Add(point);
                    }

                    if (linePoints.Any())
                    {
                        g.DrawLines(linePen, linePoints.ToArray());
                    }
                }
            }
            // drawing framed rectangles
            private void DrawFramedRectangles(Graphics g, int[] functionValues, Color functionColor)
            {
                BarPositions = new List<int>();

                int barXPos = FirstBarDrawPosition;
                Rectangle barRect = Rectangle.Empty;
                barRect.Width = WidthOfBar - 1;
                int barYPos = -1;

                using (Pen barPen = new Pen(functionColor))
                {
                    for (int i = FirstVisibleItemIndex, k = 0; i < _indexLimit; i++, k++)
                    {
                        if (base.GetBarEndPosition(k) > Width)
                            return;

                        BarPositions.Add(GetTickPosition(k));

                        if (i < functionValues.Length)
                            barYPos = functionValues[i];
                        else
                            continue;

                        //barRect = new Rectangle();
                        barRect.X = barXPos;
                        barRect.Y = barYPos;
                        //barRect.Width = WidthOfBar - 1;
                        barRect.Height = Height - barYPos;
                        g.DrawRectangle(barPen, barRect);
                        barXPos += (WidthOfBar + DistanceBetweenBars);
                    }
                }
            }
            // drawing filled rectangles
            private void DrawFilledRectangles(Graphics g, int[] functionValues, Color functionColor)
            {
                BarPositions = new List<int>();

                int barXPos = FirstBarDrawPosition;
                Rectangle barRect = Rectangle.Empty;
                barRect.Width = WidthOfBar;
                int barYPos = -1;

                using (SolidBrush barBrush = new SolidBrush(functionColor))
                {
                    for (int i = FirstVisibleItemIndex, k = 0; i < _indexLimit; i++, k++)
                    {
                        if (base.GetBarEndPosition(k) > Width)
                            return;

                        BarPositions.Add(GetTickPosition(k));

                        if (i < functionValues.Length)
                            barYPos = functionValues[i];
                        else
                            continue;

                        //barRect = new Rectangle();
                        barRect.X = barXPos;
                        barRect.Y = barYPos;
                        //barRect.Width = WidthOfBar;
                        barRect.Height = Height - barYPos;
                        g.FillRectangle(barBrush, barRect);
                        barXPos += (WidthOfBar + DistanceBetweenBars);
                    }
                }
            }

private void DrawStepLines(Graphics g, int[] lineData, Color lineColor)
        {
            BarPositions = new List<int>();
            int lineYPos = -1;
            int barXPos = FirstBarDrawPosition;

            using (Pen linePen = new Pen(lineColor, 2.0f))
            {
                for (int i = FirstVisibleItemIndex, k = 0; i < _indexLimit; i++, k++)
                {
                    if (base.GetBarEndPosition(k) > Width)
                        return;

                    BarPositions.Add(GetTickPosition(k));

                    if (i < lineData.Length)
                        lineYPos = lineData[i];
                    else
                        continue;

                    // draw third function line
                    //lineHeight = lineData[i];

                    g.DrawLine(linePen, barXPos, lineYPos, barXPos + WidthOfBar - 1, lineYPos);

                    barXPos += (WidthOfBar + DistanceBetweenBars);
                }
            }
        }

我正在使用绘制顺序和形状,如阶梯线、线条、框架矩形(只是矩形),矩形是填充矩形。

由于对性能至关重要的应用程序,我想知道绘制这些形状的最快方法。

提前感谢您的任何建议。

【问题讨论】:

  • 你检查过标准函数太慢了吗?我认为他们应该能够提供至少大约 10fps 的体面动画。这足以满足任何人类的需求,因为无论如何人类至少需要一秒钟的时间来做出反应。更快的速度可能会使动画更流畅,但不会增加任何真正的价值——只是养眼。
  • 对于动力不足/移动设备而言,Flash 可能是您的最佳选择。
  • @Vilx-: 15ms 进入 1 秒大约 67 次。
  • @leppie - 是的,我是说这么快地重绘是没有意义的。
  • 你应该尽量找到一些优化策略,避免每次都重绘。

标签: c# compact-framework .net-cf-3.5


【解决方案1】:

您熟悉双缓冲吗?保留一个屏幕外图像缓冲区以在更改进入时进行写入。然后覆盖 OnPaint 以在一个语句中对整个图像进行 blit。此外,使用无操作覆盖 OnPaintBackground 以摆脱在每次绘制时将控件清除为其背景色的默认行为。


像山一样古老,但here 是一篇关于在 Compact Framework 中使用 GDI 的最佳实践的文章。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 2013-12-18
    相关资源
    最近更新 更多