Java 可以访问和修改JSlider的可视指针组件吗?

Java 可以访问和修改JSlider的可视指针组件吗?,java,swing,components,jslider,Java,Swing,Components,Jslider,我正在开发一个应用程序,尝试缩放通用窗口(JFrame或JDialog)。 我发现了一个问题,即当要缩放JSlider组件时,视觉指针component不会缩放,即使JSlider本身的边界已更改 我在JSliderpublic API中查找了一个函数,该函数返回一个基类Component的对象,该对象可以修改,但我没有找到任何函数。 另外,函数jSlider1.getComponentCount()返回0。 我还查看了SliderUI类的内部,以防那里有合适的函数,但没有成功。 是否有人知道访

我正在开发一个应用程序,尝试缩放通用窗口(
JFrame
JDialog
)。

我发现了一个问题,即当要缩放
JSlider
组件时,视觉指针
component
不会缩放,即使
JSlider
本身的边界已更改

我在
JSlider
public API中查找了一个函数,该函数返回一个基类
Component
的对象,该对象可以修改,但我没有找到任何函数。
另外,函数
jSlider1.getComponentCount()
返回0。
我还查看了
SliderUI
类的内部,以防那里有合适的函数,但没有成功。

是否有人知道访问
JSlider
的可视指针
组件的正确方法?或者至少如何设置它的大小,以便能够缩放它?

正如我之前在评论中所说的,我最终决定覆盖JSlider和MetalSliderUI类。 至少这与Java-8兼容,因为我开始使用的代码是oracle JDK-8的代码

下面是使用新类的示例代码

新界面:

新覆盖的类: ZoomMetalSliderUI:

