Java 我试图在applet中使用线程移动球,但它不移动
我试图用线程在小程序中移动球,但它不移动。有人能帮我吗?我是小程序新手,正在进行游戏开发。这里是我的代码供参考Java 我试图在applet中使用线程移动球,但它不移动,java,multithreading,swing,awt,event-dispatch-thread,Java,Multithreading,Swing,Awt,Event Dispatch Thread,我试图用线程在小程序中移动球,但它不移动。有人能帮我吗?我是小程序新手,正在进行游戏开发。这里是我的代码供参考 public class ballGame extends JApplet implements Runnable { int x_pos=50; int y_pos=100; int rad=10; Thread t; public void start() { super.start(); t=ne
public class ballGame extends JApplet implements Runnable
{
int x_pos=50;
int y_pos=100;
int rad=10;
Thread t;
public void start()
{
super.start();
t=new Thread("t");
t.start();
}
public void paint(Graphics g)
{
super.paint(g);
g.setColor(Color.red);
setBackground(Color.BLACK);
g.drawOval(x_pos,y_pos,2*rad,2*rad);
while(true)
{
x_pos++;
//validate();
repaint();
try
{
Thread.sleep(100);
}
catch(Exception e)
{
e.printStackTrace();
}
}//end of while
}//end of paint()
}
无法在paint()内调用repaint()方法。而且您不能在paint()方法中组织无限循环-这样做,您将阻止小程序中的绘图。在
paint
中有无限循环意味着该方法的任何一个过程都无法完成
另外,在paint
方法中,永远不要调用Thread.sleep(100)
。这会阻止EDT,并降低性能
相反,请使用来执行更新和重新绘制工作。此外,我将子类a
JComponent
并重写paintComponent
在Runnable的run方法中使用while循环
更新:
在start方法中使用此选项
t=new Thread(this);
t.start();
x_pos
是一个int值,因此它是通过值传递给方法的,而不是通过引用。这就是为什么,当您更改其值时,圆内的值不会更新…您创建的线程没有run()
方法。此方法应包含可运行的代码。。。此外,paint()
方法是绘制内容,而不是更新内容
因此,将while循环从paint()
方法移动到线程的run()
方法:
t=new Thread("t") {
@Override
public void run()
{
while(true)
{
x_pos++;
//validate();
repaint();
try
{
Thread.sleep(100);
}
catch(Exception e)
{
e.printStackTrace();
}
}//end of while
}
};
请注意,
ballGame
不需要implementrunnable
部分。因为您创建的线程将提供它。Swing是一个单线程环境。也就是说,所有更新和交互都在单个线程中执行。Swing也是线程安全的。这意味着对UI的所有更新必须在该线程(事件调度线程或ETD)的上下文中执行
任何阻止EDT的代码都会阻止它(除其他外)重新绘制UI并响应用户的输入
您担心paint code永远不会更新屏幕,事实上它会使您的应用程序看起来“挂起”,因为paint
方法不允许完成,并且正在阻止ETD
调用paint
方法后会快速返回,并且可能会连续快速重复调用,这是一个例外
一般来说,线程
可能有点杀伤力过大,类似于javax.swing.Timer的线程在这些情况下更合适
public class AnimatedBoat {
public static void main(String[] args) {
new AnimatedBoat();
}
public AnimatedBoat() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new AnimationPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class AnimationPane extends JPanel {
private BufferedImage boat;
private int xPos = 0;
private int direction = 1;
public AnimationPane() {
try {
boat = ImageIO.read(new File("boat.png"));
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
xPos += direction;
if (xPos + boat.getWidth() > getWidth()) {
xPos = getWidth() - boat.getWidth();
direction *= -1;
} else if (xPos < 0) {
xPos = 0;
direction *= -1;
}
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public Dimension getPreferredSize() {
return boat == null ? super.getPreferredSize() : new Dimension(boat.getWidth() * 4, boat.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int y = getHeight() - boat.getHeight();
g.drawImage(boat, xPos, y, this);
}
}
}
公共类动画船{
公共静态void main(字符串[]args){
新的动画船();
}
公共救生艇(){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
}
JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(新的BorderLayout());
frame.add(新的AnimationPane());
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
}
});
}
公共类AnimationPane扩展了JPanel{
私人缓冲成像船;
私有int xPos=0;
私有int方向=1;
公共动画窗格(){
试一试{
boat=ImageIO.read(新文件(“boat.png”);
计时器计时器=新计时器(40,新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
xPos+=方向;
如果(xPos+boat.getWidth()>getWidth()){
xPos=getWidth()-boat.getWidth();
方向*=-1;
}否则如果(xPos<0){
xPos=0;
方向*=-1;
}
重新油漆();
}
});
timer.setRepeats(真);
timer.setCoalesce(真);
timer.start();
}捕获(IOEX异常){
例如printStackTrace();
}
}
@凌驾
公共维度getPreferredSize(){
返回boat==null?super.getPreferredSize():新维度(boat.getWidth()*4,boat.getHeight());
}
@凌驾
受保护组件(图形g){
超级组件(g);
int y=getHeight()-boat.getHeight();
g、 drawImage(船、XPO、y、此);
}
}
}
作为旁注。您应该很少需要重写顶级容器(如JApplet
或JFrame
)的paint
方法,尽管有很多很好的理由,但您最感兴趣的是它们不是双缓冲,这意味着当屏幕更新时,您可能会看到闪烁
最好使用类似于JPanel
的方法,并替代它的paintComponent
方法
看看
更多信息
铌
虽然我在示例中使用了JFrame
,但将动画面板放入JApplet
,这是不需要/不想从顶级容器扩展的另一个原因;) 我试着把它放在run()里面,但球还是不动。Kay Reimeus…我会尝试使用swing定时器,谢谢。实际上我已经写了run()并且已经写了