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

Java JSlider 滑桿控制動畫播放速度完整實作:模型-視圖分離與執行緒安全設計

     編輯:Java 相關知識

構建一個以 JSlider 控制 GIF 動畫播放幀率的 Swing 應用,展示滑桿模型配置、事件監聽、Timer 驅動動畫、視窗圖示化暫停/還原、圖片延遲載入與邊界處理,完整示範模型-視圖-控制器分離與執行緒安全設計。

核心類別:SliderDemo


public class SliderDemo extends JPanel implements ActionListener, WindowListener, ChangeListener {
    // 滑桿參數常數
    static final int FPS_MIN = 0, FPS_MAX = 30, FPS_INIT = 15;
    int frameNumber = 0, NUM_FRAMES = 14;
    ImageIcon[] images = new ImageIcon[NUM_FRAMES];
    int delay; Timer timer; boolean frozen = false;
    JLabel picture;
    public SliderDemo() {
        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
        delay = 1000 / FPS_INIT;
        // UI 構建
        JLabel sliderLabel = new JLabel("調整滑桿改變播放速度!", JLabel.CENTER);
        sliderLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
        JSlider fpsSlider = new JSlider(JSlider.HORIZONTAL, FPS_MIN, FPS_MAX, FPS_INIT);
        fpsSlider.addChangeListener(this);
        fpsSlider.setMajorTickSpacing(10);
        fpsSlider.setMinorTickSpacing(1);
        fpsSlider.setPaintTicks(true);
        fpsSlider.setPaintLabels(true);
        fpsSlider.setBorder(BorderFactory.createEmptyBorder(0,0,10,0));
        picture = new JLabel();
        picture.setHorizontalAlignment(JLabel.CENTER);
        picture.setAlignmentX(Component.CENTER_ALIGNMENT);
        picture.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLoweredBevelBorder(),
            BorderFactory.createEmptyBorder(10,10,10,10)));
        updatePicture(0);
        add(sliderLabel); add(fpsSlider); add(picture);
        setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
        // Timer 驅動動畫
        timer = new Timer(delay, this);
        timer.setInitialDelay(delay * 7);
        timer.setCoalesce(true);
    }
    // 滑桿事件處理
    public void stateChanged(ChangeEvent e) {
        JSlider source = (JSlider)e.getSource();
        if (!source.getValueIsAdjusting()) { // 僅在釋放滑桿時處理
            int fps = source.getValue();
            if (fps == 0) { if (!frozen) stopAnimation(); }
            else {
                delay = 1000 / fps;
                timer.setDelay(delay);
                timer.setInitialDelay(delay * 10);
                if (frozen) startAnimation();
            }
        }
    }
    // 動畫控制
    public void startAnimation() { timer.start(); frozen = false; }
    public void stopAnimation() { timer.stop(); frozen = true; }
    // Timer 事件:切換幀
    public void actionPerformed(ActionEvent e) {
        frameNumber = (frameNumber + 1) % NUM_FRAMES;
        updatePicture(frameNumber);
        if (frameNumber == 0 || frameNumber == NUM_FRAMES/2 - 1) timer.restart();
    }
    // 延遲載入圖片
    protected void updatePicture(int frameNum) {
        if (images[frameNum] == null)
            images[frameNum] = createImageIcon("images/doggy/T" + frameNum + ".gif");
        picture.setIcon(images[frameNum] != null ? images[frameNum] : null);
        if (images[frameNum] == null) picture.setText("Image #" + frameNum + " not found");
    }
    protected static ImageIcon createImageIcon(String path) {
        java.net.URL imgURL = SliderDemo.class.getResource(path);
        return imgURL != null ? new ImageIcon(imgURL) : null;
    }
    // 視窗事件:最小化暫停,還原繼續
    public void windowIconified(WindowEvent e) { stopAnimation(); }
    public void windowDeiconified(WindowEvent e) { startAnimation(); }
    // ... 其他 WindowListener 方法留空 ...
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Slider Demo");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setContentPane(new SliderDemo());
            frame.pack();
            frame.setVisible(true);
        });
    }
}

關鍵設計亮點

設計點實作方式效益
滑桿模型配置setMajorTickSpacing(10), setPaintTicks(true), setPaintLabels(true)直觀視覺回饋
事件去抖動!source.getValueIsAdjusting() 僅釋放時處理避免拖曳時頻繁調整 Timer 造成卡頓
FPS=0 特殊處理停止動畫而非設定無限延遲語義清晰,節省資源
圖片延遲載入首次顯示時才 createImageIcon()啟動快、記憶體友善
視窗狀態聯動WindowListener 最小化暫停、還原繼續符合使用者預期,省電
Timer 合併觸發setCoalesce(true) 合併延遲觸發避免系統忙碌時堆疊事件

進階擴展建議

  1. 雙向綁定:動畫播放時同步更新滑桿位置(需區分程式設值 vs 用戶操作)。
  2. 自訂滑桿 UI:繼承 BasicSliderUI 繪製漸層軌道、動態刻度。
  3. 多動畫併發:每個動畫獨立 Timer,滑桿控制全域倍率。
  4. 鍵盤無障礙:左右鍵微調、Home/End 跳至極值。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved