【问题标题】:JFrame moving rectangle-Why isnt my rectangle moving and clearing his pathJFrame移动矩形-为什么我的矩形不移动并清除他的路径
【发布时间】:2022-06-29 12:12:24
【问题描述】:

我对在 java 中使用 JFrames 和 Graphics 很陌生。我的长期目标是创建一个 RayCast 游戏世界。以下代码是我在 jframe 中在其坐标处移动矩形的第一种方法。当用户按下箭头键时,坐标会发生变化。但是似乎有些问题,因为当我使用程序时,矩形只是被绘制并创建了一条路径。我希望在坐标位置绘制矩形。

import javax.swing.JFrame;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
import java.awt.event.ActionEvent;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JMenu;



public class Raycast_World_2 extends JFrame implements ActionListener, KeyListener, Runnable
{
    public int px,py;
    int velx = 0, vely = 0;
    Graphics f;
   
    public Raycast_World_2()
    {
        // Instanzvariable initialisieren
        px = 100;
        py = 100;
        setSize(1280,960);
        setVisible(true);
        setDefaultCloseOperation(3);
        addKeyListener(this);
         setFocusable(true);
        setFocusTraversalKeysEnabled(false);
        setTitle("Raycast_World-Try4_Version 3.0");
        JMenuBar menuBar = new JMenuBar();
JMenu menuFile = new JMenu("File");
JMenuItem menuItemExit = new JMenuItem("Exit");
menuFile.add(menuItemExit);
 
menuBar.add(menuFile);
 
// adds menu bar to the frame
setJMenuBar(menuBar);
    }
    public void actionPerformed(ActionEvent e){
        update(getGraphics());
        repaint();
    
    
}
    public void paint(java.awt.Graphics g) {
    
  g.setColor(Color.red);
  
  g.fillRect(px,py,20,20);
  g.dispose();  
  repaint();
}
public void run(){
   
    
}

    public void keyPressed(KeyEvent e){
    
    int c = e.getKeyCode();
    if(c == KeyEvent.VK_LEFT){
        
        px = px-10;
    }
    if(c == KeyEvent.VK_UP){
        
        py = py -10;
    }
    if(c == KeyEvent.VK_RIGHT){
        
        px = px +10;
    }
    if(c == KeyEvent.VK_DOWN){
        
        py = py +10;
    }
}
public void keyTyped(KeyEvent e){
}
public void keyReleased(KeyEvent e){}
}

请解释一下我做错了什么。 提前感谢您帮助我!

【问题讨论】:

  • 不得对传递给绘制方法的 Graphics 对象调用 dispose()。 Graphics 对象属于系统。除非您创建了任何 Graphics 对象,否则不要丢弃它。

标签: java swing jframe graphics2d


【解决方案1】:

很遗憾,你画的不正确。

  • 不要扩展JFrame。顶级类很少被子类化。您所需要的只是一个JFrame 的实例,您将在其中添加一个JPanel 来进行绘画。框架用于固定组件。
  • 扩展 JPanel 并将其添加到框架实例中。
  • 不要覆盖 paint(),覆盖 JPanel 子类中的 paintComponent
  • 然后调用super.paintComponent(g)调用父方法来做清除背景等事情。如果您不这样做,矩形会在您移动时留下痕迹。
  • 并且永远不要从paintComponent 中调用repaint。它将继续在 Event Dispatch Thread 中调用paintComponent,并且可能会锁定或溢出堆栈。
  • 在keylistener中,修改坐标的地方就是调用repaint的地方。

这是执行上述操作的代码的修改版本。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Raycast_World_2 extends JPanel implements KeyListener{
    public int px, py;
    int velx = 0, vely = 0;
    JFrame frame = new JFrame();
    public Raycast_World_2() {
        // Instanzvariable initialisieren
        px = 100;
        py = 100;
        // okay here but in some situations getPreferredSize() should be
        // overridden.
        setPreferredSize(new Dimension(600,500));
        setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        addKeyListener(this);
        setFocusable(true);
        setFocusTraversalKeysEnabled(false);
        frame.setTitle("Raycast_World-Try4_Version 3.0");
        frame.add(this);
        JMenuBar menuBar = new JMenuBar();
        JMenu menuFile = new JMenu("File");
        JMenuItem menuItemExit = new JMenuItem("Exit");
        menuFile.add(menuItemExit);
        menuBar.add(menuFile);
        frame.setJMenuBar(menuBar);
        frame.pack(); // size and layout components.
        frame.setLocationRelativeTo(null); // center on screen
        frame.setVisible(true);
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(()->new Raycast_World_2());
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics gg = g.create();
        gg.setColor(Color.red);
        
        gg.fillRect(px, py, 20, 20);
        gg.dispose();
    }
    }
    
    
    
    public void keyPressed(KeyEvent e) {
        
        int c = e.getKeyCode();
        if (c == KeyEvent.VK_LEFT) {
            
            px = px - 10;
        }
        if (c == KeyEvent.VK_UP) {
            
            py = py - 10;
        }
        if (c == KeyEvent.VK_RIGHT) {
            
            px = px + 10;
        }
        if (c == KeyEvent.VK_DOWN) {
            
            py = py + 10;
        }
        repaint();
    }
    
    public void keyTyped(KeyEvent e) {
    }
    
    public void keyReleased(KeyEvent e) {
    }
}

Java Tutorials 中查看how to paint

在 StackOverflow 上也有许多正确绘画的优秀示例。

这是另一个建议,但不是必需的。使用inner class 创建您的keyListener。通过继承KeyAdapter,您不必自己添加未实现的方法。 KeyAdapter 只是一个带有空方法的类。 MouseAdapter 是另一个。请注意,内部类可以访问包含类的字段。因此,您可以执行以下操作:

public class MyKeyListener extends KeyAdapter {
     public void keyPressed(KeyEvent e) {
    
    int c = e.getKeyCode();
    if (c == KeyEvent.VK_LEFT) {    
        px = px - 10;
    } else
    if (c == KeyEvent.VK_UP) {
        py = py - 10;
    } else
    if (c == KeyEvent.VK_RIGHT) {
        px = px + 10;
    } else
    if (c == KeyEvent.VK_DOWN) {
        py = py + 10;
    }
    repaint();
}

那么你可以做以下事情。

addKeyListener(new MyKeyListener());

您可能还想考虑使用教程中也介绍的Key Bindings

【讨论】:

    【解决方案2】:

    您的问题似乎是每次调用“paint”方法时都没有重置屏幕。所以发生的情况是,每次你运行这个方法时,它都会获取屏幕的先前状态,并在这个现有状态上绘制你想要的任何东西。更清楚地说,它只是使屏幕上的绘画过载。 为了解决这个问题,您需要做的就是在您的paint方法开始处添加以下代码行:

    super.paint(g);
    

    这个从超类 JFrame 调用的方法将确保之前绘制到屏幕上的所有内容都将被删除。所以在这行代码之后你的屏幕将是空的,现在只会用你在这行代码之后绘制的任何内容来绘制。

    【讨论】:

      猜你喜欢
      • 2015-04-13
      • 1970-01-01
      • 1970-01-01
      • 2014-12-02
      • 2019-11-20
      • 1970-01-01
      • 2013-02-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多