我需要实现一个动态添加图形的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();
}
}
(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();
}
}
就看到你
stList = new ArrayList<StateIcon>();初始化,也没看到你用propertyChange方法来stList.add(stIcon),也没看到你用再说你的程序也不全,要贴程序就贴全点。
所有代码有很多文件代码太多,跟GUI没什么关系
你说了顶层容器是jframe,第2层是jpanel ,第3层是jcomponent,所以你只要在jcomponent,里调用gui,然后加入jpanel,在把jpanel加入jframe,看你的说明,明明是很简单的一个程序,我不知道你为什么会有很多的文件。好好整理一下你的思路吧,别把简单问题复杂化。
如果一切都在构造函数里做,我也能正常绘制,现在的问题是需要在observer里动态添加绘制图形,就无法正常输出了。
正因为不知道问题出在哪里, 所以才没有思路
下面我建立了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);
}
}