3

私が参照しているコードは独自のものであり、マルチキャスト サーバーが必要なため、SSCCE スニペットを投稿できません。これにより、実行可能な回答を引き出す有益な洞察が妨げられる可能性があることは理解しています...

私はJava 7 u 9でコンパイルしています。

私は現在、マルチキャスト データをリッスンし、到着時に表示する GUI アプリで JTable を使用しています。テーブルをスクロールしたり、列のサイズを変更したりすると、アプリの応答が非常に遅くなります。

コードを適切に構成したと思いました。

私はラッパー クラスを使用し、その main() 関数で、それ自体のインスタンスを作成し、コマンド ライン引数を処理し、リスナーを作成し、JFrame を作成し、JTable を返すクラスを呼び出します。これはすべて、イベント ディスパッチ スレッドの外で行われます。

次に、次の行で、invokeLater() メソッドを使用して、すべての GUI レンダリングを処理するスレッドを作成しました。JScrollPane を作成し、JTable をスクロール ペインに追加し、スクロール バーを設定し、ビューポートを設定し、スクロール モードを設定し、JScrollPane を JFrame に追加します。これはすべて、イベント ディスパッチ スレッド内で処理されます。

通常、行はかなり迅速に入力され、時折画面がフリーズします (一部の行には 30 行以上が含まれます) が、応答性は許容できるようです。ただし、列をスクロールまたはサイズ変更すると、応答が非常に遅くなります。

SwingX SwingLabs のデモを含め、私が見たすべての例は、事前にロードされた初期データセットを参照しています。ストリーミング データで JTable を使用する例が必要です。

誰かがそのような例/デモを教えてもらえますか?

これは私の main() スニペットです...

public static void main(String args[]) 
{
    final JXTrapTableGUI ttg = new JXTrapTableGUI(args);
    SwingUtilities.invokeLater(new Runnable()
    {
        public void run() 
        {
            ttg.createAndShowGUI();
        }
    });
}

PS。回答してくれたすべての人に感謝したい。このプロジェクトは 3 月 11 日まで延期されましたが、その日にすべての回答を確認します。

4

3 に答える 3

3

JTable がストリーミング データでうまく機能するとはまったく思いません。TableModelに実際のリストが含まれておらず、代わりにデータストリームへの接続が含まれている場合、イベントディスパッチスレッドから処理を切り離すなど、言及したすべての最適化手法は無関係です。

これをどのように処理しようとしたかを確認しないと、なぜ遅いのかを正確に知ることは困難です。しかし、これをレスポンシブにする方法は次のとおりです。リストを格納するListModelを作成します-ストリームへの参照ではなく、単なるリストです。別のスレッドにストリームからマルチキャスト データをキャプチャさせて、それを呼び出しましょうDataStreamCollector。次に、必要に応じて ListModeljavax.swing.Timerをチェックして更新するタイマー ( ) で実行される Thread を起動します。DataStreamCollector

ここでの私の設計では、データ ストリームとの 100% の同期よりも UI の応答性の方が重要であると想定しています。タイマーを調整すると、最新のテーブルを使用することと、レスポンシブな UI を使用することのトレードオフが可能になります。

于 2013-02-20T18:50:46.733 に答える
2

残りのメソッド

import java.awt.*;
import java.lang.reflect.*;
import java.util.*;
import javax.swing.*;

/**
 * Thread responsible for publishing changes to the Model. Sleeps for a defined
 * amount of time, waits for no activity in the UI and then users invokeAndWait
 * to publish changes.
 */
public class UpdateThread extends Thread {

    private int sleepTime;
    private int eqSleepTime;
    private int threshhold;
    private boolean updatesEnabled;
    private Runnable publishRunnable;
    private Runnable emptyRunnable;
    private GeneratorThread generator;
    private CTTableModel model;
    private Map<?, ?> lastData;
    private long notifyTime;
    private long paintTime;
    private int updateCount;
    private boolean done;

    public UpdateThread(GeneratorThread generator, CTTableModel model, 
            int sleepTime, int eqSleepTime, int threshhold) {
        super();
        setPriority(Thread.MIN_PRIORITY);
        this.sleepTime = sleepTime;
        this.eqSleepTime = eqSleepTime;
        updatesEnabled = true;
        this.threshhold = threshhold;
        this.generator = generator;
        this.model = model;
        publishRunnable = new Runnable() { 
        // Runnable used to publish changes to the event dispatching thread
            @Override
            public void run() {
                publishChangesOnEventDispatchingThread();
            }
        }; 
        // Empty runnable, used to wait until the event dispatching thread 
        // has finished processing any pending events.
        emptyRunnable = new Runnable() {
            @Override
            public void run() {
            }
        };
    }

    @Override
    public void interrupt() {
        done = true;
        super.interrupt();
    }

    @Override
    public void run() {
        while (!isInterrupted() && !done) {
            try {
                sleep(sleepTime);
                publishChanges();
            } catch (InterruptedException ie) {
            }
        }
        System.out.println("UpdateThread done");
    }

