Работаю по-своему arround repaint () в Java - PullRequest
1 голос
/ 01 августа 2011

Я планирую написать простой космический шутер.Я прочитал, что метод repaint () является только запросом, и он не выполняется каждый раз, когда он вызывается.Я полагаю, что замечаю эффекты этого, поскольку мой космический корабль имеет тенденцию немного отставать, когда я перемещаю это.В настоящее время я просто рисую свой корабль в методе JPCanel paintComponent () и продолжаю вызывать repaint () через регулярные промежутки времени (моя панель также Runnable).Видя, что repaint () потенциально может меня испортить, я пытаюсь найти способ обойти это, однако у меня закончились идеи.Код, который у меня пока есть:

private void renderGraphics() {
    if (MyImage == null) {
        MyImage = new BufferedImage(getPreferredSize().width,
                getPreferredSize().height, BufferedImage.TYPE_INT_RGB);
    }
    MyGraphics = MyImage.getGraphics();
    MyGraphics.setColor(Color.BLACK);
    MyGraphics.fillRect(0, 0, getPreferredSize().width, getPreferredSize().height);
    MyGraphics.drawImage(ship.getImage(), ship.getCurrentX(), ship.getCurrentY(), null);       
}

Идея заключалась в том, чтобы создать собственную графику, а затем заставить ее рисовать JPanel и продолжать вызывать ее вместо repaint () в моем методе run (), однакоЯ понятия не имею, как это сделать.Я бы оценил любой вклад по этому вопросу.

Ответы [ 6 ]

4 голосов
/ 01 августа 2011

Есть несколько способов подойти к этому.

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

Вы можете сделать еще один шаг и полностью отказаться от Swing, просто используя Frame / BufferStrategy. В моем вопросе есть полностью рабочий пример (из которого был взят и адаптирован фрагмент кода):

Пользовательский рендеринг AWT - захват плавного изменения размера и устранение мерцания изменения размера

В любом случае, вот реализация BufferStrategy, которую вы можете просто вставить:

// you should be extending JFrame
public void addNotify() {
    super.addNotify();
    createBufferStrategy(2);
}

private synchronized void render() {
    BufferStrategy strategy = getBufferStrategy();
    if (strategy==null) return;
    sizeChanged = false;
    // Render single frame
    do {
        // The following loop ensures that the contents of the drawing buffer
        // are consistent in case the underlying surface was recreated
        do {
            MyGraphics draw = strategy.getDrawGraphics();
            draw.setColor(Color.BLACK);
            draw.fillRect(0, 0, getPreferredSize().width, getPreferredSize().height);
            draw.drawImage(ship.getImage(), ship.getCurrentX(), ship.getCurrentY(), null);
            draw.dispose();

            // Repeat the rendering if the drawing buffer contents 
            // were restored
        } while (strategy.contentsRestored());

        // Display the buffer
        strategy.show();

        // Repeat the rendering if the drawing buffer was lost
    } while (strategy.contentsLost());
}
2 голосов
/ 01 августа 2011

Вызов перерисовки без каких-либо аргументов означает, что вся панель перерисовывается.

Если вам нужно перекрасить части экрана (космический корабль переместился в другое место), вы должны убедиться, что только эти частиэкран перекрашен.Области, которые остаются неизменными, не должны быть затронуты.

Перекраска принимает координаты прямоугольника, который должен быть перекрашен.При перемещении корабля вы должны знать старые координаты корабля и координаты, по которым он должен двигаться.

repaint( oldShipCoordinateX, oldShipCoordinateY, shipWidth, shipLength );
repaint( newShipCoordinateX, newShipCoordinateY, shipWidth, shipLength );

Это обычно намного быстрее, чем вызывать repaint () без аргументов.Однако у вас есть дополнительные усилия, чтобы запомнить последнюю позицию корабля и вы должны быть в состоянии вычислить новую позицию корабля.

См. Также: http://download.oracle.com/javase/tutorial/uiswing/painting/index.html - особенно шаг 3

2 голосов
/ 01 августа 2011

Только для кода, который вы публикуете здесь:

1 /, если вы хотите отобразить Image / ImageIcon , тогда лучший и самый простой способ - Использовать метки

2 /, как вы упомянули Runnable{...}.start(); Swing является простым потоком, и весь вывод в GUI должен выполняться в EDT;вам нужно взглянуть на Параллельность в Swing , в результате все выходные данные из BackGround Task(s) должны быть обернуты в invokeLater(), а если есть проблема с перфоманцией, то в invokeAndWait()

3 / если вы переключаетесь (между JComponents) / добавляете / удаляете / изменяете Layout, тогда вы должны вызывать revalidate() + repaint() как последние строки в конкретном кодовом блоке

РЕДАКТИРОВАТЬ:

грязный хак будет paintImmediately ()

2 голосов
/ 01 августа 2011

Разделите всю логику на 2 части. Статический и Динамический. (например, море и движущийся корабль. Судно меняет форму / местоположение на статическом изображении моря)

Нарисуйте статическое содержимое на изображении один раз и используйте изображение в своем paintComponent (). Назовите динамическое окрашивание деталей после статического изображения.

Используйте setClip () для ограничения областей перекраски.

2 голосов
/ 01 августа 2011

любой рисунок будет по-прежнему выполняться в Swing Thread, поэтому, независимо от того, что вы пытаетесь обойти, это не поможет.

Убедитесь, что вы не выполняете никаких длинных вычислений в потоке свинга, это может помешать выполнению перекраски, как только она должна быть выполнена

1 голос
/ 01 августа 2011

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

Он объединяет несколько запросов repaint () в одинболее эффективным.

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

Затем опубликуйте свой SSCCE, чтодемонстрирует эту проблему.Я подозреваю, что проблема в вашем коде.

Что касается принятого вами решения, взгляните на последнюю запись Чарльза: Swing / JFrame vs AWT / Frame для рендеринга вне EDT , сравнивая Swing vs AWTрешения.

...