在运行时

时间:2015-05-19 10:36:07

标签: java swing

我有一个类Roundabout(JFrame),Surface(JPanel)和Spawn。在Surface paintComponent我已经画了一些红绿灯,因为它们总是在环形交叉路口。但我也想在运行时绘制组件。所以我在JFrame中添加了一个mousePressed事件,我在这里调用的方法从Spawn.java中调用spawnPedestrian,我可以看到这个因为println。但是当调用spawnPedestrian时,没有画任何东西!如果我在Surface类中创建一个行人并绘制它,它就可以工作。我如何让spawnPedestrian工作?我试图包含最小代码片段(见下文)。

human human.png

track 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中设置widthsetBounds()。有谁可以提供帮助?

编辑:修改了我的帖子,现在是一个可运行的示例,您只需为TrackPedestrian选择自己的图片。

编辑:一次复制粘贴操作以添加代码和图像。

1 个答案:

答案 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);

   }

}
编辑:我发现您的代码存在一些其他问题:

  • Surface.java:请注意,您使用默认的FlowLayout(因此它不会管理在给定坐标处显示组件)。
  • Pedestrian.java:在构造函数的末尾添加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);
}
  • RoundAbout.java:surface =new Surface();应在initUI()内调用,以便在事件线程上实现。