Java自定义JSlider UI

简介:
JSlider作为Swing中提供的滑标组件, 以图形方式在有界区间内通过移动滑块来选择值,滑块可以显示主刻度标记和次刻度标记。大量应用于如播放器中的音量设定等领域中。

但是JSlider本身提供的UI样式很单调,不足以满足用户的审美需求,往往需要我们自行重构其UI。

下面我给出一个简单的例子。

package org.loon.framework.swing.test;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.RenderingHints;

import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/** *//**
 * <p>
 * Title: LoonFramework
 * </p>
 * <p>
 * Description:
 * </p>
 * <p>
 * Copyright: Copyright (c) 2007
 * </p>
 * <p>
 * Company: LoonFramework
 * </p>
 * 
 * @author chenpeng
 * @email:[email]ceponline@yahoo.com.cn[/email]
 * @version 0.1
 */
public class ExampleSlider extends JPanel ...{
    /** *//**
     * 
     */
    private static final long serialVersionUID = 1L;

    public ExampleSlider() ...{
        // 设定布局器
        super(new BorderLayout());
        // 设定监听器
        ChangeListener listener = new ChangeListener() ...{
            public void stateChanged(ChangeEvent e) ...{
                if (e.getSource() instanceof JSlider) ...{
                    System.out.println("刻度: "
                            + ((JSlider) e.getSource()).getValue());
                }
            }
        };
        // 设定JSlider1
        JSlider s1 = new JSlider(0, 100, 0);
        // 注入自定义ui
        s1.setUI(new MySliderUI());
        // 主刻度
        s1.setMajorTickSpacing(10);
        // 次刻度
        s1.setMinorTickSpacing(5);
        // 设定为显示
        s1.setPaintTicks(true);
        s1.setPaintLabels(true);
        // 监听slider1
        s1.addChangeListener(listener);
        // 设定JSlider2
        JSlider s2 = new JSlider(0, 100, 0);
        // 使用MetalSliderUI为ui
        s2.setUI(new javax.swing.plaf.metal.MetalSliderUI() ...{
            protected void paintHorizontalLabel(Graphics g, int v, Component l) ...{
                JLabel lbl = (JLabel) l;
                lbl.setForeground(Color.green);
                super.paintHorizontalLabel(g, v, lbl);
            }
        });
        
        s2.setForeground(Color.BLUE);
        s2.setMajorTickSpacing(10);
        s2.setMinorTickSpacing(5);
        s2.setPaintTicks(true);
        s2.setPaintLabels(true);
        s2.addChangeListener(listener);

        //使用盒式容器
        Box box = Box.createVerticalBox();
        box.add(Box.createVerticalStrut(5));
        box.add(s1);
        box.add(Box.createVerticalStrut(5));
        box.add(s2);
        box.add(Box.createVerticalGlue());
        add(box, BorderLayout.CENTER);
        add(Box.createHorizontalStrut(5), BorderLayout.WEST);
        add(Box.createHorizontalStrut(5), BorderLayout.EAST);
        //设定窗体大小
        setPreferredSize(new Dimension(240, 100));
    }

    public static void main(String[] args) ...{
        EventQueue.invokeLater(new Runnable() ...{
            public void run() ...{
                createUI();
            }
        });
    }

