gpt4 book ai didi

java - 让 JLabel 跨 JPanel 移动

转载 作者:行者123 更新时间:2023-11-29 04:21:17 24 4
gpt4 key购买 nike

我试图让我的游戏中的一个桶自己向下漂浮到屏幕上,我已经尝试了一些东西并查阅了一些教程,但我似乎无法让它工作。也许我试图通过在 paintcomponent() 中执行此操作以错误的方式处理此问题?在我的 JPanel 中,我还有一个汽车对象,它是 KeyListeners 控制的 JPanel 的扩展。

// this is inside a JPanel class that I made that's painting out the game


OilBarrel barrel = new OilBarrel();


@Override
public void paintComponent(Graphics g) {

super.paintComponent(g);
road.paintComponent(g);

this.add(car);
this.add(barrel);

barrel.setBounds(barrelX, barrel.getBarrelY(), 150, 180);
int carX = car.getCarX();

car.setBounds(carX, carY, 800, 400);
barrel.setBounds(550, barrel.getBarrelY(), 800, 400);
while (true) {
barrel.move();
repaint();
try {
Thread.sleep(1);

} catch (Exception e) {
}
}

}



// this is the oilbarrel class

import java.awt.Dimension;
import java.awt.Image;

import javax.swing.ImageIcon;
import javax.swing.JLabel;


public class OilBarrel extends JLabel{

int barrelX;
int barrelY = 0;

public OilBarrel() {

setVisible(true);
this.setFocusable(true);
Image img = new ImageIcon(this.getClass().getResource("/oil.png")).getImage();


this.setIcon(new ImageIcon(img));


}



public void move(){

if(barrelY<1000)
barrelY +=1;

}



public int getBarrelY() {
return barrelY;
}

}

最佳答案

Swing 是单线程的,这意味着您在 paintComponent 方法中的 for-loop 阻塞了事件调度线程,阻止它更新 UI。

参见 Concurrency in Swing了解更多详情

解决该问题的最简单方法是使用 Swing Timer ,因为它允许在 EDT 之外安排一个小的延迟,但这会触发它在 EDT 上的更新,从而可以安全地从内部更新 UI。

组件动画并不难,但它确实需要不同的工作流程,例如:

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

public static void main(String[] args) {
new Test();
}

public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class TestPane extends JPanel {

private JLabel label;
private int xDelta = 1;

public TestPane() {
setLayout(null);
label = new JLabel("*");
label.setSize(label.getPreferredSize());
label.setLocation(0, (200 - label.getHeight()) / 2);
add(label);
Timer timer = new Timer(10, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int x = label.getX();
x += xDelta;
if (x + label.getWidth() > getWidth()) {
x = getWidth() - label.getWidth();
xDelta *= -1;
} else if (x < 0) {
x = 0;
xDelta *= -1;
}
label.setLocation(x, label.getY());
}
});
timer.start();
}

@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}

}

}

作为个人喜好,我会避免在这项工作中使用组件,而倾向于使用完整的自定义绘画路线。

这有很多原因,组件是复杂的对象,需要非常注意细节。也很难对它们应用额外的效果或转换

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

public static void main(String[] args) {
new Test();
}

public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class TestPane extends JPanel {

private Rectangle box;
private int xDelta = 1;

public TestPane() {
setLayout(null);
box = new Rectangle(0, 75, 50, 50);
Timer timer = new Timer(10, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int x = box.x;
x += xDelta;
if (x + box.width > getWidth()) {
x = getWidth() - box.width;
xDelta *= -1;
} else if (x < 0) {
x = 0;
xDelta *= -1;
}
box.setLocation(x, box.y);
repaint();
}
});
timer.start();
}

@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.draw(box);
g2d.dispose();
}

}

}

关于java - 让 JLabel 跨 JPanel 移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48994496/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com