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

自定義 JButton 實現鼠標交互視覺反饋

     編輯:Java 相關知識

需求背景

標準 JButton 在不同交互狀態(滑入、按下、釋放、滑出)下缺乏豐富的視覺反饋。本文實現一個 ZButton 組件,通過動態切換 Border 實現:

  • 默認:無邊框
  • 鼠標進入:凸起立體邊框 (RAISED)
  • 鼠標按下:凹陷按下效果 (LOWERED)
  • 鼠標釋放/移出:恢復凸起或無邊框

核心實現代碼

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); // 移出區域 → 恢復默認
        }
    }
}

關鍵設計細節解析

  1. Border 組合優於繼承繪圖:利用 Swing 邊框機制,無需重寫 paintComponent(),輕量且兼容 L&F。
  2. BevelBorder 顏色參數順序:highlightOuter, highlightInner, shadowInner, shadowOuter。RAISED 時外高光/內陰影構成凸起感;LOWERED 相反構成凹陷感。
  3. 啟用狀態檢查:每次切換前判斷 isEnabled(),禁用狀態下保持默認外觀,避免誤導用戶。
  4. mouseReleased 座標判斷:getBounds().contains(e.getX(), e.getY()) 確保拖出按鈕區域釋放時不觸發「懸浮」狀態,符合原生按鈕行為。
  5. MouseAdapter 簡化監聽:僅覆寫所需方法,避免實現完整 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)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved