RCP之病人信息系统开发总结(7):MVC模式之View层—向导

向导有四类:
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.自定义向导
 
本节实现一个自定义的向导,完成一个完整的向导开发:添加和修改病人信息的向导
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,那么就要让各个文本框中是病人原有的信息
 
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
这里需要注意的是三个下拉列表是关联着的,我的做法是:首先是只有科室是可以选择的,只有选择了科室之后才可以看到病房列表,
然后选择病房了之后才可以看到病床列表,同时,如果前面的修改了后面的要跟着一起修改!
还有一个要注意的是病人之前就有了一个病床,如果是在这里进行了操作,但是没有换病床,这个时候要提示一个更加合理的信息
如果是换了病床,同样也要提示是否这个病床已经有人住了
 
 
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;
  }
}





转载于:https://www.cnblogs.com/yinger/archive/2011/11/19/2255644.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值