標準 JButton 在不同交互狀態(滑入、按下、釋放、滑出)下缺乏豐富的視覺反饋。本文實現一個 ZButton 組件,通過動態切換 Border 實現:
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
public class ZButton extends JButton {
private Border borderOut; // 默認/移出狀態
private Border borderIn; // 滑入狀態 (凸起)
private Border borderPressed; // 按下狀態 (凹陷)
public ZButton() {
init();
}
private void init() {
// 1. 定義三種邊框
borderOut = BorderFactory.createEmptyBorder(); // 也可用 createEmptyBorder(2,2,2,2) 保留間距
borderIn = BorderFactory.createBevelBorder(
BevelBorder.RAISED,
Color.WHITE, Color.WHITE, // 高光色
new Color(148, 145, 140), // 陰影色
new Color(103, 101, 98) // 深陰影色
);
borderPressed = BorderFactory.createBevelBorder(
BevelBorder.LOWERED,
Color.WHITE, Color.WHITE,
new Color(148, 145, 140),
new Color(103, 101, 98)
);
// 2. 初始狀態
setBorder(borderOut);
// 3. 註冊鼠標監聽器 (使用匿名內部類適配器)
addMouseListener(new MouseAdapter() {
@Override public void mouseEntered(MouseEvent e) { onMouseEntered(e); }
@Override public void mouseExited(MouseEvent e) { onMouseExited(e); }
@Override public void mousePressed(MouseEvent e) { onMousePressed(e); }
@Override public void mouseReleased(MouseEvent e){ onMouseReleased(e); }
});
}
// --- 狀態切換邏輯 ---
private void onMouseEntered(MouseEvent e) {
if (isEnabled()) setBorder(borderIn);
}
private void onMouseExited(MouseEvent e) {
setBorder(borderOut);
}
private void onMousePressed(MouseEvent e) {
if (isEnabled()) setBorder(borderPressed);
}
private void onMouseReleased(MouseEvent e) {
if (!isEnabled()) return;
// 判斷釋放點是否仍在按鈕區域內
if (getBounds().contains(e.getX(), e.getY())) {
setBorder(borderIn); // 仍在內部 → 恢復懸浮狀態
} else {
setBorder(borderOut); // 移出區域 → 恢復默認
}
}
}
paintComponent(),輕量且兼容 L&F。highlightOuter, highlightInner, shadowInner, shadowOuter。RAISED 時外高光/內陰影構成凸起感;LOWERED 相反構成凹陷感。isEnabled(),禁用狀態下保持默認外觀,避免誤導用戶。mouseReleased 座標判斷:getBounds().contains(e.getX(), e.getY()) 確保拖出按鈕區域釋放時不觸發「懸浮」狀態,符合原生按鈕行為。MouseListener 接口的樣板代碼。JFrame frame = new JFrame("ZButton Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
ZButton btn1 = new ZButton("正常按鈕");
ZButton btn2 = new ZButton("禁用按鈕");
btn2.setEnabled(false);
frame.add(btn1);
frame.add(btn2);
frame.pack();
frame.setVisible(true);
setBorderOut/In/Pressed(Border) 方法,允許外部自定義邊框風格。RolloverIcon/PressedIcon 實現圖標同步切換。setFocusPainted(true) 配合 UIManager)。