向导有四类:
1.导入向导:扩展点 org.eclipse.ui.importWizards 与之关联的类必须要实现 org.eclipse.ui.IImportWizards
2.导出向导:扩展点 org.eclipse.ui.exportWizards 与之关联的类必须要实现 org.eclipse.ui.IExortWizards
3.导入向导:扩展点 org.eclipse.ui.newWizards 与之关联的类必须要实现 org.eclipse.ui.INewWizards
4.自定义向导
RCP之病人信息系统开发总结(7):MVC模式之View层—向导
 
本节实现一个自定义的向导,完成一个完整的向导开发:添加和修改病人信息的向导
1.继承自Wizard类的向导类:AddPatientInfoWizard,主要内容如下:
(1)向这个向导中添加两个向导页Page,我这里实现wizard和两个page之间Patient对象的统一使用的策略是:
定义一个单例类PatientFactory,里面只有一个Patient实例instance,而区别是添加操作还是修改操作使用的是一个type字符串
一个是“ADD”,另一个是“MODIFY”,调用打开wizard时传入type值,然后在生成page时传入type,这样就可以了!
(2)针对不同的type执行不同的操作,add的话是insert操作,modify的话是update操作
 
package com.yinger.patientims.wizards; 

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.swt.graphics.Image;

import com.yinger.patientims.Activator;
import com.yinger.patientims.dao.PatientDAO;
import com.yinger.patientims.model.Patient;
import com.yinger.patientims.sigleton.PatientFactory;
import com.yinger.patientims.util.DBUtil;
import com.yinger.patientims.util.PluginUtil;
import com.yinger.patientims.wizards.wizardPages.PatientBasicInfoWizardPage;
import com.yinger.patientims.wizards.wizardPages.PatientRegisterInfoWizardPage;

public class AddPatientInfoWizard extends Wizard {
  /**
   * 我觉得这里应该使用单态模式,用一个类(或者是Patient类)来保存一个patient对象,
   * 从而确保新建的时候处理的是同一个patient
   * 同时显示patient的信息也是一个patient,为了避免和这个patient冲突,可以在那个类中定义两个
   * 不同的patient,都是采用单例模式进行访问,OK! 添加病人信息和修改病人信息其实是同一个窗体!
   * 但是不同的是添加时patient是没有数据的
   */

//  private Patient patient;
  // 注意!这里对两个page和这个Wizard中都使用了一个Patient对象
  // 目的是为了通过这个patient得到输入的信息
  // 两个自定义的WizardPage
  private PatientBasicInfoWizardPage pageOne;
  private PatientRegisterInfoWizardPage pageTwo;

  private String type;

  @Override
  // 添加向导页面(实现了IWizardPage的类)
  /* 最需要注意的是两个page的patient对象是如何关联在一起的 */
  public void addPages() {
    // 设置图片这一句可以,没有问题
    getShell().setImage(new Image(null, Activator.getImageDescriptor("/icons/small/add.gif").getImageData()));
    // TODO:但是设置标题这一句没有生效!
    getShell().setText("Add Patient Information");

    pageOne = new PatientBasicInfoWizardPage();
    pageOne.setType(type);
    // 重点!
//    pageOne.setPatient(patient);
    pageTwo = new PatientRegisterInfoWizardPage();
    pageTwo.setType(type);
    // pageTwo.setPatient(patient);
    // 重点!
//    pageTwo.setPatient(pageOne.getPatient());// 后页的patient是前页的patient!
    addPage(pageOne);
    addPage(pageTwo);
  }

