Eclipse插件RCP桌面应用开发的点点滴滴

Eclipse插件开发的点点滴滴

新公司做的是桌面应用程序, 与之前一直在做的web页面 ,相差甚大 。
这篇文章是写于2022年10月底,这时在新公司已经入职了快三月。写作目的是:国内对于eclipse插件开发相关的文档是少之又少,这三个月我们小组翻遍了国外文档,勉强将软件拼凑出并release出测试版本,为了方便同行以及自我学习,所以想把这几个月学到的eclipse rcp插件相关知识写下来。

一、 Wizard部分

Wizard 一般用于向导式对话框 ,eclipse的新建项目就是一个典型的wizard 。wizard一般由几个wizard page 组成 ,通过按钮控制 上一页下一页完成取消 。
Eclipse插件RCP桌面应用开发的点点滴滴

1.wizardpages

wizardpage1
package de.vogella.rcp.intro.wizards.wizard;  import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text;  public class MyPageOne extends WizardPage {     private Text text1;     private Composite container;      public MyPageOne() {         super("First Page");         setTitle("First Page");         setDescription("Fake Wizard: First page");     }      @Override     public void createControl(Composite parent) {         container = new Composite(parent, SWT.NONE);         GridLayout layout = new GridLayout();         container.setLayout(layout);         layout.numColumns = 2;         Label label1 = new Label(container, SWT.NONE);         label1.setText("Put a value here.");          text1 = new Text(container, SWT.BORDER | SWT.SINGLE);         text1.setText("");         text1.addKeyListener(new KeyListener() {              @Override             public void keyPressed(KeyEvent e) {             }              @Override             public void keyReleased(KeyEvent e) {                 if (!text1.getText().isEmpty()) {                     setPageComplete(true);                  }             }          });         GridData gd = new GridData(GridData.FILL_HORIZONTAL);         text1.setLayoutData(gd);         // required to avoid an error in the system         setControl(container);         setPageComplete(false);      }      public String getText1() {         return text1.getText();     } } 
wizardpage2
package de.vogella.rcp.intro.wizards.wizard;  import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text;  public class MyPageTwo extends WizardPage {     private Text text1;     private Composite container;      public MyPageTwo() {         super("Second Page");         setTitle("Second Page");         setDescription("Now this is the second page");         setControl(text1);     }      @Override     public void createControl(Composite parent) {         container = new Composite(parent, SWT.NONE);         GridLayout layout = new GridLayout();         container.setLayout(layout);         layout.numColumns = 2;         Label label1 = new Label(container, SWT.NONE);         label1.setText("Say hello to Fred");          text1 = new Text(container, SWT.BORDER | SWT.SINGLE);         text1.setText("");         text1.addKeyListener(new KeyListener() {              @Override             public void keyPressed(KeyEvent e) {                 // TODO Auto-generated method stub             }              @Override             public void keyReleased(KeyEvent e) {                 if (!text1.getText().isEmpty()) {                     setPageComplete(true);                 }             }          });         GridData gd = new GridData(GridData.FILL_HORIZONTAL);         text1.setLayoutData(gd);         Label labelCheck = new Label(container, SWT.NONE);         labelCheck.setText("This is a check");         Button check = new Button(container, SWT.CHECK);         check.setSelection(true);         // required to avoid an error in the system         setControl(container);         setPageComplete(false);     }      public String getText1() {         return text1.getText();     } } 

①自定义wizardpage主要是继承JFACE 的 WizardPage ,并重写 createControl方法。 在createControl方法中,可以对你的向导页面组件进行布局、添加监听等动作。
②对于当前页面的标题、描述等信息,可以在构造函数中通过setTitle 和 setDescription方法来设置

2.wizard

wizardpage添加好后,需要新建一个wizard类来管理它们 。

MyWizard
package de.vogella.rcp.intro.wizards.wizard;  import org.eclipse.jface.wizard.Wizard;   public class MyWizard extends Wizard {      protected MyPageOne one;     protected MyPageTwo two;      public MyWizard() {         super();         setNeedsProgressMonitor(true);     }      @Override     public String getWindowTitle() {         return "Export My Data";     }      @Override     public void addPages() {         one = new MyPageOne();         two = new MyPageTwo();         addPage(one);         addPage(two);     }      @Override     public boolean performFinish() {         // Print the result to the console         System.out.println(one.getText1());         System.out.println(two.getText1());          return true;     } } 

① 自定义wizard继承 JFACE的 Wizard类 。
重写addPage()方法,为向导添加向导页。
重写performFinish()方法,指定点击finish按钮后完成的动作.
重写canFinish()方法,FINISH按钮是否可以点击,

可以通过这个方法,来判断是否是最后一页,最后一页才可以点FINISH按钮
@Override 	public boolean canFinish() { 		if (this.getContainer().getCurrentPage() instanceof FilePreprocessingWizardPage) // FilePreprocessingWizardPage为最后一个页面 			return true; 		else 			return false; 	} 

重写getNextPage()方法, 下一页

3.WizardDialog

wizardDialog 一般用于管理向导页的按钮,如果你想将原有的next/finish/cancel等按钮重写,就需要新建这个类。
下面是我项目中遇到的代码,需求是:最后一个页不再显示next按钮,而是改为start,并执行相关功能。
第一页finish不可点 (这个由wizard类的canfinish方法控制):
Eclipse插件RCP桌面应用开发的点点滴滴
第二页finish可以点、next 变为start
Eclipse插件RCP桌面应用开发的点点滴滴

点击查看代码
  import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.wizard.IWizard; import org.eclipse.jface.wizard.IWizardPage; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Button;  public class InputFileWizardDialog extends WizardDialog { 	private Button startBtn; 	private Button nextButton;  	public InputFileWizardDialog(Shell parentShell, IWizard newWizard) { 		super(parentShell, newWizard); 	}  	@Override 	protected void buttonPressed(int buttonId) { 		switch (buttonId) { 		case IDialogConstants.HELP_ID: { 			helpPressed(); 			break; 		} 		case IDialogConstants.BACK_ID: { 			backPressed(); 			break; 		} 		case IDialogConstants.NEXT_ID: { 			nextPressed(); 			break; 		} 		case IDialogConstants.FINISH_ID: { 			finishPressed(); 			break; 		} 		} 	}  	@Override 	protected void nextPressed() { 		IWizardPage currentPage = getCurrentPage(); 		IWizardPage nextPage = currentPage.getNextPage(); 		if (currentPage instanceof FilePreprocessingWizardPage) { 			((FilePreprocessingWizardPage) currentPage).startButtonClick(); 		} 		if (nextPage instanceof FilePreprocessingWizardPage) { // last page 			if (nextPage.getControl() != null) 				nextPage.dispose(); 			showPage(nextPage); 			startBtn = this.getButton(IDialogConstants.NEXT_ID); 			startBtn.setText("Start"); 			startBtn.setEnabled(true); 		} 	}  	/** 	 * The Back button has been pressed. 	 */ 	@Override 	protected void backPressed() { 		IWizardPage page = getCurrentPage().getPreviousPage(); 		super.backPressed(); 		if (!(page instanceof FilePreprocessingWizardPage)) { // last page 			nextButton = this.getButton(IDialogConstants.NEXT_ID); 			nextButton.setText(IDialogConstants.NEXT_LABEL); 		} 	} }  

①buttonPressed()方法监听按钮被点击后执行的方法
②nextPressed()方法,下一页 。 这里判断当前页面的下一页是否为最后一页,如果是则通过setTest方法将按钮改为start按钮,并将其设为可用状态 。 如果当前页面已经是最后一页,则执行在最后一页中定义的startbuttonclick方法 。
③ backPressed()方法,点上一页时,将上个方法中被改变的next按钮复原

4.最后,打开一个wizard

一般写在一个按钮监听中 , 或者菜单功能里 。

按钮监听:
Button button = new Button(parent, SWT.PUSH); button.setText("Open Wizard"); button.addSelectionListener(new SelectionAdapter() {     @Override     public void widgetSelected(SelectionEvent e) {         WizardDialog wizardDialog = new WizardDialog(parent.getShell(),             new MyWizard());         if (wizardDialog.open() == Window.OK) {             System.out.println("Ok pressed");         } else {             System.out.println("Cancel pressed");         }     } }); 
菜单功能,这里用的是E4的handle机制
 import org.eclipse.e4.core.di.annotations.Execute; import org.eclipse.ui.IWorkbench; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.widgets.Shell;  public class InputFilesAssistantHandle { 	@Execute 	public void execute(IWorkbench iWorkbench, Shell shell) { 		WizardDialog wizardDialog = new WizardDialog(shell, new MyWizard()); 		WizardDialog.setDefaultImage(ApplicationContext.getImage(Constant.PLUGIN_ID, "icons/module/cn_icon.png")); 		if (wizardDialog.open() == Window.OK) { 		} else { 		} 	} }  

①可以通过setDefaultImage来设置向导的图标

效果:
Eclipse插件RCP桌面应用开发的点点滴滴

进阶:

① wizardpage 的动态刷新 、 联动

你的wizardpages 初始化是在wizard打开的时候, 而不是点next或back时再初始化 。 所以,如果你想将两个wizardpage进行联动,通过上面的代码难以实现 。
阅读源码会发现,

源码
     private void updateForPage(IWizardPage page) {         // ensure this page belongs to the current wizard         if (wizard != page.getWizard()) {           setWizard(page.getWizard());          }         // ensure that page control has been created         // (this allows lazy page control creation)         if (page.getControl() == null) {             page.createControl(pageContainer);             // the page is responsible for ensuring the created control is accessable             // via getControl.             Assert.isNotNull(page.getControl());             // ensure the dialog is large enough for this page             updateSize(page);         }         // make the new page visible         IWizardPage oldPage = currentPage;         currentPage = page;         currentPage.setVisible(true);         if (oldPage != null) {           oldPage.setVisible(false);          }         // update the dialog controls         update();        }       

点next或back按钮后,页面之所以不会再初始化,是因为他会有个判断page.getControl() == null,因此我们只要将想办法在调转到某个WizardPage的时候,将其control设置为null就可以了.
所以,在点next 或 back 按钮时 ,可以加如下代码:
// 对参数页必须重绘
IWizardPage page = getNextPage();
if (page.getControl() != null)
page.dispose();

并在你想要刷新的页面中重写dispose方法:
public void dispose() {
super.dispose();

setControl(null);
}

二、未完待续。。。

发表评论

评论已关闭。

相关文章

当前内容话题