zoukankan      html  css  js  c++  java
  • 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;
      }
    }





  • 相关阅读:
    for循环之初学者N多算法小练习
    Java数据类型(基本数据类型)学习
    Windows10 图标重建
    springMVC框架搭建
    Spring框架 jar包下载
    Hibernate配置文件中配置各种数据库链接
    Ajax第一课
    Windows 10 碎片整理程序使用
    python之restful api(flask)获取数据
    谷歌浏览器安装扩展程序
  • 原文地址:https://www.cnblogs.com/yinger/p/2255644.html
Copyright © 2011-2022 走看看