  @Override
  public boolean performFinish() {
    // 这个patient有了很多的信息,但是没有病床id
//    patient = pageTwo.getPatient();
    //经过两个page的设置,PatientFactory的单独实例已经不再是空的了
    Patient patient = PatientFactory.getInstance();
    // 首先根据已有的信息得到病床id
//    Long id = DBUtil.getSickBedId(patient);//实际上是没有必要的,因为可以从下拉列表中得到sickbed对象,id可以很容易的得到
//    Long id = patient.getSickbed().getId();
//    if (id != 0) {
//      patient.getSickbed().setId(id);
//    } else {
//      MessageDialog.openError(null, "Information", "Add patient information failed!");
//      return false;
//    }
//    然后再插入到数据库中
    if(type.equals(PluginUtil.ADD)){
      if (new PatientDAO().insertPatient(patient)) {
        MessageDialog.openInformation(null, "Information", "Add patient information successfully!");
        return true;
      } else {
        MessageDialog.openError(null, "Information", "Add patient information failed!");
        return false;
      }
    }else{
      if (new PatientDAO().updatePatient(patient)) {
        MessageDialog.openInformation(null, "Information", "Modify patient information successfully!");
        return true;
      } else {
        MessageDialog.openError(null, "Information", "Modify patient information failed!");
        return false;
      }
    }

  }

  public String getType() {
    return type;
  }

  public void setType(String type) {
    this.type = type;
  }

//  public Patient getPatient() {
//    return patient;
//  }
//
//  public void setPatient(Patient patient) {
//    this.patient = patient;
//  }
}
 
2.单例类:PatientFactory 类
package com.yinger.patientims.sigleton; 

import com.yinger.patientims.model.Patient;

/**
 * 采用非标准的单例模式
 * 主要用于添加patient和修改patient信息中
 * 
 * 突然有一个想法是建立一个公共的泛型的单例类
 * instance的类型是不确定的,根据传入的参数来确定!
 * 这样在有很多个增删查改的系统中非常适用!
 */

public class PatientFactory {

  private static Patient instance = new Patient();

  private PatientFactory() {
//    instance = new Patient();
  }

  public static Patient getInstance(){
    return instance;
  }

  public static void setInstance(Patient patient){
    instance = patient;
  }

}
 
3.两个Page
病人基本信息的Page
需要注意的是这个page不仅继承了WizardPage,同时还实现了ModifyListener接口,可以给控件添加修改时的Listener
还有需要处理不同的type情况:如果是Modify,那么就要让各个文本框中是病人原有的信息
RCP之病人信息系统开发总结(7):MVC模式之View层—向导
 
package com.yinger.patientims.wizards.wizardPages; 

import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

import com.yinger.patientims.model.Patient;
import com.yinger.patientims.sigleton.PatientFactory;
import com.yinger.patientims.util.PluginUtil;

public class PatientBasicInfoWizardPage extends WizardPage implements ModifyListener {

  private Text textName;
  private Text textAge;
  private Text textPhone;
  private Text textAddress;
  private Combo comboSex;

  private Patient patient;// 在这个类中保存一个Patient对象
  //采用了单例模式之后,这个是很有必要的!因为这个类中的很多方法使用到了patient

  private String type;

  // 不能使用默认的构造器,不论是pubic还是protected
  // 父类WizardPage就没有默认的构造器
  // protected PatientBasicInfoWizardPage(){
  //
  // }
  // 在这个无参的构造方法中调用父类的有参的构造方法,这样就不会报错了
  //这里设置的只是页面内的显示内容
  public PatientBasicInfoWizardPage() {
    // 报错:Implicit super constructor WizardPage() is undefined. Must
    // explicitly invoke another constructor
    super("PatientBasicInfoWizardPage");// 这里很重要!
    setTitle("Add Patient Information");
    setMessage("Attention:Please input the following information!", IMessageProvider.INFORMATION);
//    this.setImageDescriptor(Activator.getImageDescriptor("/icons/small/add.gif"));
    //这个图标不是显示在窗体外面的左上角,而是内部内容的右上角!

  }

  // 这个protected的构造方法一定要有!
  // 但是有了上面那个构造方法这个方法就不需要了
  // 但是我覺得可以有,用来设置type
  protected PatientBasicInfoWizardPage(String pageName) {
    super(pageName);
    this.type = pageName;
  }

  @Override
  // 创建相应的控件
  // 一般来说,相应的控件对象都定义为该类的内部属性比较好
  // 还有,一般label控件就不用作为内部属性了,但是国际化的话还是需要!
  // 另外,一般的这类用于填写某些信息的page都是使用GridLayout
  public void createControl(Composite parent) {
    Composite composite = new Composite(parent, SWT.NONE);
    composite.setLayout(new GridLayout(2, false));// 第一个参数是指列的数目,第二个参数是指列是否是等宽的
    GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
    // 等价于
    // GridData gridData = new GridData();
    // gridData.horizontalAlignment = GridData.FILL;

    // 添加相应的需要输入的信息的控件,并给控件添加监听器(就是类本身,因为它实现了ModifyListener)
    new Label(composite, SWT.NONE).setText("Name:");
    textName = new Text(composite, SWT.BORDER);
    textName.setLayoutData(gridData);
    textName.addModifyListener(this);

    new Label(composite, SWT.NONE).setText("Age:");
    textAge = new Text(composite, SWT.BORDER);
    textAge.setLayoutData(gridData);
    textAge.addModifyListener(this);

    new Label(composite, SWT.NONE).setText("Sex:");
    comboSex = new Combo(composite, SWT.READ_ONLY);
    comboSex.setItems(new String[]{"Male","Female"});
    comboSex.setText("Male");
    comboSex.setLayoutData(gridData);
    comboSex.addModifyListener(this);

    new Label(composite, SWT.NONE).setText("Phone:");
    textPhone = new Text(composite, SWT.BORDER);
    textPhone.setLayoutData(gridData);
    textPhone.addModifyListener(this);

    new Label(composite, SWT.NONE).setText("Address:");
    textAddress = new Text(composite, SWT.BORDER);
    textAddress.setLayoutData(gridData);
    textAddress.addModifyListener(this);
    setControl(composite);    
    setPageComplete(false);

//    if(patient.getId()!=null){//此时表示本次操作是 修改patient
//    if(null!=patient){
    patient = PatientFactory.getInstance();
    if(type.equals(PluginUtil.MODIFY)){
      textName.setText(patient.getName());
      textAge.setText(String.valueOf(patient.getAge()));
      textAddress.setText(patient.getAddress());
      textPhone.setText(patient.getPhone());
      comboSex.setText(patient.getSex());//这里貌似没有生效!

      setPageComplete(true);//如果是修改的话,这里page就应该是有效的!
    }

  }

  @Override
  // 实现ModifyListener接口的modifyText方法
  /**
   * TODO:想法:这个方法验证所有的文本框里的数据都不能是空的,但是这么写的话,重复冗余的代码很多
   * 重构的话,可以将其改成:遍历page的control中的所有文本框,再调用一个公共的方法验证有效性
   * 但是这样子的对某个需要特殊处理的文本框的处理又不好设置了!
   */

  public void modifyText(ModifyEvent e) {
    // 如果信息无效,给出相应的错误信息,并设置该页还没有完成,next按钮就是灰色的
    if (textName.getText().trim().length() == 0) {
      setMessage("Attention:Name must'n be blank!", IMessageProvider.WARNING);
      setPageComplete(false);
      return;
    }
    if (textAge.getText().trim().length() == 0) {
      setMessage("Attention:Age must'n be blank!", IMessageProvider.WARNING);
      setPageComplete(false);
      return;
    }
    if (comboSex.getText().trim().length() == 0) {
      setMessage("Attention:Sex must'n be blank!", IMessageProvider.WARNING);
      setPageComplete(false);
      return;
    }
    if (textPhone.getText().trim().length() == 0) {
      setMessage("Attention:Phone must'n be blank!", IMessageProvider.WARNING);
      setPageComplete(false);
      return;
    }
    if (textAddress.getText().trim().length() == 0) {
      setMessage("Attention:Address must'n be blank!", IMessageProvider.WARNING);
      setPageComplete(false);
      return;
    }
    setMessage(null);
    savePatientInfo(); // 到这里表示通过了验证,可以设置相应的内容到一个patient对象上
    setPageComplete(true);//这一句很重要的,不然完全填写正确也是不能next的!
  }

//  public Patient getPatient() {
//    return patient;
//  }
//  
//  public void setPatient(Patient patient){
//    this.patient = patient;
//  }

