0

短い:
ノブのない JSlider に不明な値を設定することは可能ですか?

Long :
Java Swing で開発されたデスクトップ クライアントを含むプロジェクトに取り組んでおり、ユーザーはスライダーを使用していくつかのパラメーターを測定する必要があります。それは要件であり、スライダーでなければなりません。
ユーザーがスライダーを操作するまで、値は不明である必要があります。つまり、ノブが表示されません。それも要件です。
ノブを使用する場合JSlider、ノブは常に表示されint、オブジェクトではなくプリミティブ型を使用するため、範囲外の値を設定したり、null に設定したりする方法はありませんInteger
ヌルの失敗値または少なくともノブを表示しない値を設定する方法はありますか? そうすることを可能にする拡張機能はありますか?

4

2 に答える 2

2

独自の実装を作成BasicSliderUIしてオーバーライドpaintThumb(Graphics g)し、必要なことを行います。

こちらもご覧ください: jSliderのノブを非表示にする方法?

于 2013-02-22T08:47:54.763 に答える
1

ハリー・ジョイの助けを借りてノブを隠し、ついに問題を解決することができました.

BasicSliderUI.paintThumb(Graphics)Harry's answer を確認すると、ノブを非表示にするメソッドのオーバーライドについて読むことができます。Synth (つまり Nimbus を意味する) に基づいていないほとんどの L&F で問題なく動作し、アプローチは異なりますが、L&F のカスタマイズを介して実行できます。

それをインストールするのは少しトリッキーです: L&F の変更をチェックし、コンポーネントに適切な UI デリゲートをインストールする を持っていると、魔法のようになります (このソリューションでは、他のものに基づいたものをコピーして貼り付けているだけですPropertyChangeListener) 。 . また、最初にクリックされた位置に値を設定するように少し調整しました。デリゲートがノブをペイントする必要があるかどうかを知るために、呼び出された にクライアント プロパティを設定することにしました。このように、デリゲートは、拡張されたものだけでなく、任意の にインストールできます。UIManagerBasicSliderUIJSlider"ready"booleanJSlider

では、未知の値を管理するにはどうすればよいでしょうか。別の新しいプロパティを追加すると、これはとの両方のタイプ"selectedValue"にバインドされます。であるかどうかに応じて、またはその逆であり、準備ができていない限り、 と の両方が同じ値 (一方が であり、もう一方が )を保持します。これにより、 が に設定されます。複雑に聞こえるかもしれませんが、そうではありません。また、[Esc] で値をクリアし、実装されたコンポーネントにプロパティを伝達するための微調整もあります。"value""ready"Integer"ready"falsetruenull"value""selectedValue"intInteger"selectedValue"null

コードは次のとおりです。

BasicSliderUIExt

import java.awt.Graphics;
import java.awt.event.MouseEvent;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.plaf.basic.BasicSliderUI;

public class BasicSliderUIExt extends BasicSliderUI {

    public BasicSliderUIExt(JSlider slider) {
        super(slider);
    }

    @Override
    public void paintThumb(Graphics g) {
        if (isReady(super.slider)) {
            super.paintThumb(g); 
        }
    }

    @Override
    protected TrackListener createTrackListener(final JSlider slider) {
        return new TrackListener() {
            @Override
            public void mousePressed(MouseEvent event) {
                if (isReady(slider)) {
                    super.mousePressed(event);
                } else {
                    JSlider slider = (JSlider) event.getSource();
                    switch (slider.getOrientation()) {
                    case SwingConstants.VERTICAL:
                        slider.setValue(valueForYPosition(event.getY()));
                        break;
                    case SwingConstants.HORIZONTAL:
                        slider.setValue(valueForXPosition(event.getX()));
                        break;
                    }
                    super.mousePressed(event);
                    super.mouseDragged(event);
                }
            }

            @Override
            public boolean shouldScroll(int direction) {
                if (isReady(slider)) {
                    return super.shouldScroll(direction);
                }

                return false;
            }};
    }

    public static boolean isReady(JSlider slider) {
        Object ready = slider.getClientProperty(JSliderExt.READY_PROPERTY);
        return (ready == null) || (!(ready instanceof Boolean)) || (((Boolean) ready).booleanValue());
    }

}

JSliderExt

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.Constructor;
import javax.swing.BoundedRangeModel;
import javax.swing.JSlider;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.SliderUI;

