ボックスをドラッグしてそれらの間に接続線を引くことができるこのタイプのインタラクティブなアートワークを実現するために、以下のコードを使用しています。
基本的に、(ボックスを移動するために) マウスがドラッグされているとき、または新しいボックスをクリックしてパネル上で新しい選択が行われているときは、パネルをクリアし、すべての四角形、すべてのテキスト、およびタイマーを使用してすべての線の接続を描画します ( 1秒間に約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);
}