  // 保存填写的信息
  public void savePatientInfo() {
//    patient = new Patient();//注意:这里不能是new Patient!因为两个页面的patient是相关联的
    //得到PatientFactory的单独实例
//    Patient patient = PatientFactory.getInstance();

    /**
     * 如果是添加,patient是new Patient(),一个新的实例,id为null
     * 如果是修改,patient是已有的patient对象,id不为null
     * 
     * 但是对于如何判断操作的类型
     * 方法一:判断PatientFactory中的实例是否为空(但是不一定就是判断patient是否是null)
     * 方法二:使用一个String类型的参数type
     * 这里选用方法一
     * 但是,经过一段尝试,并分析之后,我觉得使用一个type来分别操作类型是最好的!
     */

    //给其赋值
    patient.setName(textName.getText().trim());
    patient.setAddress(textAddress.getText().trim());
    patient.setAge(Integer.valueOf(textAge.getText().trim()));
    patient.setPhone(textPhone.getText().trim());
    patient.setSex(comboSex.getText());
  }

  public String getType() {
    return type;
  }

  public void setType(String type) {
    this.type = type;
  }
}
 
病人住院信息page
这里需要注意的是三个下拉列表是关联着的,我的做法是:首先是只有科室是可以选择的,只有选择了科室之后才可以看到病房列表,
然后选择病房了之后才可以看到病床列表,同时,如果前面的修改了后面的要跟着一起修改!
还有一个要注意的是病人之前就有了一个病床,如果是在这里进行了操作,但是没有换病床,这个时候要提示一个更加合理的信息
如果是换了病床,同样也要提示是否这个病床已经有人住了
RCP之病人信息系统开发总结(7):MVC模式之View层—向导  RCP之病人信息系统开发总结(7):MVC模式之View层—向导
 
package com.yinger.patientims.wizards.wizardPages; 

import java.util.Date;

import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;

import com.yinger.patientims.dao.DepartmentDAO;
import com.yinger.patientims.dao.SickBedDAO;
import com.yinger.patientims.dao.SickRoomDAO;
import com.yinger.patientims.model.Department;
import com.yinger.patientims.model.Patient;
import com.yinger.patientims.model.SickBed;
import com.yinger.patientims.model.SickRoom;
import com.yinger.patientims.sigleton.PatientFactory;
import com.yinger.patientims.util.DBUtil;
import com.yinger.patientims.util.PluginUtil;

public class PatientRegisterInfoWizardPage extends WizardPage implements ModifyListener {

  private Combo comboDepartment;
  private Combo comboSickRoom;
  private Combo comboSickBed;

  private String sickBedNoString = "";
  private String sickRoomNoString = "";

  private Patient patient;// 在这个类中保存一个Patient对象

  private String type;

  public PatientRegisterInfoWizardPage() {
    super("PatientRegisterInfoWizardPage");// 这里很重要!
    setTitle("Add Patient Information");
    setMessage("Attention:Please input the following information!", IMessageProvider.INFORMATION);
    // this.setImageDescriptor(Activator.getImageDescriptor("/icons/small/add.gif"));
  }

  // 这个protected的构造方法一定要有!
  protected PatientRegisterInfoWizardPage(String pageName) {
    super(pageName);
    this.type = pageName;
  }