* * * *可能会抛出
BoundsException数组
*如果区域不在边界内。
*但是,不能保证显式边界检查。
*
*@param startX起始X坐标
*@param startY起始Y坐标
*@param w区域宽度
*@param h区域高度
*@param rgbArray如果不是
null
,则rgb像素为 *写在这里 *@param offset偏移到
rgbArray
*@param scansize用于
rgbArray
*@返回RGB像素数组。 *@see#setRGB(int,int,int) *@see#setRGB(int,int,int,int,int,int[],int,int) */ 公共静态int[]getRGB(int-startX,int-startY,int-w,int-h, 缓冲图像(bi) { ColorModel ColorModel=bi.getColorModel(); 光栅=bi.getRaster(); //WritableRaster raster=colorModel.createCompatibleWritableRaster(bi.getWidth(),bi.getHeight()); int scansize=w; 整数偏移=0; int yoff=偏移量; int off; 对象数据; int nbands=graster.getNumBands(); int dataType=graster.getDataBuffer().getDataType(); 交换机(数据类型) { case DataBuffer.TYPE_字节: 数据=新字节[nbands]; 打破 case DataBuffer.TYPE_USHORT: 数据=新的短[nbands]; 打破 case DataBuffer.TYPE_INT: 数据=新的整数[n位数]; 打破 case DataBuffer.TYPE_FLOAT: 数据=新浮点数[n位数]; 打破 case DataBuffer.TYPE_DOUBLE: 数据=新的双[n个]; 打破 违约: 抛出新的IllegalArgumentException(“未知数据缓冲区类型:”+ 数据类型); } int[]rgbArray=新int[offset+h*scansize]; 对于(int y=startY;y=0)&&(x=0)&&&(yi2?i1:i2); } 公共静态int min(int i1,int i2) { 返回(i1=0?ii:-ii); } 公共静态int sgn(int ii) {
返回(ii>0?1:(iiI)一般认为可以,因为它是由ui委托/外观和感觉处理的。您可以看看哪个使用JLayer/JXLayer来缩放活动组件哇,听起来很棒!我有时间会看一看。最后,我创建了一对覆盖JSlider和MetalSliderUI的类。如果我找到方法去做吧。
public interface ZoomInterface
{
    public void setZoomFactor( double zoomFactor );
    public double getZoomFactor();
}
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JSlider;
import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.plaf.metal.MetalSliderUI;

/**
 *
 * @author Francisco Javier Rojas Garrido <frojasg1@hotmail.com>
 */
public class ZoomMetalSliderUI extends MetalSliderUI implements ZoomInterface
{
    protected double _zoomFactor = 1.0D;

    public ZoomMetalSliderUI()
    {
        super();
    }

    @Override
    public Dimension getThumbSize()
    {
        Dimension result = ViewFunctions.instance().getNewDimension( super.getThumbSize(), null, _zoomFactor );

        return( result );
    }

    @Override
    public void setZoomFactor(double zoomFactor)
    {
        _zoomFactor = zoomFactor;
    }

    @Override
    public double getZoomFactor()
    {
        return( _zoomFactor );
    }

    @Override
    public void paint( Graphics g, JComponent c )
    {
        calculateGeometry();
        super.paint(g, c);
    }

    @Override
    public void paintThumb(Graphics g)  {
        Rectangle knobBounds = thumbRect;

//        g.translate( knobBounds.x, knobBounds.y );

        Icon icon = null;
        if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
            icon = horizThumbIcon;
        }
        else {
            icon = vertThumbIcon;
        }

        BufferedImage bi = new BufferedImage( icon.getIconWidth(), icon.getIconHeight(),
                                                BufferedImage.TYPE_INT_ARGB );
        Graphics g1 = bi.getGraphics();

        if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
            horizThumbIcon.paintIcon( slider, bi.getGraphics(), 0, 0 );
        }
        else {
            vertThumbIcon.paintIcon( slider, bi.getGraphics(), 0, 0 );
        }

        Rectangle tr = new Rectangle( 0, 0, icon.getIconWidth(), icon.getIconHeight() );
        Rectangle newRectangle = ViewFunctions.instance().getNewRectangle(tr, null, _zoomFactor );
        BufferedImage bi_tx = ImageFunctions.resizeImage(bi, (int)newRectangle.getWidth(),
                                                        (int)newRectangle.getHeight(),
                                                        null, null, null );

        Point center = ViewFunctions.instance().getCenter(knobBounds);
        g.drawImage( bi_tx, center.x - newRectangle.width / 2,
                            center.y - newRectangle.height / 2,
                            center.x + newRectangle.width / 2,
                            center.y + newRectangle.height / 2,
                            0,
                            0,
                            bi_tx.getWidth(),
                            bi_tx.getHeight(),
                            null );
//        g.translate( -knobBounds.x, -knobBounds.y );


    }


    public void paintTrack(Graphics g)  {
/*        if (MetalLookAndFeel.usingOcean()) {
            oceanPaintTrack(g);
            return;
        }
*/
        Color trackColor = !slider.isEnabled() ? MetalLookAndFeel.getControlShadow() :
                           slider.getForeground();

//        boolean leftToRight = MetalUtils.isLeftToRight(slider);
        boolean leftToRight = isLeftToRight(slider);

        g.translate( trackRect.x, trackRect.y );

        int trackLeft = 0;
        int trackTop = 0;
        int trackRight;
        int trackBottom;

        // Draw the track
        if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
            trackBottom = (trackRect.height - 1) - getThumbOverhang();
            trackTop = trackBottom - (getTrackWidth() - 1);
            trackRight = trackRect.width - 1;
        }
        else {
            if (leftToRight) {
                trackLeft = (trackRect.width - getThumbOverhang()) -
                                                         getTrackWidth();
                trackRight = (trackRect.width - getThumbOverhang()) - 1;
            }
            else {
                trackLeft = getThumbOverhang();
                trackRight = getThumbOverhang() + getTrackWidth() - 1;
            }
            trackBottom = trackRect.height - 1;
        }

        if ( slider.isEnabled() ) {
            g.setColor( MetalLookAndFeel.getControlDarkShadow() );
            g.drawRect( trackLeft, trackTop,
                        (trackRight - trackLeft) - 1, (trackBottom - trackTop) - 1 );

            g.setColor( MetalLookAndFeel.getControlHighlight() );
            g.drawLine( trackLeft + 1, trackBottom, trackRight, trackBottom );
            g.drawLine( trackRight, trackTop + 1, trackRight, trackBottom );

            g.setColor( MetalLookAndFeel.getControlShadow() );
            g.drawLine( trackLeft + 1, trackTop + 1, trackRight - 2, trackTop + 1 );
            g.drawLine( trackLeft + 1, trackTop + 1, trackLeft + 1, trackBottom - 2 );
        }
        else {
            g.setColor( MetalLookAndFeel.getControlShadow() );
            g.drawRect( trackLeft, trackTop,
                        (trackRight - trackLeft) - 1, (trackBottom - trackTop) - 1 );
        }

        // Draw the fill
        if ( filledSlider ) {
            int middleOfThumb;
            int fillTop;
            int fillLeft;
            int fillBottom;
            int fillRight;

            if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
                middleOfThumb = thumbRect.x + (thumbRect.width / 2);
                middleOfThumb -= trackRect.x; // To compensate for the g.translate()
                fillTop = !slider.isEnabled() ? trackTop : trackTop + 1;
                fillBottom = !slider.isEnabled() ? trackBottom - 1 : trackBottom - 2;

                if ( !drawInverted() ) {
                    fillLeft = !slider.isEnabled() ? trackLeft : trackLeft + 1;
                    fillRight = middleOfThumb;
                }
                else {
                    fillLeft = middleOfThumb;
                    fillRight = !slider.isEnabled() ? trackRight - 1 : trackRight - 2;
                }
            }
            else {
                middleOfThumb = thumbRect.y + (thumbRect.height / 2);
                middleOfThumb -= trackRect.y; // To compensate for the g.translate()
                fillLeft = !slider.isEnabled() ? trackLeft : trackLeft + 1;
                fillRight = !slider.isEnabled() ? trackRight - 1 : trackRight - 2;

                if ( !drawInverted() ) {
                    fillTop = middleOfThumb;
                    fillBottom = !slider.isEnabled() ? trackBottom - 1 : trackBottom - 2;
                }
                else {
                    fillTop = !slider.isEnabled() ? trackTop : trackTop + 1;
                    fillBottom = middleOfThumb;
                }
            }

            if ( slider.isEnabled() ) {
                g.setColor( slider.getBackground() );
                g.drawLine( fillLeft, fillTop, fillRight, fillTop );
                g.drawLine( fillLeft, fillTop, fillLeft, fillBottom );

                g.setColor( MetalLookAndFeel.getControlShadow() );
                g.fillRect( fillLeft + 1, fillTop + 1,
                            fillRight - fillLeft, fillBottom - fillTop );
            }
            else {
                g.setColor( MetalLookAndFeel.getControlShadow() );
                g.fillRect(fillLeft, fillTop, fillRight - fillLeft, fillBottom - fillTop);
            }
        }

        g.translate( -trackRect.x, -trackRect.y );
    }

    static boolean isLeftToRight( Component c ) {
        return c.getComponentOrientation().isLeftToRight();
    }
}
import javax.swing.BoundedRangeModel;
import javax.swing.JSlider;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.metal.MetalSliderUI;

