Eclipse插件RCP桌面應用開發的點點滴滴

来源:https://www.cnblogs.com/cnblogs-ade/archive/2022/10/24/16822273.html
-Advertisement-
Play Games

Eclipse插件開發的點點滴滴 新公司做的是桌面應用程式, 與之前一直在做的web頁面 ,相差甚大 。 這篇文章是寫於2022年10月底,這時在新公司已經入職了快三月。寫作目的是:國內對於eclipse插件開發相關的文檔是少之又少,這三個月我們小組翻遍了國外文檔,勉強將軟體拼湊出並release出 ...


Eclipse插件開發的點點滴滴

新公司做的是桌面應用程式, 與之前一直在做的web頁面 ,相差甚大 。
這篇文章是寫於2022年10月底,這時在新公司已經入職了快三月。寫作目的是:國內對於eclipse插件開發相關的文檔是少之又少,這三個月我們小組翻遍了國外文檔,勉強將軟體拼湊出並release出測試版本,為了方便同行以及自我學習,所以想把這幾個月學到的eclipse rcp插件相關知識寫下來。

一、 Wizard部分

Wizard 一般用於嚮導式對話框 ,eclipse的新建項目就是一個典型的wizard 。wizard一般由幾個wizard page 組成 ,通過按鈕控制 上一頁下一頁完成取消 。
image

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方法控制):
image
第二頁finish可以點、next 變為start
image

點擊查看代碼


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來設置嚮導的圖標

效果:
image

進階:

① 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);
}

二、未完待續。。。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • python版本:python 3.9 mutagen版本:1.46.0 mutagen是一個處理音頻元數據的python模塊,支持多種音頻格式,是一個純粹的python庫,僅依賴python標準庫,可在Python 3.7及以上版本運行,支持Linux、Windows 和 macOS系統。 git ...
  • 正則表達式03 5.6正則表達式三個常用類 java.util.regex 包主要包括以下三個類:Pattern類、Matcher類和PatternSyntaxException類 Pattern類 Pattern對象是一個正則表達式對象。Pattern類沒有公共構造方法,要創建一個Pattern對 ...
  • Alwaysblock1 組合邏輯always塊的使用,註意這裡的wire和reg綜合出來的結果是一樣的,這裡只是verilog語法導致二者聲明不一樣。 // synthesis verilog_input_version verilog_2001 module top_module( input ...
  • 目錄 一.OpenGL 反色 1.IOS Object-C 版本 2.Windows OpenGL ES 版本 3.Windows OpenGL 版本 二.OpenGL 反色 GLSL Shader 三.猜你喜歡 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> Op ...
  • 編程教材 《R語言實戰·第2版》Robert I. Kabacoff 課程教材《商務與經濟統計·原書第13版》 (安德森) P143、案例 Go Bananas #1 生產中斷的概率 c <- pbinom(4, 25, .08) # 4 是預設 P(x <= 4) answer1 <- 1 - c ...
  • Java 一直是一種面向對象的編程語言。這意味著 Java 編程中的一切都圍繞著對象(為了簡單起見,除了一些基本類型)。我們不僅有 Java 中的函數,它們還是 Class 的一部分,我們需要使用 class/object 來調用任何函數。 函數式介面 當我們研究一些其他的編程語言時,比如C++,J ...
  • 在筆者前面有一篇文章`《驅動開發:斷鏈隱藏驅動程式自身》`通過摘除驅動的鏈表實現了斷鏈隱藏自身的目的,但此方法恢復時會觸發PG會藍屏,偶然間在網上找到了一個作者介紹的一種方法,覺得有必要詳細分析一下他是如何實現的進程隱藏的,總體來說作者的思路是最終尋找到`MiProcessLoaderEntry`的... ...
  • 前言 一. 數據來源分析 明確需求, 我們採集網上什麼數據內容, 在什麼地方 分析我們想要高清原圖在什麼地方有 瀏覽器自帶工具: 開發者工具 F12 滑鼠右鍵點擊 插件 選擇 network 刷新網頁 點擊選擇 Img 可以直接找到圖片地址 通過搜索分析, 可以知道, 我們想要圖片原圖url 就在 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...