    public static void createUI() ...{
        JFrame frame = new JFrame("音量刻度设置");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.getContentPane().add(new ExampleSlider());
        frame.setResizable(false);
        frame.pack();
        //居中
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

class MySliderUI extends javax.swing.plaf.metal.MetalSliderUI ...{
    /** *//**
     * 绘制指示物
     */
    public void paintThumb(Graphics g) ...{
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        //填充椭圆框为当前thumb位置
        g2d.fillOval(thumbRect.x, thumbRect.y, thumbRect.width,
                        thumbRect.height);
        //也可以帖图(利用鼠标事件转换image即可体现不同状态)
        //g2d.drawImage(image, thumbRect.x, thumbRect.y, thumbRect.width,thumbRect.height,null);
    }

    /** *//** 
     * 绘制刻度轨迹
     */
    public void paintTrack(Graphics g) ...{
        int cy, cw;
        Rectangle trackBounds = trackRect;
        if (slider.getOrientation() == JSlider.HORIZONTAL) ...{
            Graphics2D g2 = (Graphics2D) g;
            cy = (trackBounds.height / 2) - 2;
            cw = trackBounds.width;

            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            g2.translate(trackBounds.x, trackBounds.y + cy);

            // 背景设为灰色
            g2.setPaint(Color.GRAY);
            g2.fillRect(0, -cy, cw, cy * 2);

            int trackLeft = 0;

            int trackRight = 0;

            trackRight = trackRect.width - 1;

            int middleOfThumb = 0;

            int fillLeft = 0;

            int fillRight = 0;

            //坐标换算
            middleOfThumb = thumbRect.x + (thumbRect.width / 2);
            middleOfThumb -= trackRect.x;

            if (!drawInverted()) ...{
                fillLeft = !slider.isEnabled() ? trackLeft : trackLeft + 1;
                fillRight = middleOfThumb;
            } else ...{
                fillLeft = middleOfThumb;
                fillRight = !slider.isEnabled() ? trackRight - 1
                        : trackRight - 2;
            }
            // 设定渐变
            g2.setPaint(new GradientPaint(0, 0, new Color(0, 100, 100), cw, 0,
                    new Color(0, 255, 100), true));
            g2.fillRect(0, -cy, fillRight - fillLeft, cy * 2);

            g2.setPaint(slider.getBackground());
            Polygon polygon = new Polygon();
            polygon.addPoint(0, cy);
            polygon.addPoint(0, -cy);
            polygon.addPoint(cw, -cy);
            g2.fillPolygon(polygon);
            polygon.reset();

            g2.setPaint(Color.WHITE);
            g2.drawLine(0, cy, cw - 1, cy);

            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_OFF);
            g2.translate(-trackBounds.x, -(trackBounds.y + cy));
        } else ...{
            super.paintTrack(g);
        }
    }
}


效果图:



本文转自 cping 51CTO博客,原文链接:http://blog.51cto.com/cping1982/130163

相关文章
|
10月前
|
Java
在 Java 中捕获和处理自定义异常的代码示例
本文提供了一个 Java 代码示例,展示了如何捕获和处理自定义异常。通过创建自定义异常类并使用 try-catch 语句,可以更灵活地处理程序中的错误情况。
299 1
|
2月前
|
XML 人工智能 Java
java通过自定义TraceId实现简单的链路追踪
本文介绍了如何在Spring Boot项目中通过SLF4J的MDC实现日志上下文traceId追踪。内容涵盖依赖配置、拦截器实现、网关与服务间调用的traceId传递、多线程环境下的上下文同步,以及logback日志格式配置。适用于小型微服务架构的链路追踪,便于排查复杂调用场景中的问题。
106 0
|
10月前
|
Java
在 Java 中,如何自定义`NumberFormatException`异常
在Java中,自定义`NumberFormatException`异常可以通过继承`IllegalArgumentException`类并重写其构造方法来实现。自定义异常类可以添加额外的错误信息或行为,以便更精确地处理特定的数字格式转换错误。
170 1
|
11月前
|
Java
让星星⭐月亮告诉你,自定义定时器和Java自带原生定时器
定时器是一种可以设置多个具有不同执行时间和间隔的任务的工具。本文介绍了定时器的基本概念、如何自定义实现一个定时器,以及Java原生定时器的使用方法,包括定义定时任务接口、实现任务、定义任务处理线程和使用Java的`Timer`与`TimerTask`类来管理和执行定时任务。
343 3
|
7月前
|
人工智能 JavaScript 关系型数据库
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
223 14
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
|
9月前
「Mac畅玩鸿蒙与硬件46」UI互动应用篇23 - 自定义天气预报组件
本篇将带你实现一个自定义天气预报组件。用户可以通过选择不同城市来获取相应的天气信息,页面会显示当前城市的天气图标、温度及天气描述。这一功能适合用于动态展示天气信息的小型应用。
375 38
「Mac畅玩鸿蒙与硬件46」UI互动应用篇23 - 自定义天气预报组件
|
9月前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
8461 5
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
9月前
|
Java
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
258 34
|
10月前
|
UED
「Mac畅玩鸿蒙与硬件31」UI互动应用篇8 - 自定义评分星级组件
本篇将带你实现一个自定义评分星级组件,用户可以通过点击星星进行评分,并实时显示评分结果。为了让界面更具吸引力,我们还将添加一只小猫图片作为评分的背景装饰。
222 6
「Mac畅玩鸿蒙与硬件31」UI互动应用篇8 - 自定义评分星级组件
|
10月前
|
前端开发 开发者
「Mac畅玩鸿蒙与硬件23」鸿蒙UI组件篇13 - 自定义组件的创建与使用
自定义组件可以帮助开发者实现复用性强、逻辑清晰的界面模块。通过自定义组件,鸿蒙应用能够提高代码的可维护性,并简化复杂布局的构建。本篇将介绍如何创建自定义组件,如何向组件传递数据,以及如何在不同页面间复用这些组件。
229 5
「Mac畅玩鸿蒙与硬件23」鸿蒙UI组件篇13 - 自定义组件的创建与使用

热门文章

最新文章