Я создал Java-игру, в которой используется JFrame, содержащий JApplet, который, в свою очередь, содержит JPanel, на который нарисованы графики, но по какой-то причине левая часть графики иногда мигает, Подумайте, почему это так. Я полагаю, что это может быть из-за того, что я на самом деле не использовал EDT, что я понял только потом, так кто-нибудь сможет показать мне, как я правильно интегрирую использование EDT в программу?Правильно использовать Event Dispatch Thread в JApplet?
Мой главный класс выглядит следующим образом:
public class Main extends JFrame{
public static final int HEIGHT = 600;
public static final int WIDTH = 800;
public static RApplet app;
public Main(){
setTitle("RCrawl");
Container c = getContentPane();
c.setPreferredSize(new Dimension(WIDTH, HEIGHT));
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setResizable(false);
final Player p = new Player(50, 70, true);
final Room r = new Room(0xff222244);
r.addEntity(new EntityRock(200, 150));
app = new RApplet(WIDTH, HEIGHT);
app.setRoom(r);
app.setPlayer(p);
app.setFps(25);
add(app);
setVisible(true);
new UpdateThread().start();
System.out.println("thread run");
}
public static void main(String[] args){
Main m = new Main();
}
class UpdateThread extends Thread{
public void run(){
while(true)update();
}
public void update(){
app.refresh();
}
}
}
Хотя класс RApplet выглядит следующим образом:
public class RApplet extends JApplet{
public int width, height, fps;
public long curTime, delta;
public RenderPanel panel;
public Room curRoom;
public Player player;
public boolean isSingle;
public InputHandler input;
public RApplet(int x, int y){
width = x;
height = y;
panel = new RenderPanel(width, height);
fps = 30;
isSingle = true;
input = new InputHandler();
addKeyListener(input);
setFocusable(true);
add(panel);
}
public void setPlayer(Player p){
player = p;
curRoom.addPlayer(p);
}
public void setFps(int f){
fps = f;
}
public void initialize(){
curTime = System.currentTimeMillis();
delta = curTime;
}
public void refresh(){
delta = (int)(System.currentTimeMillis() - curTime);
if(delta > 1000/fps){
curTime = System.currentTimeMillis();
render();
tick();
}
}
public void setRoom(Room r){
curRoom = r;
}
public void render(){
panel.renderStart(curRoom);
panel.renderRoom(curRoom);
panel.renderEnd();
panel.repaint();
}
public void tick(){
curRoom.tick(this);
}
}
Так что я хотел бы сделать для того, чтобы использовать EDT правильно? Я пробовал несколько вещей, используя разные комбинации invokeLater()
и invokeAndWait()
, но не смог заставить их работать. Если вы можете помочь, любая помощь будет оценена.
EDIT: Вот метод визуализации от RenderPanel
:
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
BufferedImage drawer = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g1 = drawer.getGraphics();
g1.drawImage(canvas, 0, 0, this);
g2.drawImage(drawer, 0, 0, this);
g1.dispose();
g2.dispose();
}
не было бы двойной буферизации?
'', который использует JFrame, содержащий JApplet «' - почему этот * очень странный и хрупкий дизайн? Разве это не JFrame, который имеет JPanel? –
Я использую JFrame, чтобы проверить его, прежде чем перемещать апплет на веб-страницу. – user2649681
1. Не выполняйте рисунок BufferedImage в методе paintComponent, то есть все, начиная с 'BufferedImage drawer = ....' до 'g1.drawImage (...)'. Это должно быть сделано в другом месте, возможно, в фоновом потоке. Кроме того, несмотря на то, что для объекта Graphics Graphics BufferImage отлично, g1, когда вы закончите с ним, никогда не удаляйте объект Graphics, предоставленный вам JVM, а именно объект g2. Это сломает дерево живописи Свинг. –