RCP之病人信息系统开发总结(6):MVC模式之View层—编辑器

项目中大致有三个编辑器Editor,我也只是写了最重要的 PatientInfoEditor
 
 
一个完整的编辑器的开发过程:
1.继承自EditorPart的PatientInfoEditor 类,主要内容如下:
(1)定义一个用于显示信息的TableViewer
(2)给TableViewer设置ContentProvider,LabelProvider以及Sorter
(3)设置TableViewer的数据Input
(4)设置编辑器的工具栏CoolBar上的按钮:这里将各个Action定义成了内部类,因为它们没有可复用性
Action包括Add,Modify,Delete,Refresh,其中Delete和Refresh很简单,关键是Add和Modify,它们是通过打开一个Dialog来完成的,
具体内容将在下节介绍
为了避免误删除,要有提示:
 
package com.yinger.patientims.editors; 

import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ViewForm;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorPart;

import com.yinger.patientims.Activator;
import com.yinger.patientims.dao.PatientDAO;
import com.yinger.patientims.editors.viewerSorter.PatientInfoSorter;
import com.yinger.patientims.model.Patient;
import com.yinger.patientims.sigleton.PatientFactory;
import com.yinger.patientims.util.PluginUtil;
import com.yinger.patientims.views.viewerProvider.PatientInfoTableViewerContentProvider;
import com.yinger.patientims.views.viewerProvider.PatientInfoTableViewerLabelProvider;
import com.yinger.patientims.wizards.AddPatientInfoWizard;

public class PatientInfoEditor extends EditorPart {

  private PatientDAO patientDAO;

  // 一般查看器在哪个控件(类)里显示,这个类就要有一个相应的查看器的字段
  private TableViewer tableViewer;// 表格查看器
  private boolean sort;// 标识排序的方式

  @Override
  public void doSave(IProgressMonitor monitor) {
  }

  @Override
  public void doSaveAs() {
  }

  @Override
  // 这个方法要修改(编写)
  public void init(IEditorSite site, IEditorInput input) throws PartInitException {
    this.setSite(site);
    this.setInput(input);
  }

  @Override
  public boolean isDirty() {
    return false;
  }

  @Override
  public boolean isSaveAsAllowed() {
    return false;
  }

  @Override
  // 在这个方法中设置编辑器中要显示的内容
  public void createPartControl(Composite parent) {
    // 首先初始化一个PatientDAO
    patientDAO = new PatientDAO();

    // 首先创建一个ViewForm对象,它方便于控件的布局
    ViewForm viewForm = new ViewForm(parent, SWT.NONE);
    // 布局
    viewForm.setLayout(new FillLayout());
    // 创建TableViewer
    createTableViewer(viewForm);
    tableViewer.setContentProvider(new PatientInfoTableViewerContentProvider());
    tableViewer.setLabelProvider(new PatientInfoTableViewerLabelProvider());
    tableViewer.setInput(patientDAO.getPatientInfoList());
    tableViewer.setSorter(new PatientInfoSorter());

    // 添加编辑器的工具栏,包括了 修改,删除,刷新 三个按钮
    ToolBar toolBar = new ToolBar(viewForm, SWT.FLAT);
    ToolBarManager toolBarManager = new ToolBarManager(toolBar);
    toolBarManager.add(new AddPatientAction());
    toolBarManager.add(new DeletePatientAction());
    toolBarManager.add(new ModifyPatientAction());
    toolBarManager.add(new RefreshAction());
    toolBarManager.update(true);
    // This brings the underlying widgets up to date with any changes.

    // 设置viewform
    viewForm.setTopLeft(toolBar);
    viewForm.setContent(tableViewer.getControl());
  }

