【问题标题】:Can the visual pointer component of a JSlider be accessed and modified?JSlider的可视化指针组件可以访问和修改吗?
【发布时间】:2018-08-01 20:56:45
【问题描述】:

我正在开发一个尝试缩放通用窗口(@98​​7654322@ 或 JDialog)的应用程序。

我发现当JSlider 组件被缩放时,视觉指针Component 不会缩放,即使JSlider 本身的边界已经改变。

我在JSlider公共API中寻找了一个函数,该函数返回基类Component的对象,可以修改,但我没有找到。
函数 jSlider1.getComponentCount() 也返回 0。
我还查看了 SliderUI 类的内部,以防那里有合适的函数,但没有成功。
有谁知道访问JSlider 的可视指针Component 的正确方法?或者至少如何设置它的大小,以便能够缩放它?

【问题讨论】:

  • 我通常认为可以,因为它由 ui 委托/外观处理
  • 你可以看看this example,它使用 JLayer/JXLayer 来缩放活动组件
  • 哇,听起来很棒!有空我会去看看。
  • 最后我创建了一对覆盖 JSlider 和 MetalSliderUI 的类。如果我能找到方法,我会展示这些课程的效果。

标签: java swing components jslider


【解决方案1】:

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

新类的使用示例代码如下。

新界面:

public interface ZoomInterface
{
    public void setZoomFactor( double zoomFactor );
    public double getZoomFactor();
}

新的覆盖类: ZoomMetalSliderUI:

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();
    }
}

ZoomJSlider:

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();
                }
            }
        });
    }
}

窗口类:

导入 java.awt.Component;
导入 java.awt.Dimension;
导入 java.awt.Point;
导入 javax.swing.JFrame;
导入 javax.swing.event.ChangeEvent;
导入 javax.swing.event.ChangeListener;

/*
 * 要更改此许可标头,请在项目属性中选择许可标头。
 * 要更改此模板文件,请选择工具 |模板
 * 并在编辑器中打开模板。
 */

/**
 *
 * @作者弗朗西斯科·哈维尔·罗哈斯·加里多 
 */
公共类 Window 扩展 JFrame 实现 ChangeListener
{
    受保护的维度 _dimen = 新维度(250, 30);
    受保护的 ZoomJSlider _jSlider = null;
    受保护的 javax.swing.JPanel _jPanel1;

    公共窗口()
    {
        极好的( );
        初始化组件();

        setListeners();
    }

    受保护的 void initComponents()
    {
        _jPanel1 = 新 javax.swing.JPanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(null);

        _jPanel1.setLayout(null);
        _jSlider = 新 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);

        设置尺寸(650、170);
        setLocation(getCenteredLocationForComponent(this));
    }

    受保护的无效 setListeners()
    {
        _jSlider.addChangeListener(这个);
    }

    @覆盖
    公共无效状态更改(更改事件 ce)
    {
        双缩放因子 = _jSlider.getValue() / 100.0D;
        _jSlider.setZoomFactor(zoomFactor);

        维度大小 = ViewFunctions.instance().getNewDimension(_dimen, null, zoomFactor);
        _jSlider.setBounds(_jSlider.getX(), _jSlider.getY(),
                            (int) size.getWidth(), (int) size.getHeight());
    }

    公共静态点getCenteredLocationForComponent(组件comp)
    {
        int 宽度 = java.awt.Toolkit.getDefaultToolkit().getScreenSize().width;
        int height = java.awt.Toolkit.getDefaultToolkit().getScreenSize().height;
        点结果 = new Point(width/2 - comp.getWidth()/2, height/2 - comp.getHeight()/2);

        返回(结果);
    }
}

其他类:

导入 java.awt.image.BufferedImage;
导入 java.awt.image.ColorModel;
导入 java.awt.image.DataBuffer;
导入 java.awt.image.Raster;

/**
 *
 * @作者乌苏里奥
 */
公共类 ImageFunctions
{
    public static BufferedImage resizeImage( BufferedImage original, int width, int height, Integer switchColorFrom,
                                            整数 switchColorTo,整数 alphaForPixelsDifferentFromColorFrom )抛出 IllegalArgumentException
    {
        整数阿尔法= 0xFF000000;
        if( alphaForPixelsDifferentFromColorFrom != null )
            alpha = ( (alphaForPixelsDifferentFromColorFrom) & 0xFF ) 颜色模型。只有 8 位精度
    * 当返回数据中的每个颜色分量
    * 使用这种方法。在指定坐标 (x, y) 中
    * 图像,ARGB 像素可以这样访问:
    * 
    *
    * 
    * 像素 = rgbArray[offset + (y-startY)*scansize + (x-startX)]; 
* *

* * 可能会抛出 ArrayOutOfBoundsException * 如果区域不在范围内。 * 但是,不能保证明确的边界检查。 * * @param startX 起始X坐标 * @param startY 起始 Y 坐标 * @param w 区域宽度 * @param h 区域高度 * @param rgbArray 如果不是 null,则 rgb 像素为 * 写在这里 * @param offset 偏移到 rgbArray * @param scansize rgbArray 的扫描线步幅 * @return RGB 像素数组。 * @see #setRGB(int, int, int) * @see #setRGB(int, int, int, int, int[], int, int) */ 公共静态int [] getRGB(int startX,int startY,int w,int h, 缓冲图像双) { ColorModel colorModel = bi.getColorModel(); 光栅 raster = bi.getRaster(); // WritableRaster raster = colorModel.createCompatibleWritableRaster(bi.getWidth(), bi.getHeight() ); int 扫描尺寸 = w; 整数偏移=0; int yoff = 偏移量; 关闭; 对象数据; int nbands = raster.getNumBands(); int dataType = raster.getDataBuffer().getDataType(); 开关(数据类型) { 案例 DataBuffer.TYPE_BYTE: 数据=新字节[nbands]; 休息; 案例 DataBuffer.TYPE_USHORT: 数据=新的短[nbands]; 休息; 案例 DataBuffer.TYPE_INT: 数据 = 新的 int[nbands]; 休息; 案例 DataBuffer.TYPE_FLOAT: 数据=新浮动[nbands]; 休息; 案例 DataBuffer.TYPE_DOUBLE: 数据=新双[nbands]; 休息; 默认: throw new IllegalArgumentException("未知数据缓冲区类型:"+ 数据类型); } int[] rgbArray = new int[offset+h*scansize]; for (int y = startY; y =0) && (x=0) && (y

公共类 IntegerFunctions
{
    公共静态 int 最大值(int i1,int i2)
    {
        返回(i1>i2?i1:i2);
    }

    公共静态int min(int i1,int i2)
    {
        返回( i1=0 ? ii : -ii );
    }

    公共静态 int sgn( int ii )
    {
        返回( ii>0 ? 1 : ( ii

导入 java.awt.Dimension;
导入 java.awt.Insets;
导入 java.awt.Point;
导入 java.awt.Rectangle;

/**
 *
 * @作者乌苏里奥
 */
公共类 ViewFunctions
{
    受保护的静态 ViewFunctions _instance;

    公共静态 ViewFunctions 实例()
    {
        如果(_instance == null)
            _instance = new ViewFunctions();
        返回(_instance);
    }

    public Dimension getNewDimension( Dimension dim, Insets insets, double zoomFactor )
    {
        维度结果 = null;

        如果(暗淡!=空)
        {
            如果(插图 == 空)
                插图 = 新插图(0,0,0,0);

            int insetsWidth = insets.left + insets.right;
            int insetsHeight = insets.top + insets.bottom;
            结果 = new Dimension( (int) ( zoomFactor * ( dim.getWidth() - insetsWidth ) + insetsWidth ),
                                    (int) ( zoomFactor * ( dim.getHeight() - insetsHeight ) + insetsHeight ) );
        }

        返回(结果);
    }

    public Rectangle getNewRectangle( Rectangle rect, Insets insets, double zoomFactor )
    {
        矩形结果 = null;

        如果(矩形!=空)
        {
            如果(插图 == 空)
                插图 = 新插图(0,0,0,0);

            int insetsWidth = insets.left + insets.right;
            int insetsHeight = insets.top + insets.bottom;
            结果 = 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 ) );
        }

        返回(结果);
    }

    public Insets getNewInsets( Insets insets, double zoomFactor )
    {
        插入结果 = null;

        如果(插入!= null)
        {
            结果 = new Insets( (int) ( insets.top * zoomFactor ),
                                    (int) ( insets.left * zoomFactor ),
                                    (int) ( insets.bottom * zoomFactor ),
                                    (int) ( insets.right * zoomFactor ) );
        }

        返回(结果);
    }

    公共点getCenter(矩形矩形)
    {
        点结果 = null;

        如果(矩形!=空)
        {
            结果 = 新点 ( (int) ( rect.getX() + rect.getWidth() / 2 ),
                                (int) ( rect.getY() + rect.getHeight() / 2 ) );
        }

        返回(结果);
    }

    public Rectangle calculateNewBounds( Rectangle originalBounds, Insets insets, Point center, double zoomFactor )
    {
        矩形结果 = null;

        如果(原始边界!= null)
        {
            如果(插图 == 空)
                插图 = 新插图(0, 0, 0, 0);

            int newX = (int) originalBounds.getX();
            int newY = (int) originalBounds.getY();
            如果(中心!=空)
            {
                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 );
            }

            结果=新矩形(新X,
                                    新Y,
                                    (int) ( ( originalBounds.getWidth() - insets.left - insets.right ) * zoomFactor + insets.left + insets.right ),
                                    (int) ( ( originalBounds.getHeight() - insets.top - insets.bottom ) * zoomFactor + insets.top + insets.bottom )
                                    );
        }

        返回(结果);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 2010-09-20
    • 1970-01-01
    • 2015-09-10
    • 2010-10-31
    • 2011-11-08
    相关资源
    最近更新 更多