/**
 *
 * @author Francisco Javier Rojas Garrido <frojasg1@hotmail.com>
 */
public class ZoomJSlider extends JSlider implements ZoomInterface
{
    protected double _zoomFactor = 1.0D;

    public ZoomJSlider() {
        super();
    }

    public ZoomJSlider(int orientation) {
        super(orientation);
    }

    public ZoomJSlider(int min, int max) {
        super(min, max);
    }

    public ZoomJSlider(int min, int max, int value) {
        super(min, max, value);
    }

    public ZoomJSlider(int orientation, int min, int max, int value)
    {
        super(orientation, min, max, value);
    }

    public ZoomJSlider(BoundedRangeModel brm)
    {
        super( brm );
    }

    public void switchToZoomUI()
    {
        ComponentUI compUi = getUI();
        ComponentUI newUi = null;

        if( ( compUi instanceof MetalSliderUI ) &&
            !( compUi instanceof ZoomMetalSliderUI ) )
        {
            newUi = new ZoomMetalSliderUI();
        }

        if( newUi != null )
        {
            setUI(newUi);
            ( (ZoomInterface) newUi ).setZoomFactor(_zoomFactor);
        }
    }

    @Override
    public void setZoomFactor( double zoomFactor )
    {
        _zoomFactor = zoomFactor;
        ComponentUI compUi = getUI();

        if( compUi instanceof ZoomInterface )
        {
            ZoomInterface zi = (ZoomInterface) compUi;
            zi.setZoomFactor(zoomFactor);
        }

        repaint();
    }

    @Override
    public double getZoomFactor()
    {
        return( _zoomFactor );
    }
}
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.metal.MetalLookAndFeel;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Francisco Javier Rojas Garrido <frojasg1@hotmail.com>
 */
