Frage

Ich bin mit einem JSlider Fortschritt in meiner Anwendung zu zeigen, so dass sie aktualisiert als ein bestimmte Prozess berechnet.

Ich möchte ein Benutzer in der Lage sein, den Daumen nach hinten zu einem Häkchen in der Vergangenheit zu ziehen, aber wenn dies geschieht, möchte ich die Fortschrittsanzeige an der aktuellen Position bleiben.

// A dismal attempt at drawing the situation
Progress: ---------
Thumb:            |

// User drags backwards.  What I have:
Progress: ---
Thumb:       |

// What I want instead:
Progress: ---------
Thumb:       |

Kann jemand eine Anleitung für bieten, wie man dies am besten erreichen? Vielen Dank im Voraus für alle Hilfe!

War es hilfreich?

Lösung 2

ich es herausgefunden. Ich verlängerte JSlider den Überblick über den Fortschritt von der aktuellen Position Daumen getrennt zu halten und überwog dann die paintTrack Methode des MetalSliderUI zu ziehen, um die Spur auf die Position füllen ich will.

Hier ist die Lösung, die wichtigen Teile abgespeckte.

Der neue Fortschrittsbalken:

public class ProgressSlider extends JSlider {
    protected int progress;
    private static final String uiClassID = "ProgressSliderUI";

    public ProgressSlider() {
        progress = 0;
        putClientProperty("JSlider.isFilled", Boolean.TRUE);
        updateUI();
    }
    public void updateUI() {
        setUI(new ProgressSliderUI(this));
    }
    public String getUIClassID() {
        return uiClassID;
    }

    public int getProgress() {
        return this.progress;
    }

    public void setProgress(int value) {
        if (value < this.getMinimum()) {
            this.progress = this.getMinimum();
        }
        else if (value > this.getMaximum()) {
            this.progress = this.getMaximum();
        }
        else {
            this.progress = value;
        }
    }
}

Die neue Benutzeroberfläche: Beachten Sie, dass es nur 2 Zeilen hinzugefügt, um den paintTrack () -Methode in der UI-Klasse waren, sofort den Kommentar folgenden sagt so.

public class ProgressSliderUI extends MetalSliderUI {

    public ProgressSliderUI() {
        super();
    }

    public ProgressSliderUI(JSlider b) {
    }

    @Override
    public void paintTrack(Graphics g) {
        Color trackColor = !slider.isEnabled() ? MetalLookAndFeel
                .getControlShadow() : Color.blue;

        boolean leftToRight = true;

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

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

        // 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 = 0;
            int fillTop = 0;
            int fillLeft = 0;
            int fillBottom = 0;
            int fillRight = 0;

            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;

                    // THIS IS THE CHANGE OF NOTE:
                    // Fills the progress with the value from the custom slider
                    fillRight = xPositionForValue(((ProgressSlider) slider)
                            .getProgress());
                    fillRight -= trackRect.x;
                }
                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(trackColor);
                g.fillRect(fillLeft + 1, fillTop + 1, fillRight
                                - fillLeft, fillBottom - fillTop);
            }
            else {
                g.setColor(MetalLookAndFeel.getControlShadow());
                g.fillRect(fillLeft, fillTop, fillRight - fillLeft, 
                                      trackBottom - trackTop);
            }
        }

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

}

Und für den Fahrer zu testen:

public class ProgressExample extends JFrame
{
    public ProgressExample()
    {
        super("Progress Example");

        ProgressSlider mSlider = new ProgressSlider();
        mSlider.setMinimum(0);
        mSlider.setMaximum(100);
        mSlider.setValue(20);
        mSlider.setProgress(50);

        getContentPane().setLayout(new FlowLayout());
        getContentPane().add(slider);
        getContentPane().add(mSlider);
    }
    public static void main(String args[])
    {
        ProgressExample f = new ProgressExample();
        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e)
            {
                System.exit(0);
            }
        });
        f.setSize(300, 80);
        f.show();
    }
}

Andere Tipps

Ah, ich sehe, was Sie meinen. Leider gibt es keine Möglichkeit, das zu tun.

