jrangeslider.java

来自「用applet实现很多应用小程序」· Java 代码 · 共 845 行 · 第 1/2 页

JAVA
845
字号
package prefuse.util.ui;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.Iterator;

import javax.swing.BoundedRangeModel;
import javax.swing.DefaultBoundedRangeModel;
import javax.swing.JComponent;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * <p>Implements a Swing-based Range slider, which allows the user to enter a 
 * range (minimum and maximum) value.</p>
 * 
 * @author Ben Bederson
 * @author Jesse Grosjean
 * @author Jon Meyer
 * @author Lance Good
 * @author jeffrey heer
 * @author Colin Combe
 */
public class JRangeSlider extends JComponent 
    implements MouseListener, MouseMotionListener, KeyListener
{   
    /*
     * NOTE: This is a modified version of the original class distributed by
     * Ben Bederson, Jesse Grosjean, and Jon Meyer as part of an HCIL Tech
     * Report.  It is modified to allow both vertical and horitonal modes.
     * It also fixes a bug with offset on the buttons. Also fixed a bug with
     * rendering using (x,y) instead of (0,0) as origin.  Also modified to
     * render arrows as a series of lines rather than as a GeneralPath.
     * Also modified to fix rounding errors on toLocal and toScreen.
     * 
     * With inclusion in prefuse, this class has been further modified to use a
     * bounded range model, support keyboard commands and more extensize
     * parameterization of rendering/appearance options. Furthermore, a stub
     * method has been introduced to allow subclasses to perform custom
     * rendering within the slider through.
     */
    
    final public static int VERTICAL = 0;
    final public static int HORIZONTAL = 1;
    final public static int LEFTRIGHT_TOPBOTTOM = 0;
    final public static int RIGHTLEFT_BOTTOMTOP = 1;
    
    final public static int PREFERRED_BREADTH = 16;
    final public static int PREFERRED_LENGTH = 300;
    final protected static int ARROW_SZ = 16;
    final protected static int ARROW_WIDTH = 8;
    final protected static int ARROW_HEIGHT = 4;

    protected BoundedRangeModel model;
    protected int orientation;
    protected int direction;
    protected boolean empty;
    protected int increment = 1;
    protected int minExtent = 0; // min extent, in pixels
    
    protected ArrayList listeners = new ArrayList();
    protected ChangeEvent changeEvent = null;
    protected ChangeListener lstnr;
 
    protected Color thumbColor = new Color(150,180,220);
    
    // ------------------------------------------------------------------------

    /** 
     * Create a new range slider. 
     *
     * @param minimum - the minimum value of the range.
     * @param maximum - the maximum value of the range.
     * @param lowValue - the current low value shown by the range slider's bar.
     * @param highValue - the current high value shown by the range slider's bar.
     * @param orientation - construct a horizontal or vertical slider?
     */
    public JRangeSlider(int minimum, int maximum, int lowValue, int highValue, int orientation) {
        this(new DefaultBoundedRangeModel(lowValue, highValue - lowValue, minimum, maximum),
                orientation,LEFTRIGHT_TOPBOTTOM);
    }

    /** 
     * Create a new range slider. 
     *
     * @param minimum - the minimum value of the range.
     * @param maximum - the maximum value of the range.
     * @param lowValue - the current low value shown by the range slider's bar.
     * @param highValue - the current high value shown by the range slider's bar.
     * @param orientation - construct a horizontal or vertical slider?
     * @param direction - Is the slider left-to-right/top-to-bottom or right-to-left/bottom-to-top
     */
    public JRangeSlider(int minimum, int maximum, int lowValue, int highValue, int orientation, int direction) {
        this(new DefaultBoundedRangeModel(lowValue, highValue - lowValue, minimum, maximum), 
                orientation, direction);
    }
    
    /** 
     * Create a new range slider. 
     *
     * @param model - a BoundedRangeModel specifying the slider's range
     * @param orientation - construct a horizontal or vertical slider?
     * @param direction - Is the slider left-to-right/top-to-bottom or right-to-left/bottom-to-top
     */
    public JRangeSlider(BoundedRangeModel model, int orientation, int direction) {
        super.setFocusable(true);
        this.model = model;
        this.orientation = orientation;     
        this.direction = direction;
        
        setForeground(Color.LIGHT_GRAY);
        
        this.lstnr = createListener();
        model.addChangeListener(lstnr);
        
        addMouseListener(this);
        addMouseMotionListener(this);
        addKeyListener(this);
    }
    
    /**
     * Create a listener to relay change events from the bounded range model.
     * @return a ChangeListener to relay events from the range model
     */
    protected ChangeListener createListener() {
        return new RangeSliderChangeListener();
    }
    
    /**
     * Listener that fires a change event when it receives  change event from
     * the slider list model.
     */
    protected class RangeSliderChangeListener implements ChangeListener {
        public void stateChanged(ChangeEvent e) {
            fireChangeEvent();
        }
    }
    
    /** 
     * Returns the current "low" value shown by the range slider's bar. The low
     * value meets the constraint minimum <= lowValue <= highValue <= maximum. 
     */
    public int getLowValue() {
        return model.getValue();
    }

    /** 
     * Sets the low value shown by this range slider. This causes the range slider to be
     * repainted and a ChangeEvent to be fired.
     * @param lowValue the low value to use
     */
    public void setLowValue(int lowValue) {
        int e = (model.getValue()-lowValue)+model.getExtent();
        model.setRangeProperties(lowValue, e,
            model.getMinimum(), model.getMaximum(), false);
        model.setValue(lowValue);
    }

    /** 
     * Returns the current "high" value shown by the range slider's bar. The high
     * value meets the constraint minimum <= lowValue <= highValue <= maximum. 
     */
    public int getHighValue() {
        return model.getValue()+model.getExtent();
    }

    /** 
     * Sets the high value shown by this range slider. This causes the range slider to be
     * repainted and a ChangeEvent to be fired.
     * @param highValue the high value to use
     */
    public void setHighValue(int highValue) {
        model.setExtent(highValue-model.getValue());
    }
    
    /**
     * Set the slider range span.
     * @param lowValue the low value of the slider range
     * @param highValue the high value of the slider range
     */
    public void setRange(int lowValue, int highValue) {
        model.setRangeProperties(lowValue, highValue-lowValue,
                model.getMinimum(), model.getMaximum(), false);
    }

    /**
     * Gets the minimum possible value for either the low value or the high value.
     * @return the minimum possible range value
     */
    public int getMinimum() {
        return model.getMinimum();
    }

    /**
     * Sets the minimum possible value for either the low value or the high value.
     * @param minimum the minimum possible range value
     */
    public void setMinimum(int minimum) {
        model.setMinimum(minimum);
    }

    /**
     * Gets the maximum possible value for either the low value or the high value.
     * @return the maximum possible range value
     */
    public int getMaximum() {
        return model.getMaximum();
    }

    /**
     * Sets the maximum possible value for either the low value or the high value.
     * @param maximum the maximum possible range value
     */
    public void setMaximum(int maximum) {
        model.setMaximum(maximum);
    }

    /**
     * Sets the minimum extent (difference between low and high values).
     * This method <strong>does not</strong> change the current state of the
     * model, but can affect all subsequent interaction.
     * @param minExtent the minimum extent allowed in subsequent interaction
     */
    public void setMinExtent(int minExtent) {
        this.minExtent = minExtent;
    }
    
    /**
     * Sets whether this slider is empty.
     * @param empty true if set to empty, false otherwise
     */
    public void setEmpty(boolean empty) {
        this.empty = empty;
        repaint();
    }

    /**
     * Get the slider thumb color. This is the part of the slider between
     * the range resize buttons.
     * @return the slider thumb color
     */
    public Color getThumbColor() {
        return thumbColor;
    }
    
    /**
     * Set the slider thumb color. This is the part of the slider between
     * the range resize buttons.
     * @param thumbColor the slider thumb color
     */
    public void setThumbColor(Color thumbColor) {
        this.thumbColor = thumbColor;
    }
    
    /**
     * Get the BoundedRangeModel backing this slider.
     * @return the slider's range model
     */
    public BoundedRangeModel getModel() {
        return model;
    }
    
    /**
     * Set the BoundedRangeModel backing this slider.
     * @param brm the slider range model to use
     */
    public void setModel(BoundedRangeModel brm) {
        model.removeChangeListener(lstnr);
        model = brm;
        model.addChangeListener(lstnr);
        repaint();
    }
    
    /** 
     * Registers a listener for ChangeEvents.
     * @param cl the ChangeListener to add
     */
    public void addChangeListener(ChangeListener cl) {
        if ( !listeners.contains(cl) )
            listeners.add(cl);
    }

    /** 
     * Removes a listener for ChangeEvents.
     * @param cl the ChangeListener to remove
     */
    public void removeChangeListener(ChangeListener cl) {
        listeners.remove(cl);
    }
    
    /**
     * Fire a change event to all listeners.
     */
    protected void fireChangeEvent() {
        repaint();
        if ( changeEvent == null )
            changeEvent = new ChangeEvent(this);
        Iterator iter = listeners.iterator();
        while ( iter.hasNext() )
            ((ChangeListener)iter.next()).stateChanged(changeEvent);
    }

    /**
     * @see java.awt.Component#getPreferredSize()
     */
    public Dimension getPreferredSize() {
        if (orientation == VERTICAL) {
            return new Dimension(PREFERRED_BREADTH, PREFERRED_LENGTH);
        }
        else {
            return new Dimension(PREFERRED_LENGTH, PREFERRED_BREADTH);
        }
    }

    // ------------------------------------------------------------------------
    // Rendering

    /**
     * Override this method to perform custom painting of the slider trough.
     * @param g a Graphics2D context for rendering
     * @param width the width of the slider trough
     * @param height the height of the slider trough
     */
    protected void customPaint(Graphics2D g, int width, int height) {
        // does nothing in this class
        // subclasses can override to perform custom painting
    }
    
    /**
     * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
     */
    public void paintComponent(Graphics g) {        
        Rectangle bounds = getBounds();
        int width = (int)bounds.getWidth() - 1;
        int height = (int)bounds.getHeight() - 1;

        int min = toScreen(getLowValue());
        int max = toScreen(getHighValue());

        // Paint the full slider if the slider is marked as empty
        if (empty) {
            if (direction == LEFTRIGHT_TOPBOTTOM) {
                min = ARROW_SZ;
                max = (orientation == VERTICAL) ? height-ARROW_SZ : width-ARROW_SZ;
            }
            else {
                min = (orientation == VERTICAL) ? height-ARROW_SZ : width-ARROW_SZ;
                max = ARROW_SZ;                 
            }
        }

        Graphics2D g2 = (Graphics2D)g;
        g2.setColor(getBackground());
        g2.fillRect(0, 0, width, height);
        g2.setColor(getForeground());
        g2.drawRect(0, 0, width, height);

        customPaint(g2, width, height);
        
        // Draw arrow and thumb backgrounds
        g2.setStroke(new BasicStroke(1));
        if (orientation == VERTICAL) {  
            if (direction == LEFTRIGHT_TOPBOTTOM) {
                g2.setColor(getForeground());
                g2.fillRect(0, min - ARROW_SZ, width, ARROW_SZ-1);
                paint3DRectLighting(g2,0,min-ARROW_SZ,width,ARROW_SZ-1);
            
                if ( thumbColor != null ) {
                    g2.setColor(thumbColor);
                    g2.fillRect(0, min, width, max - min-1);
                    paint3DRectLighting(g2,0,min,width,max-min-1);
                }
                
                g2.setColor(getForeground());
                g2.fillRect(0, max, width, ARROW_SZ-1);
                paint3DRectLighting(g2,0,max,width,ARROW_SZ-1);
            
                // Draw arrows          
                g2.setColor(Color.black);
                paintArrow(g2, (width-ARROW_WIDTH) / 2.0, min - ARROW_SZ + (ARROW_SZ-ARROW_HEIGHT) / 2.0, ARROW_WIDTH, ARROW_HEIGHT, true);
                paintArrow(g2, (width-ARROW_WIDTH) / 2.0, max + (ARROW_SZ-ARROW_HEIGHT) / 2.0, ARROW_WIDTH, ARROW_HEIGHT, false);
            }
            else {
                g2.setColor(getForeground());
                g2.fillRect(0, min, width, ARROW_SZ-1);
                paint3DRectLighting(g2,0,min,width,ARROW_SZ-1);
            
                if ( thumbColor != null ) {
                    g2.setColor(thumbColor);
                    g2.fillRect(0, max, width, min-max-1);
                    paint3DRectLighting(g2,0,max,width,min-max-1);
                }
            
                g2.setColor(getForeground());
                g2.fillRect(0, max-ARROW_SZ, width, ARROW_SZ-1);
                paint3DRectLighting(g2,0,max-ARROW_SZ,width,ARROW_SZ-1);
            
                // Draw arrows          
                g2.setColor(Color.black);
                paintArrow(g2, (width-ARROW_WIDTH) / 2.0, min + (ARROW_SZ-ARROW_HEIGHT) / 2.0, ARROW_WIDTH, ARROW_HEIGHT, false);
                paintArrow(g2, (width-ARROW_WIDTH) / 2.0, max - ARROW_SZ + (ARROW_SZ-ARROW_HEIGHT) / 2.0, ARROW_WIDTH, ARROW_HEIGHT, true);             
            }
        }
        else {
            if (direction == LEFTRIGHT_TOPBOTTOM) {
                g2.setColor(getForeground());
                g2.fillRect(min - ARROW_SZ, 0, ARROW_SZ-1, height);
                paint3DRectLighting(g2,min-ARROW_SZ,0,ARROW_SZ-1,height);
            
                if ( thumbColor != null ) {
                    g2.setColor(thumbColor);
                    g2.fillRect(min, 0, max - min - 1, height);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?