我需要实现一个动态添加图形的GUI程序,第一层是Jframe,第二层是Jpanel,在Jpanel中动态添加Jcomponent元素(想画多个圆圈),下面是我实现的代码,问题是现在在Jpanel中无法正常显示我绘制的Jcomponent元素,而且比较诡异的是我在Jpanel中设置的类变量的值,在log中输出的一直是初始值,哪位大神能帮忙看看我的问题在哪?
(Note: 我的最终目标就是在Jframe.setVisible之后,可以动态添加圆圈到Jpanel中. 下面代码编译不过,因为是从整体代码中裁出来的跟此问题相关的部分,其他部分没有问题,就是不明白java GUI的更新原则,我怀疑是否跟layout也有一定关系,很迷糊,求帮忙!)
/* Jframe */
public class FsaEditor
{
public static JFrame jf;
public static FsaPanel panel; public static void init()
{
FsaImpl fsa = new FsaImpl(); jf = new JFrame("FsaEditor");
//jf.setSize(800, 500);
//jf.setSize(new Dimension(1000, 500));
//jf.setLocation(100, 100);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
/* add jpanel into frame */
panel = new FsaPanel(fsa);
panel.setPreferredSize(new Dimension(800, 500));
panel.setOpaque(false);
//panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
//jf.add(panel);
jf.getContentPane().add(panel, BorderLayout.CENTER);
jf.pack();
jf.setVisible(true);
} public static void main(String[] args)
{
init();
}
}
/* Panel */
public class FsaPanel extends JPanel implements FsaListener, PropertyChangeListener
{
private FsaImpl fsaImpl;
private ArrayList<StateIcon> stList; public FsaPanel(FsaImpl fsaImpl)
{
super();//(new BorderLayout());
stList = new ArrayList<StateIcon>(); this.fsaImpl = fsaImpl;
this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); } @Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
System.out.println("FsaPanel->paintComponent!!! "+stList.size());//<<<<<<stList.size()这个始终输出的是0。。
for(StateIcon stIcon : stList)
{
stIcon.repaint();
}
}
    public void propertyChange(PropertyChangeEvent evt)
    {
     StateIcon stIcon = new StateIcon();
        st.addListener(stIcon);
        stList.add(stIcon);
     this.add(stIcon);
    }
}
public class StateIcon extends JComponent implements StateListener, PropertyChangeListener
{
@Override
protected void paintComponent(Graphics g)
{
           super.paintComponent(g);
      g.setColor(Color.black);
   g.drawOval(this.state.getXpos(), this.state.getYpos(), 40, 40);
         }
    public void propertyChange(PropertyChangeEvent evt)
    {
       StateHasChanged();
    }
    public void StateHasChanged()
    {
     System.out.println("State->StateHasChanged");
     this.repaint();
    }
}

解决方案 »

  1.   


    就看到你
    stList = new ArrayList<StateIcon>();初始化,也没看到你用propertyChange方法来stList.add(stIcon),也没看到你用再说你的程序也不全,要贴程序就贴全点。
      

  2.   

    propertyChange()是ObserverList.firePropertyChange();的接收器(observer),这部分代码我debug过没有问题,在propertyChange()函数里stList.size()的值是可以正常变化的(debug确认过),我的问题就在于GUI的机制不是很明白,或者哪位大神可以给我一个利用Jframe, Jpanel,Jcomponent动态添加图形的sample code,非常感谢!!
    所有代码有很多文件代码太多,跟GUI没什么关系
      

  3.   


    你说了顶层容器是jframe,第2层是jpanel ,第3层是jcomponent,所以你只要在jcomponent,里调用gui,然后加入jpanel,在把jpanel加入jframe,看你的说明,明明是很简单的一个程序,我不知道你为什么会有很多的文件。好好整理一下你的思路吧,别把简单问题复杂化。
      

  4.   

    其他文件是后台处理数据用的,跟GUI没太大关系。刚刚接触GUI,所以不太知道如何应用,也许对于常用的人很简单。
    如果一切都在构造函数里做,我也能正常绘制,现在的问题是需要在observer里动态添加绘制图形,就无法正常输出了。
    正因为不知道问题出在哪里, 所以才没有思路
      

  5.   


    下面我建立了jframe,jpanel,jcomponent,把jcomponent放入jpanel,然后把jpanel放入jframe,编了一个输入圆心坐标然后画圆的程序。public class Circle {
    private int x,y; public Circle(int x, int y) {
    super();
    this.x = x;
    this.y = y;
    } public int getX() {
    return x;
    } public int getY() {
    return y;
    }
    }
    public class Jcomponent extends JComponent {

    List<Circle> list; public List<Circle> getList() {
    return list;
    } public void setList(List<Circle> list) {
    this.list = list;
    } public Jcomponent() {
    super();
    // TODO Auto-generated constructor stub
    setSize(600, 500);
    } @Override
    protected void paintComponent(Graphics g) {
    // TODO Auto-generated method stub
    super.paintComponent(g);
    g.setColor(Color.red);
    if(list!=null) {
    for (Circle circle : list) {
    g.drawOval(circle.getX(), circle.getY(), 100, 100);
    }
    }
    }}public class Jpanel extends JPanel {
    public Jpanel() {
    super();
    // TODO Auto-generated constructor stub
    setLayout(null);
    setSize(600, 500);
    setBackground(Color.yellow);
    }
    }
    public class Jframe extends JFrame {
    static Jpanel jp=new Jpanel();
    static Jcomponent jc=new Jcomponent();

    public Jframe() {
    // TODO Auto-generated constructor stub
    setTitle("Gui");
    setSize(600,500);
    setLayout(null);
    setBackground(Color.yellow);
    jp.add(jc);
    getContentPane().add(jp);
    setVisible(true);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    public static void main(String arg0[]) {
    List<Circle> list=new ArrayList<Circle>();
    new Jframe();
    Scanner sc=new Scanner(System.in);
    System.out.println("请输入圆心坐标x和y以逗号分开,直接按回车结束,注:(50<x<550,50<y<450)");
    String str=sc.nextLine();
    while(str!="") {
    String[] s=str.split(",");
    int x=Integer.valueOf(s[0]);
    int y=Integer.valueOf(s[1]);
    Circle c=new Circle(x-50, y-50);
    list.add(c);
    jc.setList(list);
    jc.repaint();
    System.out.println("请输入圆心坐标x和y以逗号分开,直接按回车结束,注:(50<x<550,50<y<450)");
    str=sc.nextLine();
    }
    System.exit(0);
    }
    }