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

时间:2012-12-05 16:16:09

标签: 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);
}
}

1 个答案:

答案 0 :(得分:1)

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

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

  • 请勿使用null / Absolute布局选择appropriate LayoutManager

  • 不要覆盖JFrame paint(..),而是将JPanel添加到JFrame并覆盖paintComponent(Graphics g)的{​​{1}}并在那里绘图。(不要忘记将JPanel作为覆盖super.paintComponent(..)方法的第一次调用。有关详情,请参阅此处:Performing Custom Painting

  • 在将所有组件添加到paintComponent

  • 之前,请勿将JFrame设置为可见
  • 始终在Event Dispatch Thread上创建和操作Swing组件,如下所示:

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

  • 请勿在{{1​​}}上致电Event Dispatch Thread而是覆盖setSize(..)的{​​{1}}并返回符合所有组件的JFrame(请参阅{{3} }}用于推理),而不是在getPreferredSize()上调用here之后再将其设置为可见

  • 不要不必要地延长JPanelDimension

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

    Container

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