PaintComponent Java Slow

Я разрабатывал на своем Mac приложения JAVA. Логика такова:

  1. Сервер отправляет клиентскому приложению несколько заказов на рисование основных фигур.
  2. Клиентские приложения рисуют основные фигуры в Jpanel

Каждый раз, когда приходит форма, программа вызывает repaint()

 public void paintShape(Shape p) 
{
    //this.paintComponent(this.getGraphics());
   arrayofShapes.add(p);
   this.repaint();
    //this.updateUI();
    //this.update(this.getGraphics());

}
public void paintComponent(Graphics g) 
{ 
    super.paintComponent(g);
    g2d = (Graphics2D) g.create();
    g2d.setStroke(new BasicStroke(2));
    g2d.setColor(pickedColor);
    for(final Shape p : arrayofShapes)
    {
        g2d.draw(p);
    }
    //g2d.dispose();

}

Все работает плавно (в режиме реального времени), поэтому я решил протестировать то же приложение на компьютере с Windows. Результат - медленное приложение. К такому выводу я пришел.

  • RepaintManager накапливает вызовы repaint(). Я вижу, как формы прибывают в пункт назначения, но в некоторых случаях более 5 вызовов перерисовки накапливаются в одном, что делает приложение очень запаздывающим / не в реальном времени.

Я попытался вместо вызова repaint каждый раз, когда фигура поступает, чтобы делать это с таймером каждые несколько миллисекунд, результат тот же. Код:

ActionListener listener = new ActionListener(){
          public void actionPerformed(ActionEvent event){
            repaint();
          }
        };

Timer displayTimer = new Timer(5, listener);
displayTimer.start();

Кроме того, я протестировал некоторый случайный код, который позволяет рисовать с помощью мыши, та же логика, что и у меня с paintComponent. В этом случае он работает без сбоев.... Пример: http://javagraphics.blogspot.com.es/2010/06/shapes-implementing-freehand-pencil.html

Я не понимаю, почему paintComponent так медленно на моем компьютере с Windows (тот же Jar). Что может повлиять на производительность моей программы?

Я прочитал все ответы, касающиеся компонентов краски, но любой из них решил эту проблему.

Любой совет, как я могу решить проблему и на самом деле архивировать в реальном времени?

заранее спасибо

Обновить видео:

Видео Mac: https://youtu.be/OhNXdGXoQpk режиме реального времени без проблем справляется с большой нагрузкой

Видео Windows https://youtu.be/yol2miHudZc явно лагает

Извиняюсь за низкое качество

Обновление BufferedImage:

После введения BufferedImage результат все еще остается медленным приложением рисования. Это создает еще одну проблему, так как один из порядков заключается в удалении всех фигур, это добавляет некоторую сложность, так как я должен сделать:

 g2d.clearRect(0, 0, screenSize.width, screenSize.height);

HW / OS / JavaVersion

Windows

  • Процессор i5-4300u 2.5ghz
  • Ram 12 ГБ
  • Java версия 1.7.0_71

MAC

  • Процессор i7 2.9ghz
  • Ram 8 ГБ
  • Java версия 1.7.0_67

Java VisualVM

Видео с живого VisualVM: https://youtu.be/cRNX4b3rlZk

Я не вижу ничего странного, что могло бы объяснить причину задержки, но я далеко не эксперт (опять же извините за низкое качество)

Спасибо за все ваши ответы

3 ответа

Там нет необходимости create() каждый раз новый графический контекст; просто бросил g в Graphics2D, Это безопасно для всех конкретных реализаций. Это также устраняет необходимость dispose() созданного контекста. Как отмечено здесь, сохраните любые переменные контекста, которые могут быть критически важными для последующей рисования.

public void paintComponent(Graphics g) { 
    super.paintComponent(g);
    g2d = (Graphics2D) g;
    Stroke oldStroke = g2d.getStroke();
    g2d.setStroke(new BasicStroke(2));
    g2d.setColor(pickedColor);
    for(final Shape p : arrayofShapes) {
        g2d.draw(p);
    }
    g2d.setStroke(oldStroke);
}

Кроме того, сравните профили на обеих платформах, чтобы найти различия. Для справки, приведенный здесь пример удобно обрабатывает выборки, содержащие сотни фигур на любой платформе.

Я бы порекомендовал сделать статическое рисование для BufferedImage, а затем нарисовать BufferedImage в вашем методе paintComponent.

например,

private BufferedImage bufferedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, BufferedImage.TYPE_INT_ARGB);

public void paintShape(Shape p) {
    Graphics2D g2 = bufferedImage.createGraphics();
    g2d.setStroke(MY_STROKE); // make this a constant
    g2d.setColor(pickedColor);
    g2d.draw(p);
    g2d.dispose();
    this.repaint();
}

public void paintComponent(Graphics g) { 
    super.paintComponent(g);
    if (bufferedImage != null) {
       g2.drawImage(bufferedImage, 0, 0, null);
    }
    // do dynamic drawing such as drawing of moving sprites here
}

После более двух дней отладки я обнаружил, что проблема не имеет ничего общего с paintComponent()

С тем же сервером, генерирующим случайные фигуры

В приложении Windows некоторые формы принимаются одновременно, что невозможно, поскольку я отправляю формы каждые 15 мс. Вот почему он накапливает формы (результат = отставание).

С другой стороны, в приложении Mac каждая фигура имеет разное время приема (результат = реальное время)

Спасибо за добрые ответы и извините за неудобства

Другие вопросы по тегам