  @Override
  // 创建相应的控件
  public void createControl(Composite parent) {
    Composite composite = new Composite(parent, SWT.NONE);
    composite.setLayout(new GridLayout(2, false));// 第一个参数是指列的数目,第二个参数是指列是否是等宽的
    GridData gridData = new GridData(GridData.FILL_HORIZONTAL);

    // 添加相应的需要输入的信息的控件,并给控件添加监听器(就是类本身,因为它实现了ModifyListener)
    new Label(composite, SWT.NONE).setText("Department:");
    comboDepartment = new Combo(composite, SWT.READ_ONLY);
    comboDepartment.setLayoutData(gridData);
    comboDepartment.addModifyListener(this);
    // 设置数据
    for (Department department : new DepartmentDAO().getDepartmentList()) {
      comboDepartment.add(department.getName());// 首先要将字符串添加到列表中
      comboDepartment.setData(department.getName(), department);// 其次要设置Data,以String和Object形成映射
    }
    // comboDepartment.setSelection(new Point(0,
    // 0));//TODO:这一句不是很理解,貌似没有效果

    // 刚开始只是设置科室的列表,其他的列表动态的改变着
    new Label(composite, SWT.NONE).setText("SickRoom:");
    comboSickRoom = new Combo(composite, SWT.READ_ONLY);
    comboSickRoom.setLayoutData(gridData);
    comboSickRoom.addModifyListener(this);
    comboSickRoom.setEnabled(false);// 这里有很多的地方都要设置这个,可以重构一下

    new Label(composite, SWT.NONE).setText("SickBed:");
    comboSickBed = new Combo(composite, SWT.READ_ONLY);
    comboSickBed.setLayoutData(gridData);
    comboSickBed.addModifyListener(this);
    comboSickBed.setEnabled(false);

    setControl(composite);
    setPageComplete(false);

    // if(patient!=null){//此时表示本次操作是 修改patient
    patient = PatientFactory.getInstance();
    if (type.equals(PluginUtil.MODIFY)) {
      comboDepartment.setText(patient.getDepartment().getName());
      sickBedNoString = String.valueOf(patient.getSickbed().getSickBedNo());
      sickRoomNoString = String.valueOf(patient.getSickroom().getSickRoomNo());
      comboSickRoom.setText(sickRoomNoString);
      comboSickBed.setText(sickBedNoString);
      setPageComplete(true);
    }

  }