    /**
     * Publishes changes on the event dispatching thread when the system isn't
     * busy. This blocks the caller until the changes have been published.
     */
    private void publishChanges() {
        synchronized (this) {// Wait until the user isn't scrolling
            while (!updatesEnabled) {
                try {
                    wait();
                } catch (InterruptedException ie) {
                }
            }
        }
        EventQueue queue = Toolkit.getDefaultToolkit().getSystemEventQueue();
        // And wait until there are no pending events.
        while (queue.peekEvent() != null) {
            try {
                sleep(eqSleepTime);
            } catch (InterruptedException ie) {
            }
        }
        final long start = System.currentTimeMillis();
        try {
            SwingUtilities.invokeAndWait(publishRunnable);
            // publish the changes on the event dispatching thread
        } catch (InterruptedException ie) {
        } catch (InvocationTargetException ite) {
        }
        try {
        // Wait until the system has completed processing of any events we 
        // triggered as part of publishing changes.
            SwingUtilities.invokeAndWait(emptyRunnable);
        } catch (InterruptedException ie) {
        } catch (InvocationTargetException ite) {
        }
        final long end = System.currentTimeMillis();
        try {// Update the display
            SwingUtilities.invokeAndWait(new Runnable() {
                @Override
                public void run() {
                    Main.totalUpdateTime.setText("Total: " 
                            + Integer.toString((int) (end - start)));
                    Main.notifyTime.setText("Notify: " 
                            + Integer.toString((int) notifyTime));
                    Main.paintTime.setText("Paint: " 
                            + Integer.toString((int) paintTime));
                    Main.updateCount.setText("Updated: " 
                            + Integer.toString((int) updateCount));
                }
            });
        } catch (InterruptedException ie) {
        } catch (InvocationTargetException ite) {
        }
    }

    /**
     * Does the actual publishing of changes.
     */
    private void publishChangesOnEventDispatchingThread() {
        long start = System.currentTimeMillis();
        model.setBatchUpdates(true);
        Map<?, ?> data = generator.getData();
        boolean notify = !(data.size() > threshhold || 
                (lastData != null && lastData.size() + data.size() > threshhold));
        updateCount = data.size();
        if (lastData != null) {
            updateCount += lastData.size();
        }//Reset the data for the last set of changes we did, this forces the cells to change color.
        if (lastData != null) {
            publishData(lastData, true, notify);
            Iterator<?> dataIterator = lastData.keySet().iterator();
            while (dataIterator.hasNext()) {
                DataChange.releaseDataChange((DataChange) dataIterator.next());
            }
            lastData.clear();
        }
        publishData(data, false, notify);// Publish the current set of data.
        model.setBatchUpdates(false);
        if (!notify) {
            model.fireTableDataChanged();
        }
        lastData = data;
        long end = System.currentTimeMillis();
        notifyTime = (end - start);
        start = System.currentTimeMillis();
        RepaintManager.currentManager(null).paintDirtyRegions();
        end = System.currentTimeMillis();
        paintTime = (end - start);
    }

    /**
     * Publish the passed in set of data.
     */
    private void publishData(Map<?, ?> data, boolean negate, boolean notify) {
        Iterator<?> dataIterator = data.keySet().iterator();
        while (dataIterator.hasNext()) {
            DataChange change = (DataChange) dataIterator.next();
            Object value = data.get(change);
            if (negate) {
                value = new Integer(((Integer) value).intValue() * -1);
            }
            model.set(change.getData(), change.getColumn(), value, notify);
        }
    }

    /**
     * If enable is true, we are allowed to publish changes, otherwise we
     * aren't.
     *
     * @param enable
     */
    public void setUpdatesEnabled(boolean enable) {
        synchronized (this) {
            updatesEnabled = enable;
            if (updatesEnabled) {
                notify();
            }
        }
    }

    public boolean getUpdatesEnabled() {
        return updatesEnabled;
    }
}

.

import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;

/**
 * VisibleTableModelEvent adds the method isVisible to test if the cell
 * identified by the event is visible.
 */
public class VisibleTableModelEvent extends TableModelEvent {

    private static final long serialVersionUID = 1L;
    private Point tmpPoint;
    // This implementation caches the information for one JTable, it is
    // certainly possible to cache it for more than one should
    // you have this need.
    private boolean valid;
    private int firstVisRow;
    private int lastVisRow;
    private int firstVisCol;
    private int lastVisCol;

    public VisibleTableModelEvent(TableModel source) {
        super(source, 0, 0, 0, UPDATE);
        tmpPoint = new Point();
    }

    /**
     * Resets the underlying fields of the TableModelEvent. This assumes no ONE
     * is going to cache the TableModelEvent.
     *
     * @param row
     * @param col
     */
    public void set(int row, int col) {
        firstRow = row;
        lastRow = row;
        column = col;
    }

    /**
     * Invoked to indicate the visible rows/columns need to be recalculated
     * again.
     */
    public void reset() {
        valid = false;
    }

    public boolean isVisible(JTable table) {
        if (!valid) {// Determine the visible region of the table.            
            Rectangle visRect = table.getVisibleRect();
            tmpPoint.x = visRect.x;
            tmpPoint.y = visRect.y;
            firstVisCol = table.columnAtPoint(tmpPoint);
            firstVisRow = table.rowAtPoint(tmpPoint);
            tmpPoint.x += visRect.width;
            tmpPoint.y += visRect.height;
            lastVisCol = table.columnAtPoint(tmpPoint);
            if (lastVisCol == -1) {
                lastVisCol = table.getColumnCount() - 1;
            }
            if ((lastVisRow = table.rowAtPoint(tmpPoint)) == -1) {
                lastVisRow = table.getRowCount();
            }
            valid = true;
        }
        return (firstRow >= firstVisRow && firstRow <= lastVisRow && column
                >= firstVisCol && column <= lastVisCol);
    }
}
于 2013-02-20T19:59:37.013 に答える