JSlider в JTable

Чтобы поместить JSlider в JTable, я написал am AbstractCellEditor, который реализует TableCellRenderer и TableCellEditor. Он инициализируется значениями от 0 до 100.

У меня странное поведение, когда я впервые нажимаю на ползунок, он подскакивает до максимума.

Второе странное поведение: я добавил ChangeListener. Этот прослушиватель вызывается только в том случае, если я сначала нажимаю на ползунок. Второй щелчок (который также изменяет значение) не вызывает это событие. Почему?

public class SliderTableColumn extends AbstractCellEditor implements TableCellRenderer,
                                                                     TableCellEditor

{
    private final JSlider slRenderer;
    private final JSlider slEditor;

    private final int INITAL_VALUE;
    private final int MIN_VLAUE;
    private final int MAX_VALUE;

    public SliderTableColumn(int min, int max, int initial, ChangeListener listener)
    {
        INITAL_VALUE = initial;
        MIN_VLAUE    = min;
        MAX_VALUE    = max;

        slRenderer = new JSlider(MIN_VLAUE, MAX_VALUE);
        slEditor   = new JSlider(MIN_VLAUE, MAX_VALUE);

        slEditor.addChangeListener(listener);

        slRenderer.setUI(new CustomSliderUI(slRenderer, INITAL_VALUE));
        slEditor.setUI(new CustomSliderUI(slEditor,     INITAL_VALUE));

        slRenderer.setValue(INITAL_VALUE);
        slEditor.setValue(INITAL_VALUE);
    }

    @Override
    public Object getCellEditorValue()
    {
        return slEditor.getValue();
    }

    @Override
    public Component getTableCellRendererComponent(JTable table,
                                                Object value,
                                                boolean isSelected,
                                                boolean hasFocus,
                                                int row,
                                                int column)
    {
        if(value != null)
        {
            slRenderer.setValue(((Integer) value).intValue());
        }
        return slRenderer;
    }

    @Override
    public Component getTableCellEditorComponent(JTable table,
                                                Object value,
                                                boolean isSelected,
                                                int row,
                                                int column)
    {
        if(value != null)
        {
            slEditor.setValue(((Integer) value).intValue());
        }
        return slEditor;
    }
}

person Razer    schedule 13.01.2012    source источник


Ответы (1)


В отсутствие вашего sscce я размышляю; но я могу предложить две вещи для критического рассмотрения:

  1. В getTableCellEditorComponent() фактический параметр value исходит из вашей модели таблицы. Ваш вызов setValue() перенаправляет value в модель диапазона ползунка. value вне допустимого диапазона прикрепляется к экстремально.

  2. Ваш ChangeListener должен fireEditingStopped(), как показано в ItemListener этого связанного примера.

person trashgod    schedule 14.01.2012
comment
Спасибо. Пункт 2 исправлен. Проблема 1, кажется, что-то еще. Я использую scrollDueToClickInTrack() для перехода к текущей позиции. Это использует внутренне trackRect.width, который имеет неправильное значение в первый раз. Щелкнув ползунок во второй раз, он инициализируется правильно, и ползунок переместится в нужное положение. - person Razer; 14.01.2012
comment
Я смущен. Похоже, ваш редактор уже делает setValue(). - person trashgod; 15.01.2012
comment
Я просто исправил это, вызвав super.calculateGeometry() перед `scrollDueToClickInTrack(). Это вычисляет правильный tracRect, и этот переход к позиции работает. - person Razer; 15.01.2012
comment
Рад, что вы разобрались, но мне любопытно: зачем вообще переопределять scrollDueToClickInTrack()? - person trashgod; 15.01.2012
comment
scrollDueToClickInTrack()обычно увеличивает только ползунок. Я хочу, чтобы ползунок сразу переходил в положение, в котором он щелкнул. - person Razer; 15.01.2012