我拿我自己正在做的一个界面来介绍一下
这是是解决了清除JPanel组件并能重绘的代码
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
public class TestFrame extends JFrame implements ActionListener {
JLabel welcome = new JLabel("欢迎使用报刊订阅系统:");
JLabel user = new JLabel("user");
JButton linsert = new JButton("报 刊 录 入");
JButton lsearch = new JButton("报 刊 查 询");
JButton laccount = new JButton("报 刊 统 计");
JLabel lcenter = new JLabel("欢迎试用!");
JPanel ptop = new JPanel();
JPanel pleft1 = new JPanel();
JPanel pleft2 = new JPanel();
JPanel pleft3 = new JPanel();
JPanel pleft = new JPanel();
JPanel pcenter = new JPanel();
public TestFrame() {
super("企业报刊订阅管理系统");
ptop.setLayout(new FlowLayout(0));
pleft.setLayout(new GridLayout(8, 1));
ptop.add(welcome);
ptop.add(user);
pleft1.add(linsert);
pleft2.add(lsearch);
pleft3.add(laccount);
pleft.add(pleft1);
pleft.add(pleft2);
pleft.add(pleft3);
pcenter.add(lcenter);
ptop.setBorder(new EtchedBorder(EtchedBorder.RAISED));
pleft.setBorder(new EtchedBorder(EtchedBorder.RAISED));
pcenter.setBorder(new EtchedBorder(EtchedBorder.RAISED));
Border border=BorderFactory.createEtchedBorder(Color.white, Color.white);
Border title=BorderFactory.createTitledBorder(border,"订阅管理",TitledBorder.RIGHT,TitledBorder.TOP,
new Font("楷体", Font.BOLD, 26),Color.blue);
welcome.setFont(new Font("楷体", Font.BOLD, 24));
user.setFont(new Font("楷体", Font.BOLD, 20));
user.setForeground(Color.CYAN);
linsert.setFont(new Font("楷体", Font.BOLD, 20));
lsearch.setFont(new Font("楷体", Font.BOLD, 20));
laccount.setFont(new Font("楷体", Font.BOLD, 20));
lcenter.setFont(new Font("楷体", Font.BOLD, 24));
pleft.setBorder(border);
pleft.setBorder(title);
this.setSize(800, 600);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setLayout(new BorderLayout());
this.setVisible(true);
this.add(ptop, BorderLayout.NORTH);
this.add(pleft, BorderLayout.WEST);
this.add(pcenter, BorderLayout.CENTER);
linsert.addActionListener(this);
lsearch.addActionListener(this);
laccount.addActionListener(this);
}
public static void main(String[] args) {
new TestFrame();
}
}
我把清空组件和重绘放在按钮单击按钮事件里面完成的,所以主要就是按钮里面的方法。
一开始我用的是
if (e.getSource() == laccount) {
pcenter.removeAll();}
运行发现没用。
然后加了repaint()重绘图形区域
if (e.getSource() == laccount) {
pcenter.removeAll();
pcenter.repaint();
pcenter.add(Account.setAccount());
}
运行发现图形区域被清空了,但是并没有把我重绘的东西显示出来。
然后我把rapaint()去掉,在末尾用revalidate();
if (e.getSource() == laccount) {
pcenter.removeAll();
pcenter.add(Account.setAccount());
pcenter.revalidate();
}
运行后确实我重绘的东西显示出来了,但是观察后发现原来的组件斌没有删除,而是被遮盖了,注意是遮盖不是覆盖,原来的组件仍然存在,只是点击按钮后,把新添加进去的组件显示出来了,但是点击多个按钮会发现当所有按钮里面的组件都被添加进去后再点击按钮,显示的组件是最后一个,也就是组件不再刷新显示了,这有点像一个数组,把所有的组件添加进去后相同的组件不再添加。
之后我再把repaint(),添加进去
if (e.getSource() == laccount) {
pcenter.removeAll();
pcenter.repaint();
pcenter.add(Account.setAccount());
pcenter.revalidate();
}
最终得到了想要的结果,组件被清空,并且完成了自己的重绘功能
对于这个问题我的理解是:先用removeAll()移除了所有组件,但是并未刷新,所以单使用这个方法虽然内部组件确实改变了,但是界面显示不变;repaint()相当于刷新了整个面板,所以用了remover All()之后面板是空的,如果不先使用removeAll()那么接下来添加的组件会接在之前存在的组件后面(因为之前的组件未移除);然后在添加新的组件后使用revalidate(),重新对面板计算大小并且对面板中的组件进行布局,这样就把新添加的组件添加进去了。对于revalidate() JDK里面是这样说的:使用 validate
方法会使容器再次布置其子组件。已经显示容器后,在修改此容器的子组件的时候(在容器中添加或移除组件,或者更改与布局相关的信息),应该调用上述方法。我觉得这里应该有一个刷新作用,添加了组件后必须刷新面板才能再次显示出来。
总结:先移除组件( removeAll() ),然后重绘面板( repaint() ),再添加组件( add() ),最后重新布局面板( revalidate() )。
以上内容是我百度后自己摸索出来的,欢迎大家批评指正!
以上内容我参考了下面的网站
http://stackoverflow.com/questions/1097366/java-swing-revalidate-vs-repaint