2

我正在尝试使用 AWT 创建一个简单的游戏,但我还想要一些 JButton 来退出/重置游戏。问题是,我希望将 BufferedImage 绘制在可见框架内,就像在我的容器中一样,我最后有这个:

g.drawImage(bf,getParent().getInsets().left,getParent().getInsets().top,null);

我的问题是,当我向该框架添加一个 JButton 时,它只检测到空间中的翻转,不考虑偏移,而是在一个空间中绘制。这是相关代码(con 是容器)。

    private void addButtons()
{
    reset = new JButton("reset");
    reset.setBounds(180,460, 75,30);
    reset.addActionListener( this );
    con.add(reset);
    exit = new JButton("exit");
    exit.setBounds(290,460, 60,30);
    exit.addActionListener( this );
    con.add(exit);
    con.repaint();
}

Container中的paint方法

public void paint(Graphics g)
{
    bf = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB);
    Graphics b = bf.getGraphics();
    b.setColor(Color.GRAY);
    b.fillRect(0, 0, this.getWidth(), this.getHeight());
    b.setColor(Color.BLACK);
    b.drawRect(0,0,420,420);
    super.paint(b);
    g.drawImage(bf,getParent().getInsets().left,getParent().getInsets().top,null);
}

如何使按钮在同一个位置被绘制和检测?

这是问题的屏幕截图

按照要求:

import java.awt.*;
import javax.swing.*;
import java.util.*;
import java.awt.image.*;
import java.awt.event.*;
import java.awt.Color;
public class Draw implements ActionListener{
private SnakeFrame frame;
private SnakeCon con;
JButton reset, exit;
private boolean res;
public Draw() 
{
    frame = new SnakeFrame("Snake");
    frame.setResizable(false);
    frame.setLayout(null);
    frame.setSize(600,600);
    frame.setVisible(true);
    con = new SnakeCon();
    con.setBounds(0,0,600,600);
    frame.add(con);
}

private void addButtons()
{
    reset = new JButton("reset");
    reset.setBounds(180,460, 75,30);
    reset.addActionListener( this );
    con.add(reset);
    exit = new JButton("exit");
    exit.setBounds(290,460, 60,30);
    exit.addActionListener( this );
    con.add(exit);
    con.repaint();
}
public void run()
{

    addButtons();
    res = false;
    boolean dead = false;       
    while(!dead)
    {
        if( (res) )
            dead = true;
        if (!dead)
        {
            try{
            Thread.sleep(100);
            }
            catch (Exception e)
            {}
            frame.repaint();
        }
    }
    con.removeAll();
}

public void actionPerformed(ActionEvent e)
{
    if (e.getSource() == reset)
    res = true;
else if (e.getSource() == exit)
    System.exit(0);
}
}

--

    import java.awt.*;
import javax.swing.*;
import java.util.*;
import java.awt.image.*;
import java.awt.event.*;
import java.awt.Color;
public class SnakeCon extends Container{
    private BufferedImage bf;

    public SnakeCon()
    {
        super();
        setBounds(0,0,600,600);
    }
    public void paint(Graphics g)
    {
        bf = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics b = bf.getGraphics();
        b.setColor(Color.GRAY);
        b.fillRect(0, 0, this.getWidth(), this.getHeight());
        b.setColor(Color.BLACK);
        b.drawRect(0,0,420,420);
        super.paint(b);
        g.drawImage(bf,getParent().getInsets().left,getParent().getInsets().top,null);
    }
    public void update(Graphics g)
    {
        paint(g);
    }
    }

--

    import java.awt.*;
import javax.swing.*;
import java.util.*;
import java.awt.image.*;
import java.awt.event.*;
import java.awt.Color;
public class SnakeFrame extends Frame implements WindowListener{
    private BufferedImage bf;

    public SnakeFrame(String s)
    {
        super(s);
        addWindowListener( this );
    }
    public void paint(Graphics g)
    {

        bf = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics b = bf.getGraphics();
        super.paint(b);
        g.drawImage(bf,0,0,null);
    }
    public void update(Graphics g)
    {
        paint(g);
    }

    public void windowClosing(WindowEvent e) 
    {
            System.exit(0);
    }

    public void windowClosed(WindowEvent e) {    }

    public void windowOpened(WindowEvent e) {    }

    public void windowIconified(WindowEvent e) {    }

    public void windowDeiconified(WindowEvent e) {    }

    public void windowActivated(WindowEvent e) {    }

    public void windowDeactivated(WindowEvent e) {    }
    }

--

public class Main {
public static void main(String[] args) 
{
    boolean never = false;
    Draw d = new Draw();
    while(!never)
    {
        d.run();
    }
    System.exit(0);
}
}
4

1 回答 1

1

我不确定到底出了什么问题/你想要什么(为什么你有一个循环来不断地绘制按钮和调用removeAll()?等等,但我无法摆脱它可能以更易读/更有效的方式实现的感觉)......

但这里有一些建议只能帮助您的代码变得更好:

  • 不要使用null/ AbsoluteLayout 选择一个合适LayoutManager的.

  • 不要覆盖JFrame paint(..),而是添加JPanelJFrame覆盖并paintComponent(Graphics g)JPanel那里绘制。(不要忘记super.paintComponent(..)在覆盖paintComponent方法中进行第一次调用。有关更多信息,请参见此处:执行自定义绘画

  • JFrame在添加所有组件之前不要设置可见JFrame

  • 始终像这样创建和操作 Swing 组件Event Dispatch Thread

     SwingUtilities.invokeLater(new Runnable() {
          @Override
          public void run() {
             //create Swing components
         }
     });
    
  • 不要做长时间运行的任务,Event Dispatch Thread而是使用Swing Timer / Swing Worker

  • 不要调用setSize(..)JFrame不是覆盖和返回适合所有组件的 s(参见getPreferredSize()此处进行推理),而不是在设置为可见之前调用JPanelDimensionpack()JFrame

  • JFrame不要不必要地扩展或Container

  • 添加WindowListener用于检测JFrame退出不值得使用以下行:

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    

按下X时退出 Swing 应用程序。

于 2012-12-05T18:56:46.277 回答