В моем приложении мне нужно нарисовать петлю сетку из тысяч прямоугольников, а производительность рисования часто важна для визуальных эффектов. Когда я работал над приложением, как, что в Java, я перекрытая paintComponent
метод в следующим образом:Зачем рисовать тысячи прямоугольников в C# PictureBox намного медленнее, чем в Java jPanel?
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D graphics2D = (Graphics2D)g;
rectanglesGrid.draw(graphics2D);
}
rectenglesGrid
класс содержит 2D ArrayList прямоугольников по имени cellsGrid
. Код draw
метод очень похож на следующий код:
public void draw(Graphics2D graphics2D)
{
for (ArrayList<Rectangle2D.Float> cells : cellsGrid)
{
for (Rectangle2D.Float cell : cells)
{
graphics2D.setPaint(someColor);
graphics2D.draw(cell);
graphics2D.fill(cell);
}
}
}
Чтобы заставить JPanel перекрашивать, я создал свой собственный TimerTask
класс и в run
вызове метода jPanel.repaint()
а. Рисование прямоугольников в Java таким образом выполняется быстро.
Теперь я пытаюсь написать подобное приложение на C#. Чтобы нарисовать прямоугольник, я создал следующий EventHandler:
private void cellsGrid_pb_Paint(object sender, PaintEventArgs e)
{
rectanglesGrid.Draw(e.Graphics);
}
Снова rectanglesGrid
класс содержит 2D массив прямоугольников и рисовать метод похож на Java одно:
foreach(Rectangle[] cells in cellsGrid)
foreach(Rectangle cell in cells)
{
pen.Color = brush.Color = someColor;
graphics.DrawRectangle(pen, cell);
graphics.FillRectangle(brush, cell);
}
Чтобы заставить PictureBox перерисовки я использую Timer
и в вызове обработчика события Tick
pictureBox.Refresh()
. Рисование прямоугольников в C# таким образом намного медленнее, чем в Java.
Интересно, почему? Я не думаю, что это просто потому, что «приложения Java работают быстрее, чем C#» ... Мой код на C# действительно похож на Java, я даже использую эквивалентные инструменты для рисования. Как повысить производительность рисования в приложении форм Windows C#?
Я попытался установить DoubleBuffered
свойство формы в true, если это имеет значение.
EDIT - лучшее описание моей проблемы
I'w работает над проектом, который визуализирует cellular automaton. Это означает, что на самом деле у меня нет 2D сетки прямоугольников, а 2D сетка ячеек. Я сохраняю эти ячейки в 2D-массиве (или ArrayList в Java). Эта сетка ячеек содержится в классе, например 'CellularAutomaton
'. Ячейки представляют собой структуры, состоящие из State
(enum), Rectangle
, статические поля с структурой и методом Color
, который возвращает правильное значение Color
в соответствии с состоянием ячейки. Ячейки меняют свое состояние на следующих временных шагах в методе NextStep()
в пределах класса CellularAutomaton
. CellularAutomaton
класс также содержит Draw()
способ, который принимает Graphics
пример как параметр.Вот точный код этого метода в C#:
public void Draw(Graphics graphics)
{
foreach(Cell[] cells in cellsGrid)
foreach(Cell cell in cells)
{
pen.Color = brush.Color = cell.Color;
Rectangle rectangle = cell.Rectangle;
graphics.DrawRectangle(pen, rectangle);
graphics.FillRectangle(brush, rectangle);
}
}
Java:
public void draw(Graphics2D graphics2D)
{
for (ArrayList<Cell> cells : cellsGrid)
{
for (Cell cell : cells)
{
graphics2D.setPaint(cell.getColor());
graphics2D.draw(cell.getRectangle());
graphics2D.fill(cell.getRectangle());
}
}
}
В C# в обработчике события клеща таймер я зову:
pictureBox.Refresh();
cellularAutomaton.NextStep();
В Java в методе run
от TimerTask
, класс I:
jPanel.repaint();
cellularAutomaton.nextStep();
PictureBox
/jPanel
Перекраска вызывает перетаскивание сетки ячеек (поскольку я переопределял метод paintComponent в Java и написал обработчик событий для события рисования на C#, как я писал ранее).
Примеры параметров, для которых Java-код работает намного быстрее: 15k 5x5 прямоугольников и 1 миллисекундный интервал между каждой перекраской и CellularAutomaton
.
Реализации метода NextStep()
очень похожи на C# и Java, поэтому я предполагаю, что замедление в C# вызвано рисованием (конечно, этот рисунок вызывает замедление, я буду измерять его позже).
UPDATE
Я измерил, что NextStep()
работает немного быстрее в C#. Однако чертеж 200 раз 10k 5x5 прямоугольников из 2D-массива Cell
в CellularAutomaton
класс в C# занимает около 1,8 секунды, а в Java занимает около 300 миллисекунд. Так, как я думал, проблема в том, что рисование на C# намного медленнее.
Двойной буфер должен быть установлен как true для элемента управления, на который вы рисуете, но для pictureBox по умолчанию установлено значение true. Вы хотите, чтобы процесс рисования был видимым? Btw: GDI + является __really old__ по сравнению с тем, что работает внутри Java, поэтому я не удивлюсь, если он будет медленнее. – TaW
Наследовать от 'Control'. Включите 'UserPaint',' AllPaintingInWmPaint', 'OptimizedDoubleBuffer' в конструкторе. Переопределите 'OnPaint' и поместите туда логику рисования. –
@TaW Нет, я не хочу, чтобы процесс рисования был видимым. Я хочу показать окончательный результат рисования всех прямоугольников за один раз. – Darko