سؤال

أنا أستخدم JSLider لإظهار التقدم في طلبي، بحيث يتم تحديثه كحسبات عملية معينة.

أريد أن يكون المستخدم قادرا على سحب الإبهام إلى الوراء إلى علامة علامة في الماضي، ولكن عندما يحدث هذا، أريد أن يبقى مؤشر التقدم في موقعه الحالي.

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

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

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

هل يمكن لأي شخص تقديم أي إرشادات لكيفية تحقيق هذا الأمر؟ شكرا مقدما على كل المساعدة!

هل كانت مفيدة؟

المحلول 2

اكتشفتها. قمت بمحدد JSLIDER لتتبع التقدم المحرز بشكل منفصل عن موضع الإبهام الحالي، ثم تجاوز طريقة أردد metalsliderui لرسم المسار إلى الموضع الذي أريده.

إليك الحل، جردت الأجزاء المهمة.

شريط التقدم الجديد الجديد:

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

واجهة المستخدم الجديدة: ملاحظة، كانت هناك سطرين فقط إضافة إلى طريقة الطلاء () في فئة UI، على الفور بعد التعليق يقول ذلك.

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

}

وللاسة السائق لاختبارها:

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

نصائح أخرى

آه، أرى ما تقصد. لسوء الحظ، لا توجد طريقة للقيام بذلك.

"البار الأزرق" ليس جزءا حقا من JSLIDER، إنه جزء من المعدن Laf. إنها مجرد طريقة اختارت شركة Laf المعدنية ترسم المكون. إذا جربتها مع LAF آخر، فلن تحصل على الشريط على الإطلاق.

ستحتاج إلى إزاحة JPRogressBar و JSLIDER للحصول على ما تريد.

ها هي نقطة انطلاق. ستحتاج إلى تعديلها للحصول عليه للنظر

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

حسنا، لا أرى كيف يمكن ذلك. ستحتاج إلى تخصيص شريط التمرير واجهة المستخدم وتغيير النموذج لأنه لا تحتاج إلى تخزين قطعتين من المعلومات النموذجية، و "قيمة المسار" و "قيمة الإبهام".

إذا كنت تريد اختراق كبير، فأنت ترسم اثنين من المتزلجين على رأس بعضهم البعض. سيكون شريط التمرير السفلي لقيمة المسار وأعلى قيمة الإبهام.

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

سوف تحتاج أيضا تخطيط التداخل. وبعد كيف تبقيها في مزامنة ستكون متروك لك. الحل لديه العديد من العيوب، ولكن قد يعطيك بعض الأفكار.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top