  private void createTableViewer(Composite composite) {
//    tableViewer = new TableViewer(composite, SWT.BORDER | SWT.FULL_SELECTION);
    tableViewer = new TableViewer(composite, SWT.FULL_SELECTION);
    Table table = tableViewer.getTable();
    // 设置显示标题
    table.setHeaderVisible(true);
    // 设置显示表格线
    table.setLinesVisible(true);
    // 设置表格的布局 TableColumnLayout
    //TODO:重点注意下面的布局设置!不能有,它会导致很多问题,例如数组溢出,还有界面放大缩小出现
    //延迟!很多问题!
//    table.setLayout(new TableColumnLayout());
    // 建立一列
    TableColumn tc1 = new TableColumn(table, SWT.LEFT);
    // 设置列标题
    tc1.setText("ID");
    // 设置列宽
    tc1.setWidth(60);
    // 添加排序器(列被点击时触发)
    // 注意:widgetSelected方法的末尾一定要refresh,这样可以保证不用手动刷新!
    // 还有,参数传一个SelectionAdapter就可以了!
    tc1.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        sort = !sort;
        ((PatientInfoSorter) tableViewer.getSorter()).doSort(sort ? -1 : 1);
        tableViewer.refresh();
      }
    });

    TableColumn tc2 = new TableColumn(table, SWT.LEFT);
    tc2.setText("Name");
    tc2.setWidth(100);
    tc2.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        sort = !sort;
        ((PatientInfoSorter) tableViewer.getSorter()).doSort(sort ? -2 : 2);
        tableViewer.refresh();
      }
    });

    TableColumn tc3 = new TableColumn(table, SWT.LEFT);
    tc3.setText("Sex");
    tc3.setWidth(60);
    tc3.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        sort = !sort;
        ((PatientInfoSorter) tableViewer.getSorter()).doSort(sort ? -3 : 3);
        tableViewer.refresh();
      }
    });

    TableColumn tc4 = new TableColumn(table, SWT.LEFT);
    tc4.setText("Age");
    tc4.setWidth(60);
    tc4.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        sort = !sort;
        ((PatientInfoSorter) tableViewer.getSorter()).doSort(sort ? -4 : 4);
        tableViewer.refresh();
      }
    });

    TableColumn tc5 = new TableColumn(table, SWT.LEFT);
    tc5.setText("Phone");
    tc5.setWidth(100);
    tc5.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        sort = !sort;
        ((PatientInfoSorter) tableViewer.getSorter()).doSort(sort ? -5 : 5);
        tableViewer.refresh();
      }
    });

    TableColumn tc6 = new TableColumn(table, SWT.LEFT);
    tc6.setText("Department");
    tc6.setWidth(100);
    tc6.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        sort = !sort;
        ((PatientInfoSorter) tableViewer.getSorter()).doSort(sort ? -6 : 6);
        tableViewer.refresh();
      }
    });

    TableColumn tc7 = new TableColumn(table, SWT.LEFT);
    tc7.setText("SickRoom");
    tc7.setWidth(80);
    tc7.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        sort = !sort;
        ((PatientInfoSorter) tableViewer.getSorter()).doSort(sort ? -7 : 7);
        tableViewer.refresh();
      }
    });

    TableColumn tc8 = new TableColumn(table, SWT.LEFT);
    tc8.setText("SickBed");
    tc8.setWidth(80);
    tc8.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        sort = !sort;
        ((PatientInfoSorter) tableViewer.getSorter()).doSort(sort ? -8 : 8);
        tableViewer.refresh();
      }
    });

    TableColumn tc9 = new TableColumn(table, SWT.LEFT);
    tc9.setText("Address");
    tc9.setWidth(100);
    tc9.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        sort = !sort;
        ((PatientInfoSorter) tableViewer.getSorter()).doSort(sort ? -9 : 9);
        tableViewer.refresh();
      }
    });

    TableColumn tc10 = new TableColumn(table, SWT.LEFT);
    tc10.setText("Login Time");
    tc10.setWidth(100);
    tc10.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        sort = !sort;
        ((PatientInfoSorter) tableViewer.getSorter()).doSort(sort ? -10 : 10);
        tableViewer.refresh();
      }
    });

  }

  @Override
  public void setFocus() {
  }

  // 注意:以下三个操作定义为内部类!
  // 原因是它们需要访问当前类的 TableViewer 对象,所以放在这个类里实现起来很方便!
  class ModifyPatientAction extends Action {
    public ModifyPatientAction() {
      // 设置提示文本
      this.setToolTipText("Modify Patient Information");
      // 设置图标
      this.setImageDescriptor(Activator.getImageDescriptor("/icons/Applications.ico"));
    }
    public void run() {
      IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection();
      Patient patient = (Patient) selection.getFirstElement();
      if (patient == null) {
        return;
      }
      // 调出 修改病人住院信息的dialog
      PatientFactory.setInstance(patient);

      //创建自定义的向导
      AddPatientInfoWizard wizard = new AddPatientInfoWizard();
      wizard.setType(PluginUtil.MODIFY);
      //设置向导中的patient是当前选中的patient
//      wizard.setPatient(patient);//我想避免使用这些get和set
//      PatientFactory.getInstance() = patient;//这样的代码不行!报错:左边不是变量
      //解决:在PatientFactory中添加一个setInstance方法
//      
      //显示向导对话框
      WizardDialog dialog = new WizardDialog(Display.getDefault().getShells()[0], wizard);
      //设置对话框大小
      dialog.setPageSize(-1, 150);//注意:高度要足够的大,否则有些组件显示不出来
      //打开
      dialog.open();  
      //修改完成之后要刷新列表
      tableViewer.setInput(patientDAO.getPatientInfoList());
      tableViewer.refresh();
    }
  }

  class AddPatientAction extends Action {
    public AddPatientAction() {
      // 设置提示文本
      this.setToolTipText("Add Patient Information");
      // 设置图标
      this.setImageDescriptor(Activator.getImageDescriptor("/icons/small/add.gif"));
    }

    public void run() {
      // 调出 创建新的病人住院信息的dialog
      //创建自定义的向导
      AddPatientInfoWizard wizard = new AddPatientInfoWizard();
      wizard.setType(PluginUtil.ADD);
      //注意:每次打开向导页面时都要对PatientFactory的instance进行设置,不然会出现紊乱
//      PatientFactory.setInstance(null);  //不能设置为null,不然后面的操作(判断操作类型,和设置值)
//      PatientFactory.setInstance(new Patient());
      //显示向导对话框
      WizardDialog dialog = new WizardDialog(Display.getDefault().getShells()[0], wizard);
      //设置对话框大小
      dialog.setPageSize(-1, 150);//注意:高度要足够的大
      //打开
      dialog.open();
      //添加完成之后要刷新列表
//      tableViewer.refresh();//这个方法不行!
      //还是得重新取出数据并刷新现实
      tableViewer.setInput(patientDAO.getPatientInfoList());
      tableViewer.refresh();
    }
  }

  class DeletePatientAction extends Action {

    public DeletePatientAction() {
      // 设置提示文本
      this.setToolTipText("Delete Patient Information");
      // 设置图标
      this.setImageDescriptor(Activator.getImageDescriptor("/icons/small/delete.gif"));
    }

    public void run() {
      IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection();
      Patient patient = (Patient) selection.getFirstElement();
      if (patient == null) {
        return;
      }
      if (MessageDialog.openConfirm(null, "Confirm to delete", "Are you sure to delete?")) {
        if (patientDAO.deletePatient(patient)) {
          @SuppressWarnings("unchecked")
          List<Patient> list = (List<Patient>) tableViewer.getInput();
          list.remove(patient);// 这里删除便于刷新时是最新的数据
          tableViewer.remove(patient);// 实时更新
        } else {//删除出错时提示
          MessageDialog.openInformation(null, "Error Information", "Fail to delete the Patient!");
        }
      }
    }

  }

  class RefreshAction extends Action {
    public RefreshAction() {
      // 设置提示文本
      this.setToolTipText("Refresh Patient Information");
      // 设置图标
      this.setImageDescriptor(Activator.getImageDescriptor("/icons/Refresh.ico"));
    }
    public void run() {
      tableViewer.setInput(patientDAO.getPatientInfoList());
      tableViewer.refresh();
    }
  }

}
 
2.编辑器的输入类EditorInput
这个类只是简单的实现IEditorInput接口,同时实现getName和getTooltipText方法
package com.yinger.patientims.editors.editorInput; 

import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IPersistableElement;

public class PatientInfoEditorInput implements IEditorInput {

  @Override
  public Object getAdapter(Class adapter) {
    return null;
  }

  @Override
  public boolean exists() {
    return false;
  }

  @Override
  public ImageDescriptor getImageDescriptor() {
    return null;
  }

  @Override
  public String getName() {
    return "Patient Information Management";
  }

  @Override
  public IPersistableElement getPersistable() {
    return null;
  }

  @Override
  public String getToolTipText() {
    return "Hospital Management/Patient Information Management";
  }

}
 
3.TabelViewer的内容和标签提供器
内容提供器
这里getElements方法写的不是很规范,可以参照上节内容
package com.yinger.patientims.views.viewerProvider; 

import java.util.List;

import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.Viewer;

/**
 * 记住,这里是一个TableViewer的内容提供器,一定要是实现IStructuredContentProvider接口
 * 而不是IContentProvider,IStructuredContentProvider接口中定义了getElements方法,这个
 * 方法是要实现的!将setInput时传入的list参数转换成Object数组
 */

public class PatientInfoTableViewerContentProvider implements IStructuredContentProvider {

  @Override
  public Object[] getElements(Object inputElement) {
    return ((List)inputElement).toArray();
  }

  @Override
  public void dispose() {
  }

  @Override
  public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
  }

}
 
标签提供器
需要注意的是Table有table的特点,实现getColumnText方法,给相应的列提供对应的文本
package com.yinger.patientims.views.viewerProvider; 

