Java Swing отображает несоответствия и мерцаетJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Java Swing отображает несоответствия и мерцает

Сообщение Anonymous »

Я пытаюсь ознакомиться с созданием графических интерфейсов на Java и написал программу, которая должна перемещать квадрат на экране в зависимости от нажатия клавиши WASD (следуя онлайн-руководству).
Однако при запуске кажется, что квадрат мерцает и «запаздывает», иногда рендеринг плавный, но в большинстве случаев нет.
Вот мой класс JPanel, в котором находится основное содержимое. бывает :

Код: Выделить всё

package me.analyzers.scs.game;

import me.analyzers.scs.utilities.KeyPressHandler;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class MainPanel extends JPanel implements Runnable{
final int FPS = 240;
final int tileSize = 16;
final int scaling = 3;
final int realTileSize = tileSize * scaling;
final int widthX = 16;
final int widthY = 12;
final int screenWidth = realTileSize * widthX;
final int screenHeight = realTileSize * widthY;

Thread mainLoop;
KeyPressHandler keyPressHandler = new KeyPressHandler();

public MainPanel() {
super();
this.setPreferredSize(new Dimension(screenWidth, screenHeight));
this.setBackground(Color.WHITE);
this.addKeyListener(keyPressHandler);
this.setFocusable(true);
}

public void startGameLoop() {
mainLoop = new Thread(this);
mainLoop.start();
}

public boolean isRunning() {
return mainLoop != null;
}

int posX = 0;
int posY = 0;

@Override
public void run() {
long lastTime = 0;
while(isRunning()) {
long currentTime = System.currentTimeMillis();
if(currentTime-lastTime > 1000/FPS) {
lastTime = System.currentTimeMillis();
tick();
repaint();
}
}
}

public void tick() {
switch (keyPressHandler.getLastKey()) {
case 'w' -> posY-=1;
case 's' -> posY+=1;
case 'a' -> posX-=1;
case 'd' -> posX+=1;
}
}

@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLACK);
g2d.fillRect(posX, posY, realTileSize, realTileSize);
g2d.dispose();
}
}

Сначала я подумал, что это может быть вызвано проблемами параллелизма, и поэтому я часто менял код «основного цикла»; Я попробовал выполнить его условно, проверив currentTime() с помощью LastTime, попробовал выполнить Thread.sleep, а также попробовал использовать класс Timer Swing. Все они дают один и тот же результат.
Интересно отметить, что если я вызову repaint() внутри метода PaintComponent() (думаю, вызывая цикл), он будет работать нормально ; но это вызывает PaintComponent() сотни раз за игровой цикл.
После поиска в сети подобных проблем и неспособности их исправить я попытался запустить тот же jar-архив в Windows виртуальная машина. Удивительно, но все рендерится плавно! Также кажется, что на компьютере с Windows квадрат движется намного медленнее, чем на моем. Это меня очень смущает, потому что я думал, что JVM должна быть единообразной на всех платформах.
РЕДАКТИРОВАТЬ: я понял, что постоянные входные данные (включая спам-нажатия на окно ) временно остановить странное заикание. Это заставляет меня задаться вопросом, не вызвано ли это каким-то процессом, пытающимся «экономить время процессора» в моем графическом интерфейсе? Существует ли это?
EDIT 2: Toolkit.sync() успешно решил эту проблему. Я считаю, что моя оконная система работает из-за «буферизации графических событий» (что объясняет постоянный ввод, останавливающий заикание).

Подробнее здесь: https://stackoverflow.com/questions/786 ... flickering
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»