java - 当在容器中使用 BufferedImage 时,JButton 不在正确的位置

标签 java swing jbutton

我正在尝试使用 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);
}

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

here is a screenshot of the problem

根据要求:

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);
}
}

最佳答案

我不确定到底出了什么问题/你想要什么(为什么你有一个循环来不断绘制按钮并调用 removeAll()?等等,但我无法动摇它可能会在一种更具可读性/效率的方式)...

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

  • 不要使用null/Absolute 布局选择appropriate LayoutManager .

  • 不要覆盖 JFrame paint(..),而是将 JPanel 添加到 JFrame 和覆盖 JPanelpaintComponent(Graphics g) 并在那里绘图。(不要忘记将 super.paintComponent(..) 作为第一次调用在重写的 paintComponent 方法中。查看此处了解更多信息:Performing Custom Painting

  • 在将所有组件添加到 JFrame

    之前,不要将 JFrame 设置为可见
  • 始终在 Event Dispatch Thread 上创建和操作 Swing 组件像这样:

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

  • 不要在 JFrame 上调用 setSize(..) 而是覆盖 JPanelgetPreferredSize() > 并返回适合所有组件的 Dimension(推理参见 here),然后调用 pack()JFrame 上,然后将其设置为可见

  • 不要不必要地扩展 JFrameContainer!

  • 添加 WindowListener 以检测 JFrame 退出是不值得的,而是使用:

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    

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

关于java - 当在容器中使用 BufferedImage 时,JButton 不在正确的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13727586/

相关文章:

java - 如何在我的 JPanel 或 JFrame 中设置背景 Logo ?

java - 关于 JButton 和 ImageIcon

Java ActionListener 错误 : incompatible types

Java - 使用 hasNext() 方法时出现 "cannot find symbol"错误

java - hibernate 标准。选择所有不同的实体

java - 如何获取 WebSphere Application Server 中配置的 MQ 连接工厂中已使用/打开的连接数

java - 定制 JTable 外观

java - 如何在 JAVA 中用新值替换 ArrayList(具有多列)中的值

java - 如何从jtable中删除一行

java - 在 Java 网格中更改 ImageIcon