Die ‚Blue Bar“ ist nicht wirklich ein Teil JSlider, es ist Teil des Metall LAF ist. Es ist einfach die Art und Weise der Metall LAF entschied sich für die Komponente zu malen. Wenn Sie es mit einem anderen LAF versuchen Sie nicht bekommen, die Bar an alle.

Sie werden zu koppeln benötigen ein JProgressBar und ein JSlider zu bekommen, was Sie wollen.

Hier ist ein Ausgangspunkt. Sie müssen es zwicken, um es richtig zu sehen

import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.event.ChangeListener;

public class ProgressSlider extends javax.swing.JPanel
{
    private JProgressBar progressBar;
    private JSlider slider;
    public ProgressSlider() {
        this(0, 100);
    }
    public ProgressSlider(int min, int max) {
        setLayout(new GridBagLayout());

        GridBagConstraints gbc;
        gbc = new GridBagConstraints();
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        slider = new JSlider(min, max, min);
        progressBar = new JProgressBar(min, max);
        add(slider, gbc);
        add(progressBar, gbc);
    }
    public void setValue(int n) {
        boolean adjSlider = slider.getValue() == progressBar.getValue();
        progressBar.setValue(n);
        if (adjSlider)
            slider.setValue(n);
    }
    public int getValue() {
        return progressBar.getValue();
    }
    public int getSliderValue() {
        return slider.getValue();
    }
    public void syncSlider() {
        slider.setValue(progressBar.getValue());
    }
    public void addChangeListener(ChangeListener l) {
        slider.addChangeListener(l);
    }
    public void removeChangeListener(ChangeListener l) {
        slider.removeChangeListener(l);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame jf = new JFrame();
                jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                final ProgressSlider ps = new ProgressSlider();
                final JTextField tf = new JTextField(4);
                final JButton jb = new JButton(new AbstractAction("Set") {
                    public void actionPerformed(ActionEvent e) {
                        ps.setValue(Integer.parseInt(tf.getText()));
                    }});
                JPanel jp = new JPanel();
                jp.add(tf);
                jp.add(jb);
                jf.getContentPane().add(ps, BorderLayout.CENTER);
                jf.getContentPane().add(jp, BorderLayout.SOUTH);
                jf.pack();
                jf.setVisible(true);
            }
        });
    }
}

Nun, ich sehe nicht, wie dies möglich ist. Sie müssen die Slider UI anpassen und das Modell ändern, weil nicht Sie, um zwei Stücke von Modellinformationen benötigen, der „Spur Wert“ und der „Daumen-Wert“.

Wenn Sie eine große Kerbe wollen, dann malen Sie zwei Schieberegler auf aufeinander. Der untere Schieber würde für den Track-Wert sein und die obere für den Daumen Wert wäre.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.metal.*;

public class SliderTest extends JFrame
{
    public SliderTest()
    {
        JSlider bottom = createSlider();
        bottom.setUI( new MySliderUI1() );

        JSlider top = createSlider();
        top.setUI( new MySliderUI2() );
        top.setOpaque(false);

        JPanel panel = new JPanel();
        panel.setLayout( new OverlapLayout() );
        panel.add( bottom );
        panel.add( top );

        getContentPane().add( panel );
    }

    private JSlider createSlider()
    {
        JSlider slider = new JSlider(2, 50);
        slider.createStandardLabels(10, 5);
        slider.setMajorTickSpacing(10);
        slider.setPaintTicks(true);
        slider.setPaintLabels(true);
        slider.setValue(20);

        return slider;
    }

    class MySliderUI1 extends MetalSliderUI
    {
        public void paintThumb(Graphics g) {}
    }

    class MySliderUI2 extends MetalSliderUI
    {
        public void paintTrack(Graphics g) {}
    }

    public static void main(String[] args)
    {
        JFrame frame = new SliderTest();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible( true );
     }
}

Sie müssen auch das Overlap-Layout . Wie man sie synchron zu halten würde bis zu Ihnen sein. Die Lösung hat viele Mängel, aber es kann Ihnen ein paar Ideen.

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