新公司做的是桌面應用程式, 與之前一直在做的web頁面 ,相差甚大 。
這篇文章是寫於2022年10月底,這時在新公司已經入職了快三月。寫作目的是:國內對於eclipse外掛開發相關的檔案是少之又少,這三個月我們小組翻遍了國外檔案,勉強將軟體拼湊出並release出測試版本,為了方便同行以及自我學習,所以想把這幾個月學到的eclipse rcp外掛相關知識寫下來。
Wizard 一般用於嚮導式對話方塊 ,eclipse的新建專案就是一個典型的wizard 。wizard一般由幾個wizard page 組成 ,通過按鈕控制 上一頁下一頁完成取消 。
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();
}
}
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方法來設定
wizardpage新增好後,需要新建一個wizard類來管理它們 。
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按鈕是否可以點選,
@Override
public boolean canFinish() {
if (this.getContainer().getCurrentPage() instanceof FilePreprocessingWizardPage) // FilePreprocessingWizardPage為最後一個頁面
return true;
else
return false;
}
重寫getNextPage()方法, 下一頁
wizardDialog 一般用於管理嚮導頁的按鈕,如果你想將原有的next/finish/cancel等按鈕重寫,就需要新建這個類。
下面是我專案中遇到的程式碼,需求是:最後一個頁不再顯示next按鈕,而是改為start,並執行相關功能。
第一頁finish不可點 (這個由wizard類的canfinish方法控制):
第二頁finish可以點、next 變為start
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按鈕復原
一般寫在一個按鈕監聽中 , 或者選單功能裡 。
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");
}
}
});
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來設定向導的圖示
效果:
你的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);
}
二、未完待續。。。