在肥客戶端 Swing 應用中,資料驗證若能完全在本地端完成,不僅提升回應速度,更支援離線操作。本文介紹一個通用驗證模組,結合 Hibernate Validator(註解式驗證規則)、Beans Binding (JSR 295)(屬性同步)與 JXLayer(UI 裝飾),讓開發者幾乎無需撰寫驗證程式碼,即可在文字欄位即時顯示錯誤圖示與提示。
模組包含三個關鍵類別:
AbstractLayerUI<JTextComponent>,在 paintLayer 中呼叫 Hibernate Validator 驗證指定 Bean 屬性,若失敗則繪製錯誤圖示並設定 ToolTip。createTextField 將 JTextField 與 Bean 屬性雙向綁定,並包裝進 JXLayer 套用驗證 UI。@Entity
public class Country extends AbstractBean {
@NotEmpty
public String getName() { ... }
@NotEmpty @Length(min=2, max=2, message="Code length must be 2")
public String getCode() { ... }
}
繼承 SwingX 的 AbstractBean 即可自動支援 PropertyChangeEvent,搭配 Beans Binding 的 ELProperty 監聽屬性變更。
public class HibernateValidationUI extends AbstractLayerUI<JTextComponent> {
private final ClassValidator validator;
private final ELProperty elProperty;
// 建構子注入目標物件與屬性名稱
// installUI/uninstallUI 註冊/移除 PropertyStateListener
// paintLayer 中驗證並繪製圖示與 ToolTip
// isValid() 供外部檢查
}
屬性變更觸發 setDirty(true) 導致重繪,驗證邏輯集中於 paintLayer,雖然在繪製時修改 ToolTip 略違反 Swing 單執行緒規則,但實測穩定;後續可優化移至事件處理。
public static JXLayer<JTextComponent> createTextField(
BindingGroup bg, Object source, String prop) {
JTextField field = new JTextField();
AutoBinding binding = Bindings.createAutoBinding(READ_WRITE,
source, ELProperty.create("${" + prop + "}"),
field, BeanProperty.create("text"));
bg.addBinding(binding);
bg.bind();
return new JXLayer<>(field, new HibernateValidationUI(source, prop));
}
使用 MigLayout 建立簡單視窗,兩欄位分別綁定 Country.code 與 Country.name。啟動後,欄位為空即顯示錯誤圖示與訊息;輸入符合規則的資料(代碼兩碼、名稱非空)圖示立即消失。開發者僅需在 POJO 加上註解,呼叫 createTextField 即完成驗證整合。