Java Swing滑块标签不根据滑块最小/最大值进行更新

4

当JSlider的最小值和最大值发生变化时,标签表没有相应更新。通过调用getMinimum()和getMaximum()方法可以正确地更新最小/最大值。滑块下面的自动标签显示错误的值。

以下是一个独立的示例,出现了这个问题。该代码大部分是由Eclipse窗口构建器/Swing设计器自动生成的。

按下滑块两侧的按钮会更改滑块的最大值。

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;

import java.awt.BorderLayout;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JSlider;
import javax.swing.JLabel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class SliderTrouble implements ActionListener
{

    private JFrame frame;
    private JSlider slider;
    private JLabel lblMin;
    private JLabel lblMax;
    private JLabel lblCurrent;
    private int sliderMax = 100;
    private int sliderMajorSpacing = sliderMax / 4;

    /**
     * Launch the application.
     */
    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                try
                {
                    SliderTrouble window = new SliderTrouble();
                    window.frame.setVisible(true);
                } catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public SliderTrouble()
    {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize()
    {
        frame = new JFrame();
        frame.setTitle("Slider problems");
        frame.setBounds(100, 100, 481, 122);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new BorderLayout(0, 0));

        JPanel panel = new JPanel();
        frame.getContentPane().add(panel, BorderLayout.CENTER);

        JButton btnNewButton = new JButton("100");
        btnNewButton.setBounds(10, 22, 64, 23);
        btnNewButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                System.out.println("Pressed 100. Since this is the default value, everything is ok.");
                sliderMax = 100;
                sliderMajorSpacing = sliderMax / 4;
                changeSlider(sliderMax, sliderMajorSpacing);
            }
        });
        panel.setLayout(null);
        panel.add(btnNewButton);

        class SliderListener implements ChangeListener
        {
            public void stateChanged(ChangeEvent e)
            {
                JSlider slider = (JSlider) e.getSource();
                if (slider.getValueIsAdjusting())
                {
                    updateCurrent(slider.getValue());
                }
            }
        }

        slider = new JSlider();
        slider.setBounds(79, 11, 300, 45);
        slider.setMajorTickSpacing(sliderMajorSpacing);
        slider.setPaintTicks(true);
        slider.setPaintLabels(true);
        slider.setMaximum(sliderMax);
        slider.addChangeListener(new SliderListener());
        panel.add(slider);

        JButton btnNewButton_1 = new JButton("196");
        btnNewButton_1.setBounds(389, 22, 62, 23);
        btnNewButton_1.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                System.out.println("Pressed 196. The actual minimum and maximum values are updated correctly. getValue gets the correct value. The little gray tick lines are not updated accordingly. The text labels are done according to the default (button '100') settings, showing a max at 175 instead of 196. 175 is the closest multiple of 25 (which is the default major tick space).");
                sliderMax = 196;
                sliderMajorSpacing = sliderMax / 4;
                changeSlider(sliderMax, sliderMajorSpacing);
            }
        });

        panel.add(btnNewButton_1);

        JPanel panel_1 = new JPanel();
        frame.getContentPane().add(panel_1, BorderLayout.SOUTH);

        JLabel lblSliderMin = new JLabel("Slider min:");
        panel_1.add(lblSliderMin);

        lblMin = new JLabel();
        lblMin.setText(String.valueOf(slider.getMinimum()));
        panel_1.add(lblMin);

        JLabel lblMax_1 = new JLabel("max:");
        panel_1.add(lblMax_1);

        lblMax = new JLabel();
        lblMax.setText(String.valueOf(slider.getMaximum()));
        panel_1.add(lblMax);

        JLabel lblCur = new JLabel("current:");
        panel_1.add(lblCur);

        lblCurrent = new JLabel();
        lblCurrent.setText(String.valueOf(slider.getValue()));
        panel_1.add(lblCurrent);

        //frame.pack();
    }

    private void changeSlider(int max, int majspace)
    {
        slider.setMajorTickSpacing(majspace);
        slider.setMaximum(max);

        System.out.println("max: " + max + " major: " + sliderMajorSpacing);

        updateText(slider.getMinimum(), slider.getMaximum(), slider.getValue());
    }

    private void updateText(int minimum, int maximum, int value)
    {
        lblMin.setText(String.valueOf(minimum));
        lblMax.setText(String.valueOf(maximum));
        lblCurrent.setText(String.valueOf(value));
    }

    private void updateCurrent(int value)
    {
        lblCurrent.setText(String.valueOf(value));
    }

    public void actionPerformed(ActionEvent arg0)
    {   
    }
}

你期望标签显示什么?刻度间距为25,因此可以显示的最大值为175,对于196个长范围来说。 - kiheru
主要的刻度间距在changeSlider方法中被改变,该方法在其中一个按钮被按下时被调用。我期望标签在刻度间距改变时也会随之改变。 - Demian Wright
1个回答

6

看起来,当在一个已有标签集的滑动条上调用setMajorTickSpacing()时,它实际上并没有更新任何内容。这可以通过调用以下方法进行解决:

slider.setLabelTable(null);

在设置新的刻度间距之前,强制重新创建标签。

我本来以为我试过了那个方法。这解决了问题。谢谢。 - Demian Wright

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接