通过自定义 buttonmodel 并同时重写 `ispressed()` 和 `isarmed()` 方法,可使 jbutton 在任意状态下(包括鼠标移出时)持续呈现被按下的视觉效果,适用于 windows classic 等原生 l&f。
在 Swing 中,JButton 的“按下”外观(如凹陷、阴影、颜色变暗等)不仅取决于 isPressed(),还高度依赖于 isArmed() 状态——后者控制按钮是否处于“准备触发”状态(例如鼠标按下但未释放时)。Windows Classic(及多数系统级 Look & Feel)会将 armed && pressed 作为渲染“已按下”样式的默认条件;若仅重写 isPressed(),而 isArmed() 仍返回 false(尤其当鼠标不在按钮上时),UI 委托(UI delegate)将回退到普通/悬停状态,导致视觉效果失效。
✅ 正确做法是:同步覆盖 isPressed() 和 isArmed(),确保二者在业务逻辑需要时均返回 true:
class ForcedPressedButtonModel extends DefaultButtonModel {
private boolean forcedPressed;
public void setForcedPressed(boolean forced) {
boolean old = this.forcedPressed;
this.forcedPressed = forced;
// 通知状态变更,触发重绘
fireStateChanged();
if (old != forced) {
firePropertyChange("pressed", old, forced);
}
}
@Override
public boolean isPressed() {
return super.isPressed() || forcedPressed;
}
@Override
public boolean isArmed() {
return super.isArmed() || forcedPressed;
}
}
使用示例(集成到自定义 JButton 子类中):