import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.swt.graphics.Image;

import com.yinger.patientims.model.Patient;

public class PatientInfoTableViewerLabelProvider implements ITableLabelProvider {

  @Override
  public void addListener(ILabelProviderListener listener) {
  }

  @Override
  public void dispose() {
  }

  @Override
  public boolean isLabelProperty(Object element, String property) {

    return false;
  }

  @Override
  public void removeListener(ILabelProviderListener listener) {
  }

  @Override
  public Image getColumnImage(Object element, int columnIndex) {

    return null;
  }

  @Override//得到列中要显示的文本
  public String getColumnText(Object element, int columnIndex) {
    Patient patient = (Patient) element;
    switch (columnIndex) {//注意:列的索引是从0开始的
    case 0:
      return patient.getId().toString();
    case 1:
      return patient.getName();
    case 2:
      return patient.getSex();
    case 3:
      return patient.getAge()+"";
    case 4:
      return patient.getPhone();
    case 5:
      return patient.getDepartment().getName();
    case 6:
      return patient.getSickroom().getSickRoomNo()+"";
    case 7:
      return patient.getSickbed().getSickBedNo()+"";
    case 8:
      return patient.getAddress();
    case 9:
      return patient.getLogtime().toString();
//    default:
//      break;
    }
    return "";//默认返回空字符串
  }

}
 
整个流程的执行过程与上节类似
 
 
4.还有一个重要的类:排序器,通过这个类可以实现对TableViewer的排序
tableviewer通过调用doSort方法最终就可以调用到compare方法进行排序
package com.yinger.patientims.editors.viewerSorter; 

import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;

import com.yinger.patientims.model.Patient;
/**
 * 表格查看器的排序器
 * 对于给定的列的索引进行排序
 * 
 * 我觉得有一个地方不好,那就是这里的数字!它固定了某一列就是在某列
 * 某一列的排序算法也是!还有就是这个compare方法太长了,过于复杂
 * ->可以在外部自定义一个类,用于设置列索引和排序方法的统一
 * 例如 IDASC=1 IDDSC=-1 
 */

public class PatientInfoSorter extends ViewerSorter {

  private int column;

  public void doSort(int column) {
    this.column = column;
  }

  @Override // 处理排序的方法
  public int compare(Viewer viewer, Object e1, Object e2) {
    Patient patient1 = (Patient) e1;
    Patient patient2 = (Patient) e2;
    switch (column) {
    case 1:
      return patient2.getId().compareTo(patient1.getId());
    case -1:
      return patient1.getId().compareTo(patient2.getId());
    case 2:
      return patient2.getName().compareTo(patient1.getName());
    case -2:
      return patient1.getName().compareTo(patient2.getName());
    case 3:
      return patient2.getSex().compareTo(patient1.getSex());
    case -3:
      return patient1.getSex().compareTo(patient2.getSex());
    case 4:
      return (patient2.getAge() + "").compareTo(patient1.getAge() + "");
    case -4:
      return (patient1.getAge() + "").compareTo(patient2.getAge() + "");
    case 5:
      return patient2.getPhone().compareTo(patient1.getPhone());
    case -5:
      return patient1.getPhone().compareTo(patient2.getPhone());
    case 6:
      return patient2.getDepartment().getName().compareTo(patient1.getDepartment().getName());
    case -6:
      return patient1.getDepartment().getName().compareTo(patient2.getDepartment().getName());
    case 7:
      return (patient2.getSickroom().getSickRoomNo() + "").compareTo(patient1.getSickroom().getSickRoomNo() + "");
    case -7:
      return (patient1.getSickroom().getSickRoomNo() + "").compareTo(patient2.getSickroom().getSickRoomNo() + "");
    case 8:
      return (patient2.getSickbed().getSickBedNo() + "").compareTo(patient1.getSickbed().getSickBedNo() + "");
    case -8:
      return (patient1.getSickbed().getSickBedNo() + "").compareTo(patient2.getSickbed().getSickBedNo() + "");
    case 9:
      return patient2.getAddress().compareTo(patient1.getAddress());
    case -9:
      return patient1.getAddress().compareTo(patient2.getAddress());
    case 10:
      return patient2.getLogtime().compareTo(patient1.getLogtime());
    case -10:
      return patient1.getLogtime().compareTo(patient2.getLogtime());
    default:
      return 0;
    }
  }

}
 
5.其他的没有涉及的内容会在后面的内容中总结到...





原文地址:https://www.cnblogs.com/yinger/p/2255643.html