打造我的java向导型窗口

类别:Java 点击:0 评论:0 推荐:

    首先声明,偶是菜鸟!所以高手看这篇文章前请平心静气,看完后请勿破口大骂,谢谢!欢迎友好的评论!
    最近对制做窗体产生极大的兴趣(唉,又一个不务正业者)。整天在那边琢磨这个窗体是怎么做的,那个窗体是怎么设计的,恨不得把电脑里装的程序一个个大卸八块仔细研究研究(走火入魔了,-_-|||)。今天琢磨了一下向导的制做方法,弄出来大家讨论讨论……
    一个向导运行的过程中,可能会加载很多JPanel,如果采用临时加载的办法,运行时就会比较慢。所以我采用在向导启动时全部加载,这样启动的时候会较慢,但是运行时就快了。观察发现,和用PS制做图像的图层相反,java在加载组件的时候,先加载的组件将覆盖后面的组件。这样我们就可以把所有的JPanel加载在同一个位置,要显示下一个JPanel的时候只要把当前的setVisible(false);再repaint();就行了。现在问题出来了,有些组件会透过前面的JPanel显示出来,比如JTextField。怎么办呢?把不需要显示的JPanel全部setVisible(false);整个世界清静了……
    现在我们解决了一个显示的问题。Next problem is NEXT.向导不是光用来看的。首先我们要捕获用户的输入,然后判断用户的输入是否合法,无效的输入要产生错误提示,有效的输入才能继续。当然我们不能在GuideFrame类中做这些事情,否则就不能重用了。所以我们要声明一个Interface:

package nicholas.swing;

public interface Checkable {
 public boolean check();
 public String getErrorMessage();
}

再声明一个Abstract class:

package nicholas.swing;

import javax.swing.*;

public abstract class CheckPanel extends JPanel implements Checkable {
 
 public CheckPanel() {
  this.setVisible(false);
  this.setBorder(BorderFactory.createEtchedBorder());
 }
 
 public abstract String getTitle();
 public abstract String getDetail();
}


现在我们可以使用CheckPanel的子类来实现所有的输入检查操作,而GuideFrame只要获得检查的结果并决定是否调用下一个CheckPanel就可以了。下面是GuideFrame的代码:

package nicholas.swing;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class GuideFrame extends JFrame implements ActionListener {
 
 private CheckPanel panel[];
 private JButton nextButton;
 private JButton prevButton;
 private JButton exitButton;
 
 private JLabel titleLabel;
 private JLabel detailLabel;
 private JLabel imageLabel;
 
 private int current;
 
 public GuideFrame() {
  super();
  current = 0;
  getContentPane().setLayout(null);
  setupUI();
  setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
  setResizable(false);
  setSize(500,360);
  Dimension screen = getToolkit().getScreenSize();
  setLocation((screen.width-getSize().width)/2, (screen.height-getSize().height)/2);
  show();
 }
 
 public void setPanel(CheckPanel p[]) {
  panel = p;
  
  for(int i=0;i<panel.length;i++) {
   panel[i].setBounds(-2,53,504,235);
   getContentPane().add(panel[i]);
  }
  panel[0].setVisible(true);
 }
 
 private void setupUI() {
  titleLabel = new JLabel("标题");
  titleLabel.setBounds(10,5,200,20);
  detailLabel = new JLabel("详细");
  detailLabel.setBounds(20,20,300,20);
  //enable this sentence will greatly slow down the speed.
//  detailLabel.setFont(new Font("宋体",Font.PLAIN,12));
  imageLabel = new JLabel();
  imageLabel.setBounds(445,7,40,40);
  imageLabel.setBorder(BorderFactory.createEtchedBorder());
  
  JPanel panel = new JPanel(null);
  panel.setBounds(0,0,500,53);
  panel.setBackground(Color.white);
  panel.add(titleLabel);
  panel.add(detailLabel);
  panel.add(imageLabel);
  getContentPane().add(panel);
  
  prevButton = new JButton("上一步");
  prevButton.setBounds(245,298,75,21);
  prevButton.addActionListener(this);
  prevButton.setVisible(false);
  nextButton = new JButton("下一步");
  nextButton.setBounds(325,298,75,21);
  nextButton.addActionListener(this);
  exitButton = new JButton("取消");
  exitButton.setBounds(413,298,65,21);
  exitButton.addActionListener(this);
  getContentPane().add(prevButton);
  getContentPane().add(nextButton);
  getContentPane().add(exitButton);
 }
 
 private void quit() {
 }
 
 public void actionPerformed(ActionEvent ae) {
  if(ae.getSource()==exitButton) {
   int result = JOptionPane.showConfirmDialog(this,"您是否确认要退出本向导?\n所有信息将丢失.",
       "退出",JOptionPane.YES_NO_OPTION,JOptionPane.INFORMATION_MESSAGE);
   if(result==JOptionPane.YES_OPTION) {
    System.exit(0);
   } 
  } else if(ae.getSource()==nextButton) {
   if(panel[current].check()) {
    //can do next job
    panel[current].setVisible(false);
    current++;
    if(current==1) {
     prevButton.setVisible(true);
    }
    if(current==(panel.length-1)) {
     prevButton.setVisible(false);
     nextButton.setText("完成");
    } else if(current==panel.length) {
     quit();
     return;
    }
    panel[current].setVisible(true);
    repaint();
   } else {
    //cannot continue
    JOptionPane.showMessageDialog(this,panel[current].getErrorMessage(),
      "警告",JOptionPane.ERROR_MESSAGE);
    return;
   }
  } else {
   panel[current].setVisible(false);
   current--;
   panel[current].setVisible(true);
   if(current==0) {
    prevButton.setVisible(false);
   }
   repaint();
  }
 }
}


    其中titleLabel、detailLabel、imageLabel可以放在CheckPanel中,但是个人觉得放在GuideFrame里比较好,只是CheckPanel跳转时要同时给前两个JLabel赋值比较麻烦(代码没给出,偶懒……)。另外还没琢磨出来license panel要怎么弄……
    如果您有任何意见或建议,请不吝指出,谢谢!

Nicholas Lin @ Jan 8,2005

本文地址:http://com.8s8s.com/it/it11958.htm