Как создать ячейку JTable с прокручиваемым содержимым

Я хотел бы использовать JTable для отображения некоторых данных. Иногда данные могут быть немного больше, поэтому необходимо иметь возможность прокрутки внутри ячеек JTable.

Я пытаюсь сделать это с помощью приведенного ниже кода. Созданная таблица выглядит нормально, к сожалению, она не работает. Полоса прокрутки даже не реагирует на щелчки мыши.

Как я могу сделать это без «зависания» полос прокрутки?

Благодарность,

Торстен

package main;

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;

public class ScrollableCellTableTest extends JPanel {

    JTable table;
    String val = "This is my totally cool test data. ";


    public ScrollableCellTableTest() {

        setLayout(new BorderLayout());

        for (int t=0; t<10; t++)
            val+=val;

        table = new JTable(new String[][]{{val}}, new String[]{"colname"}) {
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };

        table.getColumnModel().getColumn(0)
                .setCellRenderer(new ScrollableCellRenderer());

        add(new JScrollPane(table), BorderLayout.CENTER);

    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        ScrollableCellTableTest scrollableCellTable = new ScrollableCellTableTest();
        frame.getContentPane().setLayout(new BorderLayout());
        frame.getContentPane().add(scrollableCellTable, BorderLayout.CENTER);
        frame.pack();
        frame.setLocation(500, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

}

Класс рендеринга ячеек:

package main;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.TableCellRenderer;

/**
 * Scrollable Cell Renderer.
 */
public class ScrollableCellRenderer extends JPanel implements
        TableCellRenderer {
    private List rowColHeight = new ArrayList();
    JScrollPane jScrollPane;
    JTextArea textArea = new JTextArea();

    public ScrollableCellRenderer() {
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);

        setLayout(new BorderLayout());
        add(textArea, BorderLayout.CENTER);
        jScrollPane = new JScrollPane(this);
    }

    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {

        textArea.setText(value.toString());

        adjustRowHeight(table, row, column);

        return new JScrollPane(this);
    }

    /**
     * Calculate the new preferred height for a given row, and sets the height
     * on the table.
     */
    private void adjustRowHeight(JTable table, int row, int column) {

        int cWidth = table.getTableHeader().getColumnModel().getColumn(column)
                .getWidth();
        setSize(new Dimension(cWidth, 1000));
        int prefH = getPreferredSize().height;

        // Limit the height, so scrollbars become neccessary
        prefH = Math.min(prefH, 100);


        while (rowColHeight.size() <= row) {
            rowColHeight.add(new ArrayList(column));
        }
        List colHeights = (List) rowColHeight.get(row);
        while (colHeights.size() <= column) {
            colHeights.add(new Integer(0));
        }
        colHeights.set(column, new Integer(prefH));
        int maxH = prefH;
        for (int t = 0; t < colHeights.size(); t++) {
            int colHeight = ((Integer) colHeights.get(t)).intValue();
            if (colHeight > maxH)
                maxH = colHeight;
        }
        if (table.getRowHeight(row) != maxH) {
            table.setRowHeight(row, maxH);
        }

    }
}

person user1119859    schedule 18.08.2014    source источник
comment
Рендерер используется только для рисования. Читать о TableCellEditor   -  person StanislavL    schedule 18.08.2014


Ответы (2)


Ваш подход никогда не будет работать, потому что рендерер используется только для рендеринга содержимого ячейки. Взаимодействие с визуализатором невозможно. Вы можете обеспечить взаимодействие с содержимым ячейки только с помощью редактора. К сожалению, у вас может быть только один редактор одновременно. Единственный способ обеспечить прокрутку в реальной ячейке - установить прослушиватель мыши, который делает редактируемой текущую ячейку (возможно, с небольшой задержкой). В вашем слушателе вы должны отслеживать следующие события: перемещение (сделать ячейку в точке редактируемой), вход (то же, что и для перемещения) и выход (удалить текущий редактор, если он существует). Вероятно, этот подход будет работать и без слушателя: интерфейс CellEditor определяет метод isCellEditable(EventObject anEvent). Здесь вы должны попытаться проверить, является ли событие событием мыши и его идентификатором является вход, перемещение или выход. И не забудьте определить соответствующие ячейки как редактируемые в вашей модели таблицы!

person Sergiy Medvynskyy    schedule 18.08.2014

Иногда данные могут быть немного больше

Если он лишь «немного» больше, то самое простое решение — использовать всплывающую подсказку. Есть два способа сделать это:

  1. Создайте собственный рендерер и вызовите метод setToolTipText(...) в рендерере
  2. Переопределите метод getToolTipText(...) JTable, чтобы вернуть всплывающую подсказку.
person camickr    schedule 18.08.2014