5

コンパイル可能なソースはhttp://www.splashcd.com/jtable.tarにあります。

私はこの言語に慣れていないので、これが許容される動作であるかどうかはわかりません。

受信したメッセージごとに行を表示する JTable を作成しました (20 秒ごとに約 1 つ受信します)。テーブルの列の 1 つに大量のテキストが含まれる可能性があるため、単語を折り返して行の高さを適切に設定するカスタム セル レンダラーを作成しました。

テーブルに最初の行が表示されると、ユーザーがテーブルを閉じるまで、セルレンダラーが 1 秒間に約 10 回呼び出されることを除いて、すべて期待どおりに機能します。

約 20 行を取得すると、テーブルの動作がかなり遅くなり、列のサイズ変更、上下のスクロール、または選択した行を選択した背景色でレンダリングするのに 2 ~ 8 秒かかります。

レンダラー内に print ステートメントを挿入したので、getTableCellRendererComponent メソッドが何回呼び出されているかがわかります。

ツール ヒントを無効にし、すべてのセル編集を無効にしました。新しい行が追加されるか、テーブルのサイズが変更されると、ビューを最後の行にスクロールするリスナーがあります。

画面を表示しているとき (マウスやキーボードに触れていないとき) に、getTableCellRendererComponent メソッドを 1 秒間に数回呼び出す必要がありますか?

ティア

4

3 に答える 3

10
  • あああああ

  • あなたが必要doLayout()

  • 次のレベル :-) では、ほとんど手間をかけずにMaximum visible rowsを設定することもできますJTextComponents

ここに画像の説明を入力

doLayout()

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.text.*;
//http://tips4java.wordpress.com/2008/10/26/text-utilities/
public class AutoWrapTest {

    public JComponent makeUI() {
        String[] columnNames = {" Text Area Cell Renderer "};
        Object[][] data = {
            {"123456789012345678901234567890"},
            {"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddx"},
            {"----------------------------------------------0"},
            {">>>>>>>>>>>>>dddddddddddddddddddddddddddddddddddddddddddddddddd"
                + "dddddddxdddddddddddddddddddddddddddddddddddddddddddddd"
                + "dddddddddddx>>>>>>>>>>>>>>>>>>>>>>>>>|"},
            {">>>>>>>>>>>>ddddddddddddddddddddddddddddddddddddddddddddddddddd"
                + "ddddddx>>>>>>>>>>>>>>>>>>>>>>>>>>|"},
            {"a|"},
            {">>>>>>>>bbbb>>>>>>>>>>>>>>>>>>>|"},
            {">>>>>>>>>>>>>>>>>>|"},
            {">>>>>>>>>>>>>dddddddddddddddddddddddddddddddddddddddddddddddddd"
                + "dddddddxdddddddddddddd123456789012345678901234567890dddddd"
                + "dddddddddddddddddddddddddddddddddddddx>>>>>>>>>>>>>>>>>>>>"
                + ">>>>>|"},
            {">>>>>>>>>>>>>dddddddddddddd123456789012345678901234567890dddddd"
                + "dddddddddddddddddddddddddddddddddddddxdddddddddddddd123456"
                + "789012345678901234567890dddddddddddddddddddddddddddddddddd"
                + "ddddd123456789012345678901234567890ddddx>>>>>>>>>>>>>>>>>>"
                + ">>>>>>>|"},};
        TableModel model = new DefaultTableModel(data, columnNames) {

            private static final long serialVersionUID = 1L;

            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };
        JTable table = new JTable(model) {

            private static final long serialVersionUID = 1L;

            @Override
            public void doLayout() {
                TableColumn col = getColumnModel().getColumn(0);
                for (int row = 0; row < getRowCount(); row++) {
                    Component c = prepareRenderer(col.getCellRenderer(), row, 0);
                    if (c instanceof JTextArea) {
                        JTextArea a = (JTextArea) c;
                        int h = getPreferredHeight(a) + getIntercellSpacing().height;
                        if (getRowHeight(row) != h) {
                            setRowHeight(row, h);
                        }
                    }
                }
                super.doLayout();
            }

            private int getPreferredHeight(JTextComponent c) {
                Insets insets = c.getInsets();
                View view = c.getUI().getRootView(c).getView(0);
                int preferredHeight = (int) view.getPreferredSpan(View.Y_AXIS);
                return preferredHeight + insets.top + insets.bottom;
            }
        };
        table.setEnabled(false);
        table.setShowGrid(false);
        table.setTableHeader(null);
        table.getColumnModel().getColumn(0).setCellRenderer(new TextAreaCellRenderer());
        //table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane sp = new JScrollPane(table);
        sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        sp.setPreferredSize(new Dimension(250, 533));
        JPanel p = new JPanel(new BorderLayout());
        p.add(sp);
        return p;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }

    public static void createAndShowGUI() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.getContentPane().add(new AutoWrapTest().makeUI());
        f.setLocation(100, 100);
        f.pack();
        f.setVisible(true);
    }
}

class TextAreaCellRenderer extends JTextArea implements TableCellRenderer {

    private static final long serialVersionUID = 1L;
    private final Color evenColor = new Color(230, 240, 255);

    public TextAreaCellRenderer() {
        super();
        setLineWrap(true);
        setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        if (isSelected) {
            setForeground(table.getSelectionForeground());
            setBackground(table.getSelectionBackground());
        } else {
            setForeground(table.getForeground());
            setBackground(table.getBackground());
            setBackground((row % 2 == 0) ? evenColor : getBackground());
        }
        setFont(table.getFont());
        setText((value == null) ? "" : value.toString());
        return this;
    }
}
于 2012-10-12T22:16:10.337 に答える
3

のパフォーマンスを最大限に引き出すには、が呼び出されるTableCellRendererたびにコンポーネントの新しいインスタンスを作成していないことを確認してください。getTableCellRendererコンポーネントを一度作成し、クラスのフィールドとして保存します。

また、使用する各コンポーネントに、何もしないようにオーバーライドされた次のメソッドがあることを確認する必要があります。

  • 検証
  • 無効にする
  • 再検証
  • 塗り直す
  • 火のプロパティ変更

(そして、おそらくハードコーディングしたいでしょうisOpaque)。

詳細については、http: //docs.oracle.com/javase/6/docs/api/javax/swing/tree/DefaultTreeCellRenderer.htmlを参照してください。

于 2012-10-12T18:51:15.533 に答える
1

この問題は、カスタムセルレンダラーを呼び出して無限ループに陥らせるため、カスタムセルレンダラー内にJTableのsetRowHeight()があることに起因しているようです。

現在の行の高さが計算された単語でラップされた行の高さと一致するかどうかを確認するために、チェックを追加する必要がありました。もしそうなら、私は再度setRowHeight()を試みませんでした。

修正されたコード:

import java.awt.Component;

import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.table.TableCellRenderer;

//custom cell renderer for word wrapping, but if you use, you have to
//implement zebra striping functionality which the default renderer has
public class LineWrapCellRenderer extends JTextArea implements TableCellRenderer
{
    private int numOfTimesCalled;
    @Override
    public Component getTableCellRendererComponent(
            JTable table,
            Object value,
            boolean isSelected,
            boolean hasFocus,
            int row,
            int column)
    {
        System.out.println("Line Wrap Cell Renderer Called: " + numOfTimesCalled++);
        System.out.println("row:"+ row + ", col:" + column);
//set up the row size based on the number of newlines in the text in the cell
        int fontHeight = this.getFontMetrics(this.getFont()).getHeight();
        int numWraps = value.toString().split("\r\n|\r|\n").length;
        int rowHeight = fontHeight * numWraps;
//if the calculated rowHeight is the same as the row height of row,
// then don't call setRowHeight again, as doing so will throw us into
// an infinite loop
        if(rowHeight != table.getRowHeight(row))
        {
            table.setRowHeight(row, rowHeight);

//configure word wrapping
            setWrapStyleWord(true);
            setLineWrap(true);
//use the table's font
            setFont(table.getFont());
        }
//zebra striping, because whatever cell uses this renderer loses the
//default cell renderer zebra striping
        if(isSelected)
        {
            setBackground(table.getSelectionBackground());
        }
        else
        {
            if(row%2 == 1)
            {
                setBackground(UIManager.getColor("Table.alternateRowColor"));
            }
            else
            {
                setBackground(table.getBackground());
            }
        }
        this.setText(value.toString());
        return this;
    }
}
于 2012-10-12T22:06:48.733 に答える