Frage

Ich versuche, eine bereits bestehende Komponente nachzuahmen (oder eine bereits bestehende Komponente zu finden), die den Zoom -Schieberegler von Word 2007 nachahmt:

Two state zoom bar

Es gibt zwei Hauptunterschiede zwischen dieser Komponente und einem Standard -Java Jslider:

  1. Schnapp
  2. Slider ist nicht den ganzen Weg über linear: Die linke Hälfte des Sliders geht von 10% bis 100%; Die rechte Seite geht von 100% bis 500%.

Hier ist, was ich bisher habe:Java clone

Quelle:

    import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 *
 * @author NDUNN
 * @date Nov 25, 2009
 */
public class ZoomBar extends JPanel implements ActionListener, ChangeListener {

    private JLabel zoomAmount;
    private JButton minus;
    private JButton plus;
    private JSlider slider;

    private static final int MIN_ZOOM = 10;
    private static final int MAX_ZOOM = 200;
    private static final int DEFAULT_ZOOM = 100;

    private static final int MAJOR_ZOOM_SPACING = 50;
    private static final int MINOR_ZOOM_SPACING = 10;

    public ZoomBar() {
        super();

        minus = new JButton("-");
        plus = new JButton("+");
        slider = new JSlider(MIN_ZOOM, MAX_ZOOM, DEFAULT_ZOOM);

        slider.setMinorTickSpacing(MINOR_ZOOM_SPACING);
        slider.setMajorTickSpacing(MAJOR_ZOOM_SPACING);
        slider.setPaintTicks(true);
        slider.setSnapToTicks(true);

        zoomAmount = new JLabel(slider.getValue() + "%");

        add(zoomAmount);
        add(minus);
        add(slider);
        add(plus);

        plus.addActionListener(this);
        minus.addActionListener(this);

        slider.addChangeListener(this);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Zoom bar clone");
        frame.setContentPane(new ZoomBar());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == plus) {
            slider.setValue(slider.getValue() + MINOR_ZOOM_SPACING);
        }
        else if (e.getSource() == minus) {
            slider.setValue(slider.getValue() - MINOR_ZOOM_SPACING);
        }
    }

    public void stateChanged(ChangeEvent e) {
        if (slider.getValueIsAdjusting()) {
            return;
        }
        zoomAmount.setText(slider.getValue() + "%");
    }

}

Grundsätzlich nur den Look nachahmen, aber ohne diese beiden oben genannten Funktionen. Ich sehe nichts in der Jslider -API Das ermöglicht mir, dieses Verhalten zu bekommen. Müsste ich von vorne anfangen, um dieses Verhalten zu bekommen? Wenn ja, ist es meine Zeit nicht wert, aber wenn jemand einen guten Weg kennt, um dieses Verhalten zu erhalten, wäre es schön, in dem Projekt, an dem ich arbeite, zu haben.

Vielen Dank,

Nick


BEARBEITEN:

Vielen Dank an PSPEED für die Idee, nur die 0..50 und 50..100 auf verschiedene Werte zuzuordnen. Der Code dazu ist unten.

Leider hat die Idee, das SetValue in Snap zu ändern, nicht funktioniert.

public void stateChanged(ChangeEvent e) {
    // While slider is moving, snap it to midpoint
    int value = slider.getValue();
    if (slider.getValueIsAdjusting()) {
        return;
    }

    zoomValue = fromSlider(value);
    zoomLabel.setText(zoomValue + "%");
}

public int fromSlider(int sliderValue) {
    int mappedValue = 0;
    if (sliderValue <= 50) {
        // Map from [0, 50] to [MIN ... DEFAULT]
        mappedValue = (int) map(sliderValue, 0, 50, MIN_ZOOM, DEFAULT_ZOOM);
    }
    else {
        // Convert from  (50, 100] to (DEFAULT ... MAX]
        mappedValue = (int) map(sliderValue, 50, 100, DEFAULT_ZOOM, MAX_ZOOM);
    }
    return mappedValue;
}

public int toSlider(int modelValue) {
    int mappedValue = 0;
    if (modelValue <= DEFAULT_ZOOM) {
        // Map from [MIN_ZOOM, DEFAULT_ZOOM] to [0 ... 50]
        mappedValue = (int) map(modelValue, MIN_ZOOM, DEFAULT_ZOOM, 0, 50);
    }
    else {
        // Convert from  (DEFAULT ... MAX] to (50, 100]
        mappedValue = (int) map(modelValue, DEFAULT_ZOOM, MAX_ZOOM, 50, 100);
    }
    return mappedValue;
}


/**
 * @param value The incoming value to be converted
 * @param low1  Lower bound of the value's current range
 * @param high1 Upper bound of the value's current range
 * @param low2  Lower bound of the value's target range
 * @param high2 Upper bound of the value's target range
 * @return
 */
public static final double map(double value, double low1, double high1, double low2, double high2) {

    double diff = value - low1;
    double proportion = diff / (high1 - low1);

    return lerp(low2, high2, proportion);
}

public static final double lerp(double value1, double value2, double amt) {
    return ((value2 - value1) * amt) + value1;
}

Bearbeiten 2: Ein weiterer Unterschied, den ich bemerke, ist, dass ein Jbutton Sie nicht mehrmals an Feuerknopf gedrückt halten, während die +/- Schaltflächen im Büro dies tun. Irgendeine Idee, wie man das nachahmt?

War es hilfreich?

Lösung

Ich glaube, Sie können all dieses Verhalten mit einem benutzerdefinierten Boundedrangemodel bekommen. Der Schlüssel besteht darin, den Modell Bericht zu einem normalen Wertebereich zu machen, aber es anders behandelt, wenn Sie Ihren Zoomfaktor möchten.

Wenn Sie beispielsweise Ihren Bereich von 0 bis 100 laufen lassen, würden Sie 0-50 und 50-100 auf andere Weise behandeln (10-100% bzw. 100-500%).

Um das Snap -Verhalten zu erhalten, bin ich mir ziemlich sicher, dass Sie SetValue () einfach überschreiben können, um den gewünschten Bereich zu erreichen. Wenn Sie also 0-100 als Wertebereich verwenden, wird der Wert auf 50 auf 50.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top