我正在尝试使用 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
布局选择appropriateLayoutManager
.不要覆盖
JFrame
paint(..)
,而是将JPanel
添加到JFrame
和覆盖JPanel
的paintComponent(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(..)
而是覆盖JPanel
的getPreferredSize()
> 并返回适合所有组件的Dimension
(推理参见 here),然后调用pack()
在JFrame
上,然后将其设置为可见不要不必要地扩展
JFrame
或Container
!添加
WindowListener
以检测JFrame
退出是不值得的,而是使用:frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
在按下 X 时退出 Swing 应用程序。
关于java - 当在容器中使用 BufferedImage 时,JButton 不在正确的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13727586/