我正在尝试使用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);
}
}
答案 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之后再将其设置为可见
不要不必要地延长JPanel
或Dimension
!
添加JFrame
以检测JFrame
退出是不值得的,而不是使用:
Container
在按下 X 时退出Swing应用程序。