  @Override
  // 实现ModifyListener接口的modifyText方法
  /* 这个方法需要几点,最主要的是e.getSource(),还有一个是setPageComplete,最后一个是setEnabled */
  public void modifyText(ModifyEvent e) {
    // 如果信息无效,给出相应的错误信息,并设置该页还没有完成,next按钮就是灰色的
    if (e.getSource().equals(comboDepartment)) {// 首先得到出发事件的事件源
      if (comboDepartment.getText().trim().length() == 0) {// TODO:这个事件貌似不会发生!
        // 没选之前不会触发它,选了之后就不能再选择到空白
        setMessage("Attention:You should choose a department!", IMessageProvider.WARNING);
        setPageComplete(false);
        comboSickRoom.setEnabled(false);
        comboSickBed.setEnabled(false);
      } else {
        // 这里每次设置值之前要删除掉以前的值,但是这样带来的麻烦就是每次都要查一次数据库来设置值
        refreshComboSickRoom(comboDepartment.getText());
        comboSickRoom.setEnabled(true);
        comboSickBed.setEnabled(false);
      }
      return;
    }
    if (e.getSource().equals(comboSickRoom)) {
      if (comboSickRoom.getText().trim().length() == 0) {
        setMessage("Attention:You should choose a sickroom!", IMessageProvider.WARNING);
        setPageComplete(false);
        comboSickBed.setEnabled(false);
      } else {
        refreshComboSickBed(comboSickRoom.getText());
        comboSickBed.setEnabled(true);
      }
      return;
    }
    if (e.getSource().equals(comboSickBed)) {
      if (comboSickBed.getText().trim().length() == 0) {
        setMessage("Attention:You should choose a sickbed!", IMessageProvider.WARNING);
        setPageComplete(false);
        return;
      }
    }

    // 如果是修改操作,并且还是原来的那个病床(病房也是相同的),给出不同的提示信息
    // 注意这里的String.valueOf很重要的,不能省掉了,不然String和int用equals,永远不会相等
    if (type.equals(PluginUtil.MODIFY) && comboSickRoom.getText().equals(sickRoomNoString) && comboSickBed.getText().equals(sickBedNoString)) {
      setMessage("Warning:The SickBed has been taken by the present patient!", IMessageProvider.WARNING);
      // 此时是可以返回的,有效的
    } else {
      // 判断这个床位是否已经有人了!
      /* TODO:这里最好是改为可以入住的床位 */
      if (DBUtil.validateSickBed(comboDepartment.getText(), Integer.valueOf(comboSickBed.getText()), Integer.valueOf(comboSickRoom.getText()))) {
        setMessage("Error:The SickBed has been taken!", IMessageProvider.WARNING);
        setPageComplete(false);
        return;
      }else{
        setMessage(null);
      }
    }
    // 这里不能调用savePatientInfo方法,不然会改变原有的patient的值!这样导致下次选择到原有的信息时提示还是不对!
    savePatientInfo(); // 到这里表示通过了验证,可以设置相应的内容到一个patient对象上
    setPageComplete(true);
  }

  // 刷新病床列表
  private void refreshComboSickBed(String text) {
    comboSickBed.setItems(new String[0]);// java.lang.IllegalArgumentException:
                  // Argument cannot be null
    String where = " and sickroom_id = (select id from t_sickroom where sickroomno=" + text + ") ";
    for (SickBed sickBed : new SickBedDAO().getSickBedList(where)) {
      comboSickBed.add(String.valueOf(sickBed.getSickBedNo()));
      comboSickBed.setData(String.valueOf(sickBed.getSickBedNo()), sickBed);// 因为这里setData了,所以可以很轻松的得到病床id
    }
  }

  // 刷新病房列表
  private void refreshComboSickRoom(String text) {
    comboSickRoom.setItems(new String[0]);
    String where = " and department_id = (select id from t_department where name='" + text + "') ";
    for (SickRoom sickRoom : new SickRoomDAO().getSickRoomList(where)) {
      comboSickRoom.add(String.valueOf(sickRoom.getSickRoomNo()));
      comboSickRoom.setData(String.valueOf(sickRoom.getSickRoomNo()), sickRoom);
    }
  }

  // public Patient getPatient() {
  // return patient;
  // }
  //
  // public void setPatient(Patient patient) {
  // this.patient = patient;
  // }

  // 保存填写的信息
  public void savePatientInfo() {
    // 得到PatientFactory的单独实例
    // Patient patient = PatientFactory.getInstance();
    // patient = PatientFactory.getInstance();//还是得到这个patient

    // 给其赋值
    // 注意登记时间需要考虑
    if (type.equals(PluginUtil.ADD)) {// 只要在添加时需要修改
      patient.setLogtime(new Date());
    }
    patient.getDepartment().setName(comboDepartment.getText());
    patient.getSickroom().setSickRoomNo(Integer.valueOf(comboSickRoom.getText()));
    patient.getSickbed().setSickBedNo(Integer.valueOf(comboSickBed.getText()));

    // 设置病床id
    SickBed sickBed = (SickBed) comboSickBed.getData(comboSickBed.getText());
    patient.getSickbed().setId(sickBed.getId());
  }

  public String getType() {
    return type;
  }

  public void setType(String type) {
    this.type = type;
  }
}





相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-08-21
  • 2022-12-23
  • 2021-10-25
  • 2022-01-18
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案