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

GEF 入門系列(十二):自定義 Request 實現節點顏色動態變更

     編輯:Java 相關知識

背景與需求

GEF 中 Request 承載 Tool 將滑鼠事件轉換為 EditPart 可識別的請求。內建請求類型 (CreateRequest、SelectionRequest 等) 滿足常規需求,但特定業務 (如「油漆桶」工具點擊節點變色) 需自定義 Request。

需求:調色板新增三個工具,分別將選中節點背景色設為紅/綠/藍。

運行效果演示

實現步驟完整指南

1. 擴展模型 Node 增加 color 屬性

public class Node {
    final public static String PROP_COLOR = "COLOR";
    protected RGB color = new RGB(255, 255, 255);  // 默認白色

    public RGB getColor() { return color; }
    public void setColor(RGB color) {
        if (this.color.equals(color)) return;
        this.color = color;
        firePropertyChange(PROP_COLOR, null, color);  // 發送屬性變更通知
    }
}

2. 更新 NodePart 響應模型變化並刷新視圖

public void propertyChange(PropertyChangeEvent evt) {
    if (evt.getPropertyName().equals(Node.PROP_COLOR))
        refreshVisuals();
}

protected void refreshVisuals() {
    ((NodeFigure) getFigure()).setBackgroundColor(new Color(null, node.getColor()));
    // 實際項目中 Color 需緩存,避免系統資源耗盡
}

3. 定義自定義 Request:ChangeColorRequest

public class ChangeColorRequest extends Request {
    final static public String REQ_CHANGE_COLOR = "REQ_CHANGE_COLOR";
    private Node node;
    private RGB color;

    public ChangeColorRequest(Node node, RGB color) {
        super();
        this.node = node;
        this.color = color;
        setType(REQ_CHANGE_COLOR);  // 關鍵:EditPolicy 憑 type 判斷是否處理
    }
    // getter/setter 略
}

Request 本質是數據傳輸對象 (DTO),攜帶「目標節點」與「目標顏色」。

4. 創建對應 Tool:ChangeColorTool

public class ChangeColorTool extends SelectionTool {
    private RGB color;
    public ChangeColorTool(RGB color) { this.color = color; }

    @Override
    protected boolean handleButtonDown(int button) {
        EditPart editPart = getTargetEditPart();
        if (editPart instanceof NodePart) {
            NodePart nodePart = (NodePart) editPart;
            Node node = (Node) nodePart.getModel();

            ChangeColorRequest request = new ChangeColorRequest(node, color);
            Command command = editPart.getCommand(request);  // 從 EditPart 獲取命令
            getDomain().getCommandStack().execute(command);  // 執行命令
            return true;
        }
        return false;
    }
}

繼承 SelectionTool 復用選中邏輯,覆寫 handleButtonDown 構建 Request → 獲取 Command → 執行。

5. 封裝 ToolEntry 加入調色板:ChangeColorToolEntry

public class ChangeColorToolEntry extends ToolEntry {
    private RGB color;
    public ChangeColorToolEntry(RGB color, String label, String desc, 
                                ImageDescriptor iconSmall, ImageDescriptor iconLarge) {
        super(label, desc, iconSmall, iconLarge);
        this.color = color;
    }
    @Override
    public Tool createTool() {
        ChangeColorTool tool = new ChangeColorTool(color);
        tool.setUnloadWhenFinished(false);  // 執行後是否切回選擇工具
        tool.setDefaultCursor(SharedCursors.CROSS);
        return tool;
    }
}

在 PaletteFactory.createColorDrawer() 中創建三個實例 (紅/綠/藍) 加入調色板。

6. 實現 Command:ChangeColorCommand

public class ChangeColorCommand extends Command {
    private Node node;
    private RGB color;
    private RGB oldColor;

    public ChangeColorCommand(Node node, RGB color) { ... }

    @Override
    public void execute() {
        oldColor = node.getColor();
        node.setColor(color);
    }
    @Override
    public void undo() {
        node.setColor(oldColor);
    }
}

支持 Undo/Redo,保存舊顏色。

7. 實現 EditPolicy:ChangeColorEditPolicy

public class ChangeColorEditPolicy extends AbstractEditPolicy {
    final static public String CHANGE_COLOR_ROLE = "CHANGE_COLOR_ROLE";

    @Override
    public Command getCommand(Request request) {
        if (request.getType().equals(ChangeColorRequest.REQ_CHANGE_COLOR)) {
            ChangeColorRequest req = (ChangeColorRequest) request;
            return new ChangeColorCommand(req.getNode(), req.getColor());
        }
        return null;
    }
}

根據 Request Type 分發,創建對應 Command。定義獨特 Role 字符串避免覆蓋其他 Policy。

8. 在 NodePart 安裝 EditPolicy

protected void createEditPolicies() {
    installEditPolicy(ChangeColorEditPolicy.CHANGE_COLOR_ROLE, 
                      new ChangeColorEditPolicy());
}

類創建/修改清單

類型名稱
新建ChangeColorRequest, ChangeColorTool, ChangeColorToolEntry, ChangeColorCommand, ChangeColorEditPolicy
修改Node, NodePart, PaletteFactory

建議按功能包組織:com.example.request、com.example.tool、com.example.command、com.example.policy。

核心流程圖解

用戶點擊畫布
    ↓
ChangeColorTool.handleButtonDown()
    ↓
構建 ChangeColorRequest(節點, 顏色)
    ↓
EditPart.getCommand(request)
    ↓
ChangeColorEditPolicy.getCommand() → 返回 ChangeColorCommand
    ↓
CommandStack.execute(command)
    ↓
Command.execute() → Node.setColor() → 觸發 PropertyChange
    ↓
NodePart.propertyChange() → refreshVisuals() → Figure 重繪
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved