0

为了实现这种类型的交互式艺术品,您可以在其中拖动框并在它们之间绘制连接线,我正在使用下面的代码。

在此处输入图像描述

基本上,当鼠标被拖动(移动框)或通过单击新框在面板上进行新选择时,我清除面板,绘制所有矩形,所有文本,然后使用计时器绘制所有线连接(大约每秒 20 次)。然而,重新绘制面板组件似乎很慢,并且会产生非常烦人的闪烁效果。有没有办法优化这段代码?/ 让绘图更有效率?

    public MainForm()
    {
        // Create surface and pen to use for all drawing
        surface = NodesPanel.CreateGraphics();
        surface.InterpolationMode = InterpolationMode.Default;
        surface.SmoothingMode = SmoothingMode.Default;

        penl = new Pen(Color.Blue, 2.0f);
        ....

        timer.Tick += new EventHandler(timer_Tick);
        timer.Interval = 60;              // Timer call
        timer.Enabled = true;                       // Enable the timer
        timer.Start();
     }





    void timer_Tick(object sender, EventArgs e)
    {
        if (refreshScreen) // when dragging a box of making a new selection
        {
            RenderScreen();
        }
    }



    public void RenderScreen()
    {
        surface.Clear(Color.White);

        drawUnselectedNodes();

        if (showSearchGate)
        {
            drawGates();
        }

        if (currentlyClickedNode != null && !(currentlyClickedNode is Gate))
        {
            currentlyClickedNode.drawMyConnections(surface, penl); // Draw in a different colour
            currentlyClickedNode.drawMe(surface, penl);

            if (drawingLine)
            {
                DrawingHelper.DrawLine(surface, penl, currentlyClickedNode.getGatePosition(), linePosition, "regular");
            }
        }
    }



    private void drawUnselectedNodes()
    {
        foreach (QuestNode q in nodes)
        {
            if (q != currentlyClickedNode)
            {
                q.drawMe(surface, penl);
            }
        }

    }



 // The node structure
public class QuestNode
{
    ...
    public void drawMe(Graphics g, Pen p)
    {
        DrawingHelper.DrawRoundRectWithText
             (g, p, pos.x, pos.y, NODE_WIDTH * currentScale, NODE_HEIGHT *
                  currentScale, GATE_RADIUS * currentScale, name, description, true,
                       (selected ? RECTANGLE_SELECTED_COLOR : ANGLE_UNSELECTED_COLOR));
    }

    public void drawMyConnections(Graphics g, Pen p) 
    {
        foreach (QuestNode qn in relatedQuests)
        {
            DrawingHelper.DrawLine(g, p, pos, qn.getGatePosition(), "regular");
        }
    }
 }




static class DrawingHelper
{
    public static SolidBrush STANDARD_BRUSH = new SolidBrush(RECTANGLE_COLOR);
    public static int PRIMARY_TEXT_FONT_SIZE = 10;
    public static Font PRIMARY_FONT_STYLE = new Font("Arial", PRIMARY_TEXT_FONT_SIZE);
    public static int SECONDARY_TEXT_FONT_SIZE = 8;
    public static Font SECONDARY_FONT_STYLE = new Font("Arial", SECONDARY_TEXT_FONT_SIZE);


     public static void DrawRoundRectWithText(Graphics g, Pen p, float x, float y,
             float width, float height, float gateRadius, string textFirstLike, 
                 string textSecondsLine, bool hasGate, Color color)
    {
        Graphics formGraphics = g;
        g.InterpolationMode = InterpolationMode.Default;
        g.SmoothingMode = SmoothingMode.Default;

        SolidBrush myBrush = STANDARD_BRUSH;
        myBrush.Color = color;

        p.DashPattern = new float[] { 1 };
        Rectangle rect = new Rectangle((int)x, (int)y, (int)width, (int)height);
        p.Width = RECTANGLE_BORDER;

        formGraphics.FillRectangle(myBrush, rect);
        p.Color = RECTANGLE_COLOR;
        formGraphics.DrawRectangle(p, rect);


        DrawString(g, textFirstLike, x + TEXT_OFFSET_X, y + height / 4, PRIMARY_TEXT_FONT_SIZE, (int)width);
        DrawString(g, textSecondsLine, x + TEXT_OFFSET_X, y + height / 2, SECONDARY_TEXT_FONT_SIZE, (int)width);

        int gateWidth = (int)gateRadius;
        int gateHeight = (int)gateRadius;

        if (hasGate)
        {

            myBrush.Color = GATE_COLOR;
            Rectangle circle = new Rectangle((int)(x + width) - gateWidth/2, (int)(y + height) - gateHeight/2, gateWidth, gateHeight);

            formGraphics.FillEllipse(myBrush, circle);
            formGraphics.DrawEllipse(p, circle);

        }

        Point[] diamondPoints = new Point[4];
        diamondPoints[0] = new Point((int)(x - gateWidth / 2), (int)y);
        diamondPoints[1] = new Point((int)x, (int)(y - gateHeight / 2));
        diamondPoints[2] = new Point((int)(x + gateWidth / 2), (int)y);
        diamondPoints[3] = new Point((int)x, (int)(y + gateHeight / 2));

        myBrush.Color = Color.LightGray;
        formGraphics.FillPolygon(myBrush, diamondPoints);
        formGraphics.DrawPolygon(p, diamondPoints);
    }
  }

    public static void DrawLine(Graphics g, Pen p, Vector2D origin, Vector2D end, string style)
    {
        Pen myPen = p;
        p.Color = Color.Black;

        Graphics formGraphics = g;

        g.InterpolationMode = InterpolationMode.Default;
        g.SmoothingMode = SmoothingMode.Default;

        myPen.Width = LINE_BORDER;
        if (style == "dotted")
        {
            myPen.DashPattern = new float[] { 1, 1, 0.5f };
        }

        formGraphics.DrawLine(myPen, origin.x, origin.y, end.x, end.y);

    }

    private static void DrawString(Graphics g, string text, float posX, float posY, int fontSize, int stringMaxWidth)
    {

        string drawString = text;
        Font drawFont = (fontSize == PRIMARY_TEXT_FONT_SIZE) ? PRIMARY_FONT_STYLE : SECONDARY_FONT_STYLE;
        SolidBrush drawBrush = STANDARD_BRUSH;
        drawBrush.Color = Color.Black;

        float x = posX;
        float y = posY;

        float charHeight = drawFont.GetHeight() / 2;
        int maxChars = (int)(stringMaxWidth / charHeight);

        if (drawString.Length > (maxChars - 3))
        {
            drawString = drawString.Substring(0, maxChars - 3) + "...";
        }

        g.DrawString(drawString, drawFont, drawBrush, x, y);
    }
4

0 回答 0