`

打造绚丽的Swing slider

    博客分类:
  • java
阅读更多

我们大多数的时候,都在抱怨Swing界面简陋,其实说这话的大多数和我一样都是一个Swing的新手,或者说是一个桌面开发的新手,诸如瑞星那样的应用其实可见也没几个是原生态的Windows的桌面控件,先不谈我们可以选择look&feel来改变我们的主题,甚至实现office2007的那样的效果,Swing本身的MVC模式就为我们提供了无限的可能;在上一篇文章中我们实现了按钮的改头换面,其实那种方式是一种强耦合的界面改换,在本文中我们将利用Swing本身所提倡的方式来实现控件的美化;


--------------------------------------------------------------------------------

Swing的千千静听

 

下图是一个java Swing版本的千千静听风格的播放器,在里面我们已经见不到Swing的影子(如图一);

图一.绚丽的Swing播放器

 


--------------------------------------------------------------------------------

打造绚丽的Slider

首先我们必须在基础的BasicUI上扩展出自己的UI界面,代码清单如下:

view plaincopy to clipboardprint?
/* 
 * To change this template, choose Tools | Templates 
 * and open the template in the editor. 
 */ 
package com.hadeslee.yoyoplayer.util;  
 
import java.awt.Color;  
import java.awt.Dimension;  
import java.awt.Graphics;  
import java.awt.Image;  
import javax.swing.JSlider;  
import javax.swing.plaf.basic.BasicSliderUI;  
 
/** 
 * 
 * @author hadeslee 
 */ 
public class YOYOSliderUI extends BasicSliderUI {  
 
      
   //以下代码分别表示用于指示的图标的三种状态的图片  
   private Image thumbImage = null;//普通按的图片  
    private Image thumbOverImage;//鼠标在上面的图片  
    private Image thumbPressedImage = null;//按下面的图片  
 
    //分别是已经激活了的bar的背景和没有激活的bar的背景  
    private Image backgroundImage = null;//普通背景图片  
    private Image activeBackImage;//激活的背景图片  
 
    //一些设置变量  
    private JSlider parentSlider = null;  
    private Dimension thumbDim = null;  
    private int newThumbHeight = -1;  
    private int thumbXOffset = 0;  
    private int thumbYOffset = 0;  
    private boolean hideThumb = false;  
 
    public YOYOSliderUI(JSlider slider) {  
        super(slider);  
        //保存了solider的引用;  
        parentSlider = slider;  
    }  
 
    public void setThumbImage(Image img) {  
        thumbImage = img;  
        thumbDim = new Dimension(thumbImage.getWidth(null), thumbImage.getHeight(null));  
    }  
 
    public void setThumbPressedImage(Image img) {  
        thumbPressedImage = img;  
    }  
 
    public void setActiveBackImage(Image activeBackImage) {  
        this.activeBackImage = activeBackImage;  
    }  
 
    public void setThumbOverImage(Image thumbOverImage) {  
        this.thumbOverImage = thumbOverImage;  
    }  
 
    protected Dimension getThumbSize() {  
        return thumbDim;  
    }  
 
    public void forceThumbHeight(int h) {  
        newThumbHeight = h;  
    }  
 
    public void setThumbXOffset(int x) {  
        thumbXOffset = x;  
    }  
 
    public void setThumbYOffset(int y) {  
        thumbYOffset = y;  
    }  
 
    public void setHideThumb(boolean hide) {  
        hideThumb = hide;  
    }  
 
    public void setBackgroundImages(Image img) {  
        backgroundImage = img;  
    }  
 
    public void paintFocus(Graphics g) {  
    }  
      
    //在这里画出bar上面的指针  
    public void paintThumb(Graphics g) {  
    //如果隐藏指针,则不用画了  
        if (hideThumb == true) {  
            return;  
        }  
        Image img = thumbImage;  
        if (img != null) {  
            if (thumbPressedImage != null) {  
                //判断出正在拖动中,按钮现实获取焦点的显示状态  
                if (parentSlider.getValueIsAdjusting()) {  
                    img = thumbPressedImage;  
                }  
            }  
            if (newThumbHeight >= 0) {  
                //根据solider的引用判断出bar的方向;  
                if (parentSlider.getOrientation() == JSlider.HORIZONTAL) {  
                //thumbRect.x可以得到当前的指针被鼠标拖放在哪个位置,由基类实现  
                  //thumnXoffset则是一个浮动值,你可以用来微调  
                 //(parentSlider.getHeight() - img.getHeight(slider)) / 2是由  
                 //y+img.getHeight/2=parentSlider.getHeight/2的公式而来,使得bar和指针的中线重合  
                 //上面动态的确定了指针的位置,每次指针移动都会重新刷新页面  
                 //width和height是指针img本身的高度和宽度就可以了  
                    g.drawImage(img, thumbRect.x + thumbXOffset, (parentSlider.getHeight() - img.getHeight(slider)) / 2, img.getWidth(null), newThumbHeight, null);  
                } else {  
                    g.drawImage(img, (parentSlider.getWidth() - img.getWidth(slider)) / 2, thumbRect.y + thumbYOffset, img.getWidth(null), newThumbHeight, null);  
                }  
            } else {  
                if (parentSlider.getOrientation() == JSlider.HORIZONTAL) {  
                    g.drawImage(img, thumbRect.x + thumbXOffset, (parentSlider.getHeight() - img.getHeight(slider)) / 2, img.getWidth(null), img.getHeight(null), null);  
                } else {  
                    g.drawImage(img, (parentSlider.getWidth() - img.getWidth(slider)) / 2, thumbRect.y + thumbYOffset, img.getWidth(null), img.getHeight(null), null);  
                }  
            }  
        }  
    }  
 
    //下面的方法主要是用来绘制标志的      
    public void paintTrack(Graphics g) {  
        //获得引用的solider的高度和宽度  
        int width = parentSlider.getWidth();  
        int height = parentSlider.getHeight();  
        //得到标尺的宽度  
        int all = parentSlider.getMaximum() - parentSlider.getMinimum();  
        int value = parentSlider.getValue();  
        //绘制没有被激活的部分显示的背景图片  
        if (backgroundImage != null) {  
        //判断方向  
            if (parentSlider.getOrientation() == JSlider.HORIZONTAL) {  
        //把整个图片画出来就可以了  
                g.drawImage(backgroundImage, 0, (height - backgroundImage.getHeight(slider)) / 2, parentSlider);  
            } else {  
                g.drawImage(backgroundImage, (width - backgroundImage.getWidth(parentSlider)) / 2, 0, parentSlider);  
            }  
        }  
        if (activeBackImage != null) {  
          //用来定位已经激活的那部分的图片,这里最关键的是在于如何判断已经激活了的值  
            //在标尺上面的定位width * value / all  
            if (parentSlider.getOrientation() == JSlider.HORIZONTAL) {  
                g.drawImage(activeBackImage, 0, (height - activeBackImage.getHeight(slider)) / 2, width * value / all, activeBackImage.getHeight(slider), 0, 0, width * value / all, activeBackImage.getHeight(slider), slider);  
            } else {  
                int sx = (width - activeBackImage.getWidth(parentSlider)) / 2;  
                g.drawImage(activeBackImage, sx, height - (height * value / all), sx + activeBackImage.getWidth(slider), height, 0, height - (height * value / all), activeBackImage.getWidth(slider), height, slider);  
            }  
        }  
    }  
 
    public void setThumbLocation(int x, int y) {  
        super.setThumbLocation(x, y);  
        parentSlider.repaint();  
    }  

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.hadeslee.yoyoplayer.util;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JSlider;
import javax.swing.plaf.basic.BasicSliderUI;

/**
 *
 * @author hadeslee
 */
public class YOYOSliderUI extends BasicSliderUI {

   
   //以下代码分别表示用于指示的图标的三种状态的图片
   private Image thumbImage = null;//普通按的图片
    private Image thumbOverImage;//鼠标在上面的图片
    private Image thumbPressedImage = null;//按下面的图片

    //分别是已经激活了的bar的背景和没有激活的bar的背景
    private Image backgroundImage = null;//普通背景图片
    private Image activeBackImage;//激活的背景图片

    //一些设置变量
    private JSlider parentSlider = null;
    private Dimension thumbDim = null;
    private int newThumbHeight = -1;
    private int thumbXOffset = 0;
    private int thumbYOffset = 0;
    private boolean hideThumb = false;

    public YOYOSliderUI(JSlider slider) {
        super(slider);
        //保存了solider的引用;
        parentSlider = slider;
    }

    public void setThumbImage(Image img) {
        thumbImage = img;
        thumbDim = new Dimension(thumbImage.getWidth(null), thumbImage.getHeight(null));
    }

    public void setThumbPressedImage(Image img) {
        thumbPressedImage = img;
    }

    public void setActiveBackImage(Image activeBackImage) {
        this.activeBackImage = activeBackImage;
    }

    public void setThumbOverImage(Image thumbOverImage) {
        this.thumbOverImage = thumbOverImage;
    }

    protected Dimension getThumbSize() {
        return thumbDim;
    }

    public void forceThumbHeight(int h) {
        newThumbHeight = h;
    }

    public void setThumbXOffset(int x) {
        thumbXOffset = x;
    }

    public void setThumbYOffset(int y) {
        thumbYOffset = y;
    }

    public void setHideThumb(boolean hide) {
        hideThumb = hide;
    }

    public void setBackgroundImages(Image img) {
        backgroundImage = img;
    }

    public void paintFocus(Graphics g) {
    }
   
    //在这里画出bar上面的指针
    public void paintThumb(Graphics g) {
    //如果隐藏指针,则不用画了
        if (hideThumb == true) {
            return;
        }
        Image img = thumbImage;
        if (img != null) {
            if (thumbPressedImage != null) {
                //判断出正在拖动中,按钮现实获取焦点的显示状态
                if (parentSlider.getValueIsAdjusting()) {
                    img = thumbPressedImage;
                }
            }
            if (newThumbHeight >= 0) {
                //根据solider的引用判断出bar的方向;
                if (parentSlider.getOrientation() == JSlider.HORIZONTAL) {
                //thumbRect.x可以得到当前的指针被鼠标拖放在哪个位置,由基类实现
                  //thumnXoffset则是一个浮动值,你可以用来微调
                 //(parentSlider.getHeight() - img.getHeight(slider)) / 2是由
                 //y+img.getHeight/2=parentSlider.getHeight/2的公式而来,使得bar和指针的中线重合
                 //上面动态的确定了指针的位置,每次指针移动都会重新刷新页面
                 //width和height是指针img本身的高度和宽度就可以了
                    g.drawImage(img, thumbRect.x + thumbXOffset, (parentSlider.getHeight() - img.getHeight(slider)) / 2, img.getWidth(null), newThumbHeight, null);
                } else {
                    g.drawImage(img, (parentSlider.getWidth() - img.getWidth(slider)) / 2, thumbRect.y + thumbYOffset, img.getWidth(null), newThumbHeight, null);
                }
            } else {
                if (parentSlider.getOrientation() == JSlider.HORIZONTAL) {
                    g.drawImage(img, thumbRect.x + thumbXOffset, (parentSlider.getHeight() - img.getHeight(slider)) / 2, img.getWidth(null), img.getHeight(null), null);
                } else {
                    g.drawImage(img, (parentSlider.getWidth() - img.getWidth(slider)) / 2, thumbRect.y + thumbYOffset, img.getWidth(null), img.getHeight(null), null);
                }
            }
        }
    }

    //下面的方法主要是用来绘制标志的   
    public void paintTrack(Graphics g) {
        //获得引用的solider的高度和宽度
        int width = parentSlider.getWidth();
        int height = parentSlider.getHeight();
        //得到标尺的宽度
        int all = parentSlider.getMaximum() - parentSlider.getMinimum();
        int value = parentSlider.getValue();
        //绘制没有被激活的部分显示的背景图片
        if (backgroundImage != null) {
        //判断方向
            if (parentSlider.getOrientation() == JSlider.HORIZONTAL) {
        //把整个图片画出来就可以了
                g.drawImage(backgroundImage, 0, (height - backgroundImage.getHeight(slider)) / 2, parentSlider);
            } else {
                g.drawImage(backgroundImage, (width - backgroundImage.getWidth(parentSlider)) / 2, 0, parentSlider);
            }
        }
        if (activeBackImage != null) {
          //用来定位已经激活的那部分的图片,这里最关键的是在于如何判断已经激活了的值
            //在标尺上面的定位width * value / all
            if (parentSlider.getOrientation() == JSlider.HORIZONTAL) {
                g.drawImage(activeBackImage, 0, (height - activeBackImage.getHeight(slider)) / 2, width * value / all, activeBackImage.getHeight(slider), 0, 0, width * value / all, activeBackImage.getHeight(slider), slider);
            } else {
                int sx = (width - activeBackImage.getWidth(parentSlider)) / 2;
                g.drawImage(activeBackImage, sx, height - (height * value / all), sx + activeBackImage.getWidth(slider), height, 0, height - (height * value / all), activeBackImage.getWidth(slider), height, slider);
            }
        }
    }

    public void setThumbLocation(int x, int y) {
        super.setThumbLocation(x, y);
        parentSlider.repaint();
    }
}
 

我们首先必须保证我们的激活的背景图片和没有被激活的背景图片是一样长的:如下图2,图3,

图2,没有激活的声音

 

图3,激活了的声音

 

然后就是运用graphics一个重要的截取图片的方法,吧激活了声音的部分截取下来;

view plaincopy to clipboardprint?
public abstract boolean drawImage(Image img,  
                      int dx1, int dy1, int dx2, int dy2,  
                      int sx1, int sy1, int sx2, int sy2,  
                      ImageObserver observer); 
public abstract boolean drawImage(Image img,
          int dx1, int dy1, int dx2, int dy2,
          int sx1, int sy1, int sx2, int sy2,
          ImageObserver observer);

 代码清单如下:

view plaincopy to clipboardprint?
g.drawImage(activeBackImage, 0, (height - activeBackImage.getHeight(slider)) / 2, width * value / all, activeBackImage.getHeight(slider), 0, 0, width * value / all, activeBackImage.getHeight(slider), slider); 
 g.drawImage(activeBackImage, 0, (height - activeBackImage.getHeight(slider)) / 2, width * value / all, activeBackImage.getHeight(slider), 0, 0, width * value / all, activeBackImage.getHeight(slider), slider);

可以继承一个自己的JSolider,如下:

view plaincopy to clipboardprint?
package com.hadeslee.yoyoplayer.util;  
 
import javax.swing.JSlider;  
 
public class YOYOSlider extends JSlider {  
 
    private static final long serialVersionUID = 20071214L;  
 
    public YOYOSlider() {  
        super();  
        setDoubleBuffered(true);  
    }  
 
    public boolean isRequestFocusEnabled() {  
        setValueIsAdjusting(true);  
        repaint();  
        return super.isRequestFocusEnabled();  
    }  
 
    public void setHideThumb(boolean hide) {  
        ((YOYOSliderUI) getUI()).setHideThumb(hide);  
    }  

package com.hadeslee.yoyoplayer.util;

import javax.swing.JSlider;

public class YOYOSlider extends JSlider {

    private static final long serialVersionUID = 20071214L;

    public YOYOSlider() {
        super();
        setDoubleBuffered(true);
    }

    public boolean isRequestFocusEnabled() {
        setValueIsAdjusting(true);
        repaint();
        return super.isRequestFocusEnabled();
    }

    public void setHideThumb(boolean hide) {
        ((YOYOSliderUI) getUI()).setHideThumb(hide);
    }
}
 

然后将UI和控件结合起来,如下:

view plaincopy to clipboardprint?
YOYOSlider yoyo = new YOYOSlider();  
      YOYOSliderUI ui = new YOYOSliderUI(yoyo);  
      yoyo.setOpaque(false);  
      yoyo.setMaximum(max);  
      yoyo.setMinimum(min);  
      yoyo.setValue(value);  
      yoyo.setOrientation(orientation);  
      ui.setThumbImage(ball1);  
      ui.setThumbOverImage(ball2);  
      ui.setThumbPressedImage(ball3);  
      ui.setBackgroundImages(bg1);  
      ui.setActiveBackImage(bg2);  
      yoyo.setUI(ui);  
      yoyo.addChangeListener(listener);  
      return yoyo; 
  YOYOSlider yoyo = new YOYOSlider();
        YOYOSliderUI ui = new YOYOSliderUI(yoyo);
        yoyo.setOpaque(false);
        yoyo.setMaximum(max);
        yoyo.setMinimum(min);
        yoyo.setValue(value);
        yoyo.setOrientation(orientation);
        ui.setThumbImage(ball1);
        ui.setThumbOverImage(ball2);
        ui.setThumbPressedImage(ball3);
        ui.setBackgroundImages(bg1);
        ui.setActiveBackImage(bg2);
        yoyo.setUI(ui);
        yoyo.addChangeListener(listener);
        return yoyo;

这个时候我们就得到了一个绚丽的solider;从下图4中我们可以清晰的看见激活和未激活部分的区别,高亮了激活的部分;

图4,高亮的激活部分:

 

 

--------------------------------------------------------------------------------


备注

1)首先图片的背景必须是透明的,这样才能只显示有效的空间部分(以上图片的时候背景是黑色的,其实在ps下面是透明的),格式是支持透明的png格式;

2)在设置控件大小的时候必须用

view plaincopy to clipboardprint?
pos.setBounds(10, 108, 270, 15);  
       volume.setBounds(43, 130, 82, 15);  
       pan.setBounds(160, 72, 90, 13);  
       this.add(pos);  
       this.add(volume);  
       this.add(pan); 
 pos.setBounds(10, 108, 270, 15);
        volume.setBounds(43, 130, 82, 15);
        pan.setBounds(160, 72, 90, 13);
        this.add(pos);
        this.add(volume);
        this.add(pan);

反复调整好大小,不然会出现真实的solider和我们的图片的大小不相符,导致指针溢出等现象;

分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    slider.zip

    在微信小程序开发中,`slider`组件是一种常用的交互元素,用于实现滑动选择的效果,比如评分、进度条等。...通过深入理解这一实践,开发者可以更好地掌控小程序的界面表现,打造出更具个性化的用户体验。

    MFC重绘的透明Slider

    在MFC(Microsoft Foundation Class)库中,Slider控件(也称为TBS)通常用于创建一个可滚动的条形控件,用户可以通过拖动滑块来选择一个数值范围内的值。然而,MFC默认的Slider控件并不支持透明效果,这在某些需要...

    Slider.js一款图片播放控件

    Slider.js 是一款强大的开源图片播放控件,专为网页设计者和开发者打造,用于实现高质量的图片展示和交互功能。这款控件具有丰富的特性,包括图片备注和切换效果,能够帮助用户在网页上构建出引人入胜的视觉体验。 ...

    slider相当漂亮扩展类库

    在IT行业中,滑动条(Slider)是一种常见的用户界面元素,用于表示和调整数值或进度。"slider相当漂亮扩展类库"是一个专为滑动条组件设计的集合,提供了多种不同特性和样式的slider实现,旨在提升用户体验和界面美观...

    Slider Revolution演示全屏内容切换动画效果

    Slider Revolution演示全屏内容切换动画效果 Slider Revolution演示全屏内容切换动画效果 Slider Revolution演示全屏内容切换动画效果 Slider Revolution演示全屏内容切换动画效果

    OC圆形Slider.

    "OC圆形Slider"是一种独特的用户界面组件,它将传统的线性Slider转变为圆形设计,以提供更直观且有趣的音量调节方式。这种设计通常用于音乐播放器、音频应用或者其他需要调整音量的场景,因为它能够提供更自然的拖动...

    Slider鼠标点击 滑块移动

    在用户界面设计中,滑块(Slider)是一种常见的控件,用于让用户选择一个范围内的值。当用户点击Slider的任意位置时,滑块应能响应并移动到点击的位置,以提供直观的交互体验。 首先,我们要了解Slider的基本结构。...

    cute slider v2.1

    Cute Slider v2.1是一款强大的幻灯片制作工具,专为那些希望在网站上添加引人注目的3D效果的用户设计。...通过探索提供的资源,无论是新手还是经验丰富的开发者,都能够快速上手并打造出独特的幻灯片展示。

    jqueryslider js 滑块

    **jQuery Slider 深入解析** 在Web开发中,滑块是一种常见的用户界面元素,用于展示图片、数据或实现进度条功能。jQuery Slider是jQuery库中的一个强大组件,它为开发者提供了灵活且易于使用的滑块解决方案。本篇将...

    slider-revolution-v6.2.23_WordPress_slider_wApuu.com_

    **标题解析:** "slider-revolution-v6.2.23...总的来说,Slider Revolution v6.2.23是WordPress用户打造互动式、专业滑动内容的理想选择,它结合了易用性、功能性和灵活性,可以帮助提升网站的视觉吸引力和用户体验。

    osx开发Slider滑条

    在Mac OS X(现称macOS)开发中,创建用户界面时,Slider控件是一种常见的交互元素,允许用户通过滑动来选择一个数值范围内的值。这个控件通常用于音量控制、进度调整或者参数设置等场景。在本文中,我们将深入探讨...

    jq22jqueryslider4678201807262215.zip

    **jQuery Slider插件详解** jQuery Slider是一款广泛应用于网站设计中的轮播图插件,它基于JavaScript库jQuery进行开发,能够帮助开发者轻松实现图片、内容的动态展示效果,为用户带来流畅且美观的交互体验。本插件...

    MFC中Slider Control 使用简例

    ### MFC中Slider Control 使用简例 在Microsoft Foundation Classes (MFC)中,`Slider Control`(滑块控件)是一种常用的用户界面元素,用于让用户通过拖动滑块来选择一个值或设置某个参数。本篇文章将详细介绍如何...

    nivo-slider3.2 jquery插件源代码

    《nivo-slider3.2:打造出色的jQuery滑动特效》 在Web开发中,动态、交互的用户体验往往能提升网站的吸引力。nivo-slider3.2是一款基于jQuery的滑动插件,它以其丰富的功能、良好的兼容性和简洁的API,深受开发者...

    chop slider一款超级酷炫的JQery 图片变换插件 slider

    【chop slider:一款独特的jQuery图片变换插件】 在当今的网页设计中,动态效果已经成为提升用户体验的重要元素。...通过深入学习和实践,开发者可以将这款插件灵活应用于各类项目,打造独具特色的网页动态效果。

    wpf slider(滑块随时间滑动) 时间轴

    在Windows Presentation Foundation (WPF) 中,`Slider`控件是一种常见的用户界面元素,它允许用户通过拖动滑块在指定范围内选择一个值。在这个特定的项目中,“wpf slider(滑块随时间滑动) 时间轴”是利用`Slider...

    jQuery轮播图插件camRoll Slider

    **jQuery轮播图插件camRoll Slider详解** 在网页设计中,轮播图是一种常见的元素,用于展示多个图片或内容...通过对源代码的深入理解和调整,开发者可以轻松地将此插件集成到自己的项目中,打造出个性化的轮播图组件。

    超酷的Slider控件源码

    在IT领域,滑块(Slider)控件是一种常见的交互元素,尤其在网页设计和应用程序开发中,它被广泛用于展示可调整的数值、切换选项或创建动态效果。本主题聚焦于一个“超酷”的Slider控件,其源码不依赖任何特定的前端...

    nivo-slider3.2

    《nivo-slider3.2:打造视觉盛宴的滑动图像插件详解》 在Web设计领域,动态元素的运用能够极大地提升用户体验,其中滑动图像(Slider)是一种常见且有效的展示方式。nivo-slider3.2是流行的一款jQuery插件,专为...

    Slider Revolution for Wordpress

    Revolution Slider是一个具有视差功能的幻灯片插件,此插件是wordpress上目前为至最强大的幻灯片插件,具有自适应功能、可创建全宽幻灯片、具有视差效果,所有幻灯片拥有的功能他全部拥有。所以,你值得拥有! 图片...

Global site tag (gtag.js) - Google Analytics