我有一个类Roundabout(JFrame),Surface(JPanel)和Spawn。在Surface paintComponent
我已经画了一些红绿灯,因为它们总是在环形交叉路口。但我也想在运行时绘制组件。所以我在JFrame中添加了一个mousePressed事件,我在这里调用的方法从Spawn.java中调用spawnPedestrian
,我可以看到这个因为println
。但是当调用spawnPedestrian
时,没有画任何东西!如果我在Surface类中创建一个行人并绘制它,它就可以工作。我如何让spawnPedestrian
工作?我试图包含最小代码片段(见下文)。
human.png
roundabout.png
public class Spawn {
public void spawnPedestrian(){
//Create a new pedestrian.
Pedestrian p = new Pedestrian(100,100);
Roundabout.getSurface().add(p);
Roundabout.getSurface().revalidate();
Roundabout.getSurface().repaint();
}
}
public class Roundabout extends JFrame{
static Surface surface=new Surface();
public Roundabout(){
initUI();
}
private void initUI() {
setTitle("Roundabout");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(surface);
this.addMouseListener(new MouseAdapter() {// empty implementation of all
// MouseListener`s methods
@Override
public void mousePressed(MouseEvent e) {
System.out.println(e.getX() + "," + e.getY());
Spawn spawn=new Spawn();
spawn.spawnPedestrian();
}
});
setSize(1618,850);
setLocationRelativeTo(null);
}
public static JPanel getSurface() {
return surface;
}
public static void main(String[] args) {
//Swing thread
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Roundabout roundabout=new Roundabout();
roundabout.setVisible(true);
}
});
}
class Surface extends JPanel {
Track track=new Track();
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
//Make sure the track is painted first
track.paint(g);
}
}
public class Track{
BufferedImage track;
Point trackPosition;
static final Point TRACK_POS = new Point(0, 0);
static final Point SENSOR_POS = new Point(250, 70);
public Track(){
try {
track = ImageIO.read(Roundabout.class.getResource("images/roundabout.png"));
} catch (Exception ex) {
System.out.println("Problem loading track image: " + ex);
}
trackPosition=new Point(TRACK_POS.x,TRACK_POS.y);
}
public void paint(Graphics g)
{
g.drawImage(track,TRACK_POS.x, TRACK_POS.y, null);
}
}
public class Spawn {
//Needs x/y pos
public void spawnPedestrian(){
Pedestrian p = new Pedestrian(30,50);
System.out.println("Spawn me ");
Roundabout.getSurface().add(p);
Roundabout.getSurface().revalidate();
Roundabout.getSurface().repaint();
}
}
}
public class Pedestrian extends JComponent {
BufferedImage pedestrian;
Point pedestrianPosition;
double pedestrianRotation = 0;
int pedestrianW, pedestrianH;
public Pedestrian(int x, int y){
try {
pedestrian = ImageIO.read(Car.class.getResource("images/human.png"));
} catch (IOException e) {
System.out.println("Problem loading pedestrian images: " + e);
}
pedestrianPosition = new Point(x,y);
pedestrianW = pedestrian.getWidth();
pedestrianH = pedestrian.getHeight();
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.rotate(Math.toRadians(pedestrianRotation), pedestrianPosition.x, pedestrianPosition.y);
g2d.drawImage(pedestrian, pedestrianPosition.x, pedestrianPosition.y, null);
}
编辑:我想通过将Surface
布局设置为null
并将setBounds
设置为Pedestrian
来解决此问题。但是我向右移动图像的次数越多,我就越需要在height
中设置width
和setBounds()
。有谁可以提供帮助?
编辑:修改了我的帖子,现在是一个可运行的示例,您只需为Track
和Pedestrian
选择自己的图片。
编辑:一次复制粘贴操作以添加代码和图像。
答案 0 :(得分:2)
当您编写Roundabout.getSurface().add(p);
时,您正在向JPanel
对象添加JComponent。 JPanel必须具有显示子组件的布局。默认情况下,这是FlowLayout
(请参阅doc)。 FlowLayout用于连续显示其他组件旁边的组件。它不支持在任意坐标处显示组件。
我不确定为什么没有显示行人,但原因可能是它们的尺寸为0x0。您可以使用以下方法轻松检查:
p.setPreferredSize(new Dimension(50,50));
根据您的需要,您可以采用不同的方法:Surface可以是一个简单的Canvas,而不是扩展JPanel,它包含一个" Paintables"的列表,例如Pedestrians。在Surface.paintComponent()
中,您可以调用每个Paintable.paint()
,为其提供Graphics对象:
interface Paintable {
public void paint(Graphics2D g);
}
class Pedestrian implements Paintable {
public double x, y;
public void paint(Graphics2D g){
Shape circle = new Ellipse2D.Double(x - 5, y - 5, 10, 10);
g2d.draw(circle);
}
}
class Surface extends Canvas {
public List<Paintable> components = new ArrayList<Paintable>();
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for(Paintable p : components)
p.paint((Graphics2D) g);
}
}
编辑:我发现您的代码存在一些其他问题:
FlowLayout
(因此它不会管理在给定坐标处显示组件)。setPreferredSize(Roundabout.getSurface().getSize());
。将paint()方法替换为:
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.rotate(Math.toRadians(pedestrianRotation),
pedestrianPosition.x, pedestrianPosition.y);
g2d.drawImage(pedestrian, pedestrianPosition.x,
pedestrianPosition.y, null);
}
surface =new Surface();
应在initUI()
内调用,以便在事件线程上实现。