public class JSliderExt extends JSlider {

    private static final long serialVersionUID = 1L;

    public static final String EXTENT_PROPERTY = "extent";
    public static final String MAXIMUM_PROPERTY = "maximum";
    public static final String MINIMUM_PROPERTY = "minimum";
    public static final String READY_PROPERTY = "ready";
    public static final String SELECTED_VALUE_PROPERTY = "selectedValue";
    public static final String VALUE_PROPERTY = "value";

    public static final boolean READY_DEFAULT_VALUE = false;

    protected SliderUI uix = new BasicSliderUIExt(this);

    public JSliderExt(BoundedRangeModel model, boolean ready) {
        super(model);

        init(ready);
    }

    public JSliderExt(BoundedRangeModel model) {
        super(model);

        init(READY_DEFAULT_VALUE);
    }

    public JSliderExt(int orientation, int minimmum, int maximum, int value, boolean ready) {
        super(orientation, minimmum, maximum, value);

        init(ready);
    }

    public JSliderExt(int orientation, int minimmum, int maximum, int value) {
        super(orientation, minimmum, maximum, value);

        init(READY_DEFAULT_VALUE);
    }

    public JSliderExt(int minimmum, int maximum, int value, boolean ready) {
        super(minimmum, maximum, value);

        init(ready);
    }

    public JSliderExt(int minimmum, int maximum, int value) {
        super(minimmum, maximum, value);

        init(READY_DEFAULT_VALUE);
    }

    public JSliderExt(int minimmum, int maximum, boolean ready) {
        super(minimmum, maximum);

        init(ready);
    }

    public JSliderExt(int minimmum, int maximum) {
        super(minimmum, maximum);

        init(READY_DEFAULT_VALUE);
    }

    public JSliderExt(int orientation, boolean ready) {
        super(orientation);

        init(ready);
    }

    public JSliderExt(int orientation) {
        super(orientation);

        init(READY_DEFAULT_VALUE);
    }

    public JSliderExt(boolean ready) {
        super();

        init(ready);
    }

    public JSliderExt() {
        super();

        init(READY_DEFAULT_VALUE);
    }

    private void init(boolean ready) {
        UIManager.addPropertyChangeListener(new PropertyChangeListener() { // Changes the UI delegate in L&F change
            @Override
            public void propertyChange(PropertyChangeEvent event) {
                if ("lookAndFeel".equals(event.getPropertyName())) {
                    Object newValue = event.getNewValue();
                    if ((newValue != null) && (newValue instanceof LookAndFeel)) {
                        LookAndFeel lookAndFeel = (LookAndFeel) newValue;

                        try {
                            if (lookAndFeel instanceof MetalLookAndFeel) {
                                JSliderExt.this.uix = new MetalSliderUIExt();
                            } else if (lookAndFeel instanceof com.sun.java.swing.plaf.motif.MotifLookAndFeel) {
                                JSliderExt.this.uix = new MotifSliderUIExt(JSliderExt.this);
                            } else if (lookAndFeel instanceof com.sun.java.swing.plaf.windows.WindowsLookAndFeel) {
                                JSliderExt.this.uix = new WindowsSliderUIExt(JSliderExt.this);
                            } else {
                                throw new NullPointerException("Default Look & Feel not matched");
                            }
                        } catch (Exception e) {
                            try {
                                Package sliderPackage = JSliderExt.this.getClass().getPackage();
                                String lookAndFeelName = lookAndFeel.getName();
                                if (lookAndFeelName.equals("CDE/Motif")) {
                                    lookAndFeelName = "Motif";
                                } else if (lookAndFeelName.equals("Windows Classic")) {
                                    lookAndFeelName = "Windows";
                                } else if (lookAndFeelName.startsWith("JGoodies")) {
                                    lookAndFeelName = "Basic";
                                }

                                Class<?> sliderUiType = Class.forName(sliderPackage.getName() + "." + lookAndFeelName
                                        + "SliderUIExt");

                                Constructor<?> constructor1 = null;
                                try {
                                    constructor1 = sliderUiType.getConstructor(JSlider.class);
                                } catch (Exception e3) { // Nothing to do here
                                }
                                Constructor<?> constructor0 = null;
                                try {
                                    constructor0 = sliderUiType.getConstructor();
                                } catch (Exception e3) { // Nothing to do here
                                }

                                Object sliderUi = null;
                                if (constructor1 != null) {
                                    sliderUi = constructor1.newInstance(JSliderExt.this);
                                } else if (constructor0 != null) {
                                    sliderUi = constructor0.newInstance();
                                }

                                if ((sliderUi != null) && (sliderUi instanceof SliderUI)) {
                                    JSliderExt.this.setUI((SliderUI) sliderUi);
                                }
                            } catch (Exception e2) {
                                JSliderExt.this.uix = new BasicSliderUIExt(JSliderExt.this);
                            }
                        }
                    } else {
                        JSliderExt.this.uix = new BasicSliderUIExt(JSliderExt.this);
                    }
                    updateUI();
                }
            }});

        addPropertyChangeListener(new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent event) {
                String propertyName = event.getPropertyName();

                if (READY_PROPERTY.equals(propertyName)) {
                    Object newValue = event.getNewValue();

                    if ((newValue == null) || (!(newValue instanceof Boolean)) || (((Boolean) newValue).booleanValue())) {
                        setSelectedValue(Integer.valueOf(getValue()));
                    } else {
                        setSelectedValue(null);
                    }
                } else if (SELECTED_VALUE_PROPERTY.equals(propertyName)) {
                    Object newValue = event.getNewValue();
                    System.out.println(newValue);

                    if ((newValue != null) && (newValue instanceof Integer)) {
                        int value = getValue();
                        int newSelectedValue = ((Integer) newValue).intValue();

                        if (value != newSelectedValue) {
                            setValue(newSelectedValue);
                        }

                        setReady(true);
                    } else {
                        setReady(false);
                    }

                    repaint();
                } else if (VALUE_PROPERTY.equals(propertyName)) {
                    setReady(true);

                    Object newValue = event.getNewValue();

                    if ((newValue != null) && (newValue instanceof Integer)) {
                        setSelectedValue((Integer) newValue);
                    }
                }
            }});

        addKeyListener(new KeyAdapter() { // Enables escape key for clearing value
            @Override
            public void keyPressed(KeyEvent event) {
                if (event.getKeyCode() == KeyEvent.VK_ESCAPE) {
                    JSliderExt.this.setReady(false);
                }
            }});

        setReady(ready);
    }

    @Override
    public void setValue(int value) {
        int oldValue = getValue();
        super.setValue(value);
        firePropertyChange(VALUE_PROPERTY, Integer.valueOf(oldValue), Integer.valueOf(value));
    }

    @Override
    public void setExtent(int extent) {
        int oldExtent = getExtent();
        super.setExtent(extent);
        firePropertyChange(EXTENT_PROPERTY, Integer.valueOf(oldExtent), Integer.valueOf(extent));
    }

    @Override
    public void setMinimum(int minimum) {
        int oldMinimum = getMinimum();
        super.setMinimum(minimum);
        firePropertyChange(MINIMUM_PROPERTY, Integer.valueOf(oldMinimum), Integer.valueOf(minimum));
    }

    @Override
    public void setMaximum(int maximum) {
        int oldMaximum = getMaximum();
        super.setMaximum(maximum);
        firePropertyChange(MAXIMUM_PROPERTY, Integer.valueOf(oldMaximum), Integer.valueOf(maximum));
    }

    public Integer getSelectedValue() {
        return (Integer) getClientProperty(SELECTED_VALUE_PROPERTY);
    }

    public void setSelectedValue(Integer selectedValue) {
        putClientProperty(SELECTED_VALUE_PROPERTY, selectedValue);
    }

    public boolean isReady() {
        Object ready = getClientProperty(READY_PROPERTY);
        return ((ready != null) && (ready instanceof Boolean)) ? ((Boolean) ready).booleanValue()
                : READY_DEFAULT_VALUE;
    }

    public void setReady(boolean waiting) {
        putClientProperty(READY_PROPERTY, Boolean.valueOf(waiting));
    }

    @Override
    public void updateUI() {
        setUI(this.uix);
        updateLabelUIs();
    }

}

これは Windows システムを対象としているため、このコードを使用すると、アプリケーションによってはデリゲートの選択に変更が必要になる場合があることに注意してください。前述のように、Synth/Nimbus は別の方法で作業する必要がありますが、カスタム L&F または OSX 用でも、適切なデリゲートを拡張してリスナーに追加する必要があります。

于 2013-02-25T20:55:18.833 に答える