Как убрать мерцание с двойной буферизацией (java swing)

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

В настоящее время у меня есть класс JFrame с прослушивателем действий

JButton northWest = new JButton("↖");
    northWest.setPreferredSize(new Dimension(60, 60));
    moveBorder.add(northWest);
    northWest.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            MainBoardJPanel mainBoardPanel = new MainBoardJPanel();
            mainBoardPanel.movePlayer(painel.getGraphics(), -40, -40, playerInfo, currentPlayer.getUsername());
            performMove();
        }
    });

При нажатии кнопки метод movePlayer (внутри класса MainBoardJPanel) рисует фон, значок игрока в новом месте и, наконец, еще один слой, который действует как туман войны.

public void movePlayer(Graphics g, int x, int y, PlayerInformation[] playerInfo, String username) {
    super.paint(g);

    Graphics2D g2d = (Graphics2D) g;
    try {
        background = ImageIO.read(new File("Images\\BackgroundBoard.png"));
        playerIcon1 = ImageIO.read(new File("Images\\PlayerIcon1.png"));
        fogOfWar = ImageIO.read(new File("Images\\FogOfWar.png"));

    } catch (Exception e) {
        e.printStackTrace();
    }
    g.drawImage(background, 0, 0, this);
    g.drawImage(playerIcon1, playerInfo[0].getPosX(), playerInfo[0].getPosY(), null);
    int xFOW = x - 775;
    int yFOW = y - 775;
    g.drawImage(fogOfWar, xFOW, yFOW, this);
    updateUserInfo(x, y, username);
    setDoubleBuffered(true);
    Toolkit.getDefaultToolkit().sync();
    g.dispose();
}

(Это очень упрощенная версия, чтобы сократить нерелевантный код)

Поскольку каждое изображение рисуется последовательно, изображение продолжает мигать всякий раз, когда вызывается метод, как бы мне сделать двойную буферизацию?

1) Для более быстрой помощи опубликуйте минимальный воспроизводимый пример или Краткий, автономный, правильный пример. 2) Один из способов получить изображение (я) для примера - установить горячую ссылку на изображения в этот вопрос и ответ.

Andrew Thompson 06.06.2018 03:11
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
1
306
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

but I'm struggling to understand how to properly double buffer in order to remove flickering

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

Вызов super.paint в movePlayer является неуместным злоупотреблением системой рисования.

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

Swing использует алгоритм пассивного рендеринга, это означает, что он будет планировать рисование, когда когда-либо решит, что это необходимо сделать. У вас нет контроля над этим, лучшее, что вы можете сделать, - это дать системе «подсказки», что вы хотели бы перерисовать компонент или какую-то часть компонента (например, repaint). Подсистема покраски затем решит, когда и что нужно красить. Вашим компонентам будет предложено выполнить операцию рисования с помощью их методов рисования.

Когда это сделано таким образом, Swing будет удваивать буферизацию операции рисования, поэтому все окрашенные компоненты буферизуются, и когда проход рисования завершен, изображение обновляется на экране.

Я очень рекомендую прочитать:

для получения более подробной информации о том, как работает система рисования в Swing и как вы должны с ней работать

В качестве побочного примечания я бы также избегал загрузки ресурсов (или выполнения каких-либо трудоемких задач) в любых функциях рисования. Покраска должна идти как можно быстрее

Большое спасибо, что многое проясняет, я внимательно прочитаю ссылки, данные спасибо!

tragicProgrammer 06.06.2018 03:19

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