public class Main
{
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            javax.swing.UIManager.setLookAndFeel(MetalLookAndFeel.class.getName());

        } catch (ClassNotFoundException ex) {
            Logger.getLogger(MetalLookAndFeel.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            Logger.getLogger(MetalLookAndFeel.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(MetalLookAndFeel.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedLookAndFeelException ex) {
            Logger.getLogger(MetalLookAndFeel.class.getName()).log(Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                try
                {
                    new Window().setVisible(true);
                }
                catch( Throwable th )
                {
                    th.printStackTrace();
                }
            }
        });
    }
}
import java.awt.Component; import java.awt.Dimension; import java.awt.Point; import javax.swing.JFrame; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ /** * * @author Francisco Javier Rojas Garrido <frojasg1@hotmail.com> */ public class Window extends JFrame implements ChangeListener { protected Dimension _dimen = new Dimension( 250, 30 ); protected ZoomJSlider _jSlider = null; protected javax.swing.JPanel _jPanel1; public Window() { super( ); initComponents(); setListeners(); } protected void initComponents() { _jPanel1 = new javax.swing.JPanel(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); getContentPane().setLayout(null); _jPanel1.setLayout(null); _jSlider = new ZoomJSlider( 50, 200, 100 ); _jPanel1.add( _jSlider ); _jSlider.switchToZoomUI(); _jSlider.setBounds( 20, 30, (int) _dimen.getWidth(), (int) _dimen.getHeight() ); getContentPane().add(_jPanel1); _jPanel1.setBounds(0, 0, 600, 120); setSize( 650, 170 ); setLocation( getCenteredLocationForComponent( this ) ); } protected void setListeners() { _jSlider.addChangeListener( this ); } @Override public void stateChanged( ChangeEvent ce ) { double zoomFactor = _jSlider.getValue() / 100.0D; _jSlider.setZoomFactor( zoomFactor ); Dimension size = ViewFunctions.instance().getNewDimension(_dimen, null, zoomFactor); _jSlider.setBounds( _jSlider.getX(), _jSlider.getY(), (int) size.getWidth(), (int) size.getHeight() ); } public static Point getCenteredLocationForComponent( Component comp ) { int width = java.awt.Toolkit.getDefaultToolkit().getScreenSize().width; int height = java.awt.Toolkit.getDefaultToolkit().getScreenSize().height; Point result = new Point( width/2 - comp.getWidth()/2, height/2 - comp.getHeight()/2 ); return( result ); } }
import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.Raster; /** * * @author Usuario */ public class ImageFunctions { public static BufferedImage resizeImage( BufferedImage original, int width, int height, Integer switchColorFrom, Integer switchColorTo, Integer alphaForPixelsDifferentFromColorFrom ) throws IllegalArgumentException { int alpha = 0xFF000000; if( alphaForPixelsDifferentFromColorFrom != null ) alpha = ( (alphaForPixelsDifferentFromColorFrom) & 0xFF ) << 24; if( ( width < 1 ) || ( height < 1 ) ) throw( new IllegalArgumentException( "Bad size for image. Width: " + width + ". Height: " + height ) ); BufferedImage result = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB ); double factorX = ((double) original.getWidth()) / width ; double factorY = ( (double) original.getHeight() ) / height; int[] pixels = getRGB( 0, 0, original.getWidth(), original.getHeight(), original ); double transformedY = 0.5d; for( int tY = 0; tY < height; transformedY += 1, tY++ ) { int originalOffsetY = (int) ( Math.floor(transformedY*factorY) ) * original.getWidth(); double transformedX = 0.5D; for( int tX = 0; tX < width; transformedX += 1, tX++ ) { int originalX = (int) ( Math.floor( transformedX*factorX ) ); int pixelColor = pixels[ originalOffsetY+originalX ]; if( ( switchColorFrom != null ) && ( pixelColor == switchColorFrom ) ) { if( switchColorTo != null ) pixelColor = switchColorTo; else pixelColor = pixelColor & 0xFFFFFF; } else if( alphaForPixelsDifferentFromColorFrom != null ) { pixelColor = pixelColor & 0xFFFFFF | alpha; } result.setRGB( tX, tY, pixelColor ); } } return( result ); } /** * Returns an array of integer pixels in the default RGB color model * (TYPE_INT_ARGB) and default sRGB color space, * from a portion of the image data. Color conversion takes * place if the default model does not match the image * <code>ColorModel</code>. There are only 8-bits of precision for * each color component in the returned data when * using this method. With a specified coordinate (x,&nbsp;y) in the * image, the ARGB pixel can be accessed in this way: * </p> * * <pre> * pixel = rgbArray[offset + (y-startY)*scansize + (x-startX)]; </pre> * * <p> * * An <code>ArrayOutOfBoundsException</code> may be thrown * if the region is not in bounds. * However, explicit bounds checking is not guaranteed. * * @param startX the starting X coordinate * @param startY the starting Y coordinate * @param w width of region * @param h height of region * @param rgbArray if not <code>null</code>, the rgb pixels are * written here * @param offset offset into the <code>rgbArray</code> * @param scansize scanline stride for the <code>rgbArray</code> * @return array of RGB pixels. * @see #setRGB(int, int, int) * @see #setRGB(int, int, int, int, int[], int, int) */ public static int[] getRGB(int startX, int startY, int w, int h, BufferedImage bi ) { ColorModel colorModel = bi.getColorModel(); Raster raster = bi.getRaster(); // WritableRaster raster = colorModel.createCompatibleWritableRaster( bi.getWidth(), bi.getHeight() ); int scansize = w; int offset =0; int yoff = offset; int off; Object data; int nbands = raster.getNumBands(); int dataType = raster.getDataBuffer().getDataType(); switch (dataType) { case DataBuffer.TYPE_BYTE: data = new byte[nbands]; break; case DataBuffer.TYPE_USHORT: data = new short[nbands]; break; case DataBuffer.TYPE_INT: data = new int[nbands]; break; case DataBuffer.TYPE_FLOAT: data = new float[nbands]; break; case DataBuffer.TYPE_DOUBLE: data = new double[nbands]; break; default: throw new IllegalArgumentException("Unknown data buffer type: "+ dataType); } int[] rgbArray = new int[offset+h*scansize]; for (int y = startY; y < startY+h; y++, yoff+=scansize) { off = yoff; for (int x = startX; x < startX+w; x++) { if( (x>=0) && (x<bi.getWidth()) && (y>=0) && (y<bi.getHeight() ) ) { rgbArray[off++] = colorModel.getRGB(raster.getDataElements( x, y, data)); } else { rgbArray[off++] = 0; } } } return rgbArray; } }
public class IntegerFunctions { public static int max( int i1, int i2 ) { return( i1>i2 ? i1 : i2 ); } public static int min( int i1, int i2 ) { return( i1<i2 ? i1 : i2 ); } public static int abs( int ii ) { return( ii>=0 ? ii : -ii ); } public static int sgn( int ii ) { return( ii>0 ? 1 : ( ii<0 ? -1 : 0 ) ); } }
import java.awt.Dimension; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; /** * * @author Usuario */ public class ViewFunctions { protected static ViewFunctions _instance; public static ViewFunctions instance() { if( _instance == null ) _instance = new ViewFunctions(); return( _instance ); } public Dimension getNewDimension( Dimension dim, Insets insets, double zoomFactor ) { Dimension result = null; if( dim != null ) { if( insets == null ) insets = new Insets(0,0,0,0); int insetsWidth = insets.left + insets.right; int insetsHeight = insets.top + insets.bottom; result = new Dimension( (int) ( zoomFactor * ( dim.getWidth() - insetsWidth ) + insetsWidth ), (int) ( zoomFactor * ( dim.getHeight() - insetsHeight ) + insetsHeight ) ); } return( result ); } public Rectangle getNewRectangle( Rectangle rect, Insets insets, double zoomFactor ) { Rectangle result = null; if( rect != null ) { if( insets == null ) insets = new Insets(0,0,0,0); int insetsWidth = insets.left + insets.right; int insetsHeight = insets.top + insets.bottom; result = new Rectangle( (int) ( zoomFactor * ( rect.getX() + insets.left ) - insets.left ), (int) ( zoomFactor * ( rect.getY() + insets.top ) - insets.top ), (int) ( zoomFactor * ( rect.getWidth() - insetsWidth ) + insetsWidth ), (int) ( zoomFactor * ( rect.getHeight() - insetsHeight ) + insetsHeight ) ); } return( result ); } public Insets getNewInsets( Insets insets, double zoomFactor ) { Insets result = null; if( insets != null ) { result = new Insets( (int) ( insets.top * zoomFactor ), (int) ( insets.left * zoomFactor ), (int) ( insets.bottom * zoomFactor ), (int) ( insets.right * zoomFactor ) ); } return( result ); } public Point getCenter( Rectangle rect ) { Point result = null; if( rect != null ) { result = new Point( (int) ( rect.getX() + rect.getWidth() / 2 ), (int) ( rect.getY() + rect.getHeight() / 2 ) ); } return( result ); } public Rectangle calculateNewBounds( Rectangle originalBounds, Insets insets, Point center, double zoomFactor ) { Rectangle result = null; if( originalBounds != null ) { if( insets == null ) insets = new Insets( 0, 0, 0, 0 ); int newX = (int) originalBounds.getX(); int newY = (int) originalBounds.getY(); if( center != null ) { newX = (int) ( center.getX() - insets.left + ( originalBounds.getX() - center.getX() + insets.left ) * zoomFactor ); newY = (int) ( center.getY() - insets.top + ( originalBounds.getY() - center.getY() + insets.top ) * zoomFactor ); } result = new Rectangle( newX, newY, (int) ( ( originalBounds.getWidth() - insets.left - insets.right ) * zoomFactor + insets.left + insets.right ), (int) ( ( originalBounds.getHeight() - insets.top - insets.bottom ) * zoomFactor + insets.top + insets.bottom ) ); } return( result ); } }