首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

SWT Display.post() 實戰:模擬鍵盤滑鼠事件實現自動化測試與 RPA 原型

     編輯:Java 相關知識

Display.post() 核心機制

SWT Display.post(Event) 可將事件直接發送至 UI 執行緒事件佇列,繞過作業系統輸入子系統,實現程式化模擬使用者輸入。事件屬性決定模擬行為:type(KeyDown/KeyUp/MouseMove/MouseDown/MouseUp)、keyCode、character、x/y、button 等。

案例一:模擬鍵盤輸入字串

public class KeyboardSimulator {
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        Text text = new Text(shell, SWT.BORDER);
        text.setSize(text.computeSize(150, SWT.DEFAULT));
        shell.pack();
        shell.open();

        new Thread(() -> {
            String input = "Love the method.";
            for (int i = 0; i < input.length(); i++) {
                char ch = input.charAt(i);
                boolean shift = Character.isUpperCase(ch);
                ch = Character.toLowerCase(ch);

                if (shift) postKey(display, SWT.KeyDown, SWT.SHIFT, 0);
                postKey(display, SWT.KeyDown, 0, ch);
                sleep(10);
                postKey(display, SWT.KeyUp, 0, ch);
                sleep(100);
                if (shift) postKey(display, SWT.KeyUp, SWT.SHIFT, 0);
            }
        }).start();

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) display.sleep();
        }
        display.dispose();
    }

    static void postKey(Display display, int type, int keyCode, char character) {
        Event e = new Event();
        e.type = type;
        e.keyCode = keyCode;
        e.character = character;
        display.post(e);
    }
    static void sleep(int ms) { try { Thread.sleep(ms); } catch (InterruptedException ignored) {} }
}

關鍵細節:大寫字元需模擬 Shift 按下 → 字元按下/釋放 → Shift 釋放;字元間加入延遲模擬真人打字節奏。

案例二:模擬滑鼠移動與點擊

public class MouseSimulator {
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        Button button = new Button(shell, SWT.NONE);
        button.setSize(100, 100);
        button.setText("Click");
        shell.pack();
        shell.open();

        button.addListener(SWT.MouseDown, e -> 
            System.out.printf("Mouse Down: button=%d x=%d y=%d%n", e.button, e.x, e.y));

        // 取得 Shell 相對座標 (50,50) 對應的螢幕絕對座標
        Point pt = display.map(shell, null, 50, 50);

        new Thread(() -> {
            sleep(300);
            postMouse(display, SWT.MouseMove, pt.x, pt.y, 0);
            sleep(300);
            postMouse(display, SWT.MouseDown, pt.x, pt.y, 1); // button=1 左鍵
            sleep(300);
            postMouse(display, SWT.MouseUp, pt.x, pt.y, 1);
        }).start();

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) display.sleep();
        }
        display.dispose();
    }

    static void postMouse(Display display, int type, int x, int y, int button) {
        Event e = new Event();
        e.type = type;
        e.x = x; e.y = y; e.button = button;
        display.post(e);
    }
    static void sleep(int ms) { try { Thread.sleep(ms); } catch (InterruptedException ignored) {} }
}

座標轉換關鍵:display.map(control, null, x, y) 將控件相對座標轉為螢幕絕對座標,確保滑鼠事件在正確位置觸發。

應用場景與擴展

場景實現要點
自動化 UI 測試結合驗證點檢查(文字內容、元件狀態),建構關鍵字驅動測試框架
RPA 機器人流程自動化原型針對無 API 的 Legacy 系統,模擬使用者操作完成資料輸入/查詢/匯出
示範/教學錄製回放記錄使用者操作序列(事件+時間戳),回放重現操作流程
無障礙輔助工具語音/眼動追蹤輸入轉換為標準 SWT 事件

注意事項與限制

  • 執行緒安全:所有 UI 操作必須在 UI 執行緒,post() 雖可從背景執行緒呼叫,但事件處理仍在 UI 執行緒
  • 平台差異:按鍵碼(SWT.SHIFT 等)、滑鼠按鈕編號在不同 OS 可能不同,需條件編譯或抽象層
  • 焦點管理:模擬輸入前確保目標控件擁有焦點(control.forceFocus())
  • 安全性:簽名/信任的程式碼才可模擬系統級輸入,非簽名 Applet/Web Start 受限
  • 非完整替代 OS 輸入:無法觸發 OS 層級熱鍵(如 Alt+Tab)、UAC 提權對話框等

進階:封裝為可重用的輸入模擬器

public class InputSimulator {
    private final Display display;
    public InputSimulator(Display display) { this.display = display; }
    
    public void typeString(Control target, String text, int charDelayMs) {
        target.forceFocus();
        new Thread(() -> {
            for (char ch : text.toCharArray()) {
                boolean shift = Character.isUpperCase(ch);
                char lower = Character.toLowerCase(ch);
                if (shift) keyDown(SWT.SHIFT);
                keyPress(lower);
                sleep(charDelayMs);
                keyRelease(lower);
                if (shift) keyUp(SWT.SHIFT);
            }
        }).start();
    }
    // keyDown, keyUp, keyPress, mouseMove, mouseClick 等封裝方法...
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved