使用SwingWorker在jTable中动态加载大数据 [英] Dynamically loading large data in jTable using SwingWorker

查看:163
本文介绍了使用SwingWorker在jTable中动态加载大数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Netbeans中,我试图创建一个桌面应用程序,其UI如下所示: com / 3b0vP.pngrel =nofollow noreferrer>



我正在通过Java代码执行adb logcat命令,它在几秒钟内加载了1000行日志。我打算通过NetBeans中的jTable显示所有这些信息。



使用参数:adb logcat -t 100 - >我现在只限制日志为100行。
然而,小程序变得没有反应(或卡在process()方法)1000行或消除这种行数限制。

我不是确定我的代码中是否正确实现了SwingWorker线程。我正在寻找如何改善代码的动态加载大量的数据没有小应用程序变得没有响应的建议。
$ b

以下是applet的实现代码...与2函数:


  1. 从applet的init()方法调用的viewLogs()。
  2. SwingWorker实现。
    $ b $ pre $ public void viewLogs()throws IOException {

    String [] command = { CMD,/ C,adb logcat -t 100};
    ProcessBuilder probuilder = new ProcessBuilder(command);
    probuilder.directory(新文件(c:\\ Users \\\\\\\\\\\\\\\\\\\\\\\\\));
    进程进程= probuilder.start();

    InputStream is = process.getInputStream();
    InputStreamReader isr = new InputStreamReader(is);
    br = new BufferedReader(isr);

    DefaultTableModel model =(DefaultTableModel)jTable1.getModel();
    worker.execute();

    try {
    int exitVal = process.waitFor();
    System.out.println(exitVal =+ exitVal);
    } catch(InterruptedException e){
    e.printStackTrace();

    $ b public class TableSwingWorker extends SwingWorker< DefaultTableModel,Object []> {
    private DefaultTableModel tableModel;
    public TableSwingWorker(DefaultTableModel tableModel){
    this.tableModel = tableModel;

    $ b $ @覆盖
    保护DefaultTableModel doInBackground()抛出异常{
    Thread.sleep(2000); //为初始UI添加加载
    System.out.println(开始填充);
    字符串行,日期,时间,日志级别,PID,TID,标记,消息=;
    字符串日志;
    int count = 0; ((log = br.readLine())!= null){
    count ++;
    while
    $ b $ String split [] splitLog = log.trim()。split(\\s +);
    line = Integer.toString(count);
    date = splitLog [0];
    time = splitLog [1];
    PID = splitLog [2];
    TID = splitLog [3];
    loglevel = splitLog [4];
    tag = splitLog [5];
    for(int i = 6; i< splitLog.length; i ++){
    message + = splitLog [i]; (新对象[] {行,日期,时间,PID,TID,日志级别,标记,消息});

    发布
    }
    return tableModel;

    $ b $覆盖
    保护无效进程(List< Object []>块){
    System.out.println(Adding+ chunks.size ()+rows);
    for(Object [] row:chunks)
    tableModel.insertRow(0,row);

    }



解决方案



  try {
int exitVal = process.waitFor();
System.out.println(exitVal =+ exitVal);
} catch(InterruptedException e){
e.printStackTrace();



$ b $ p
$ b

这阻止了事件派发线程,防止发生任何可能的更新,直到 Process 完成,这样做违背了使用 SwingWorker 的目的。



你最好直接在 SwingWorker 中执行 Process ,比如...

  public class TableSwingWorker extends SwingWorker< Integer,Object []> {

private DefaultTableModel tableModel;
private int count;

public TableSwingWorker(DefaultTableModel tableModel){
this.tableModel = tableModel;

$ b $ @覆盖
保护Integer doInBackground()抛出异常{
count = 0;

String [] command = {CMD,/ C,adb logcat -t 100};
ProcessBuilder probuilder = new ProcessBuilder(command);
probuilder.directory(新文件(c:\\ Users \\\\\\\\\\\\\\\\\\\\\\\\\));
进程进程= probuilder.start();

InputConsumer consumer = new InputConsumer(process.getInputStream());
consumer.start();

int result = process.waitFor();
consumer.join();

返回结果;

$ b $覆盖
保护无效进程(List< Object []>块){
System.out.println(Adding+ chunks.size ()+rows);
for(Object [] row:chunks){
tableModel.insertRow(0,row);



protected void processOutput(String text){
count ++;

String [] splitLog = text.trim()。split(\\s +);
String line = Integer.toString(count);
String date = splitLog [0];
String time = splitLog [1];
String PID = splitLog [2];
String TID = splitLog [3];
字符串loglevel = splitLog [4];
String tag = splitLog [5];

StringBuilder message = new StringBuilder(64);
for(int i = 6; i< splitLog.length; i ++){
message.append(splitLog [i]); (新对象[] {行,日期,时间,PID,TID,日志级别,标记,消息});

发布
}

public class InputConsumer extends Thread {

private InputStream is;

public InputConsumer(InputStream is){
this.is = is;
start();

$ b @Override
public void run(){
try(BufferedReader br = new BufferedReader(new InputStreamReader(is))){
String text = null; ((text = br.readLine())!= null){
processOutput(text);
while
}
} catch(IOException exp){
exp.printStackTrace();



$ b $ / code>

好的,这可能看起来有点沉重,但它有两个重要的事情:


  1. 它加载读取进程的 InputStream 到另一个 Thread ,这使我们可以...

  2. waitFor 过程退出,所以我们得到退出值,这可以在诊断为什么有些时候不工作有用



其他观察




  • Applet的本质是在严格的安全约束下运行的,通常意味着它们不是不允许在其他机器上执行程序。

  • Applet的也不再支持。请参阅不推荐使用Java插件转到无插件网页获取更多详细信息


In Netbeans, I am trying to create a Desktop Application whose UI looks like below:

I am executing "adb logcat command" through Java code which loads 1000s of lines of logs in few seconds & I intend to display all of this information through jTable in NetBeans.

Using parameter: adb logcat -t 100 -> I am restricting the logs to 100 lines only right now. However the applet becomes unresponsive (or gets stuck in process() method) for 1000 lines or when removing such restriction on number of lines.

I am not sure whether I have properly implemented the SwingWorker thread in my code. I am looking for suggestions on how to improve the code for loading large amount of data dynamically without applet becoming unresponsive.

Following is the implemented code for the applet... with 2 functions:

  1. viewLogs() called from init() method of applet.
  2. SwingWorker implementation.

        public void viewLogs() throws IOException {
    
        String[] command = {"CMD","/C", "adb logcat -t 100"};
        ProcessBuilder probuilder = new ProcessBuilder( command );
        probuilder.directory(new File("c:\\Users\\k.garg\\Desktop\\"));
        Process process = probuilder.start();
    
        InputStream is = process.getInputStream();      
        InputStreamReader isr = new InputStreamReader(is);
        br = new BufferedReader(isr);
    
        DefaultTableModel model = (DefaultTableModel)jTable1.getModel();
        worker.execute();
    
        try {
            int exitVal = process.waitFor();
            System.out.println("exitVal = " + exitVal);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public class TableSwingWorker extends SwingWorker<DefaultTableModel, Object[]>{
    private DefaultTableModel tableModel;
    public TableSwingWorker(DefaultTableModel tableModel){
        this.tableModel = tableModel;
    }
    
    @Override
    protected DefaultTableModel doInBackground() throws Exception {
        Thread.sleep(2000); //added for initial UI to load
        System.out.println("Start populating");
        String line, date, time, loglevel, PID, TID, tag, message="";
        String log;
        int count = 0;
        while ((log = br.readLine()) != null) {
            count++;
    
            String[] splitLog = log.trim().split("\\s+");
            line = Integer.toString(count);
            date = splitLog[0];
            time = splitLog[1];
            PID = splitLog[2];
            TID = splitLog[3];
            loglevel = splitLog[4];
            tag = splitLog[5];
            for(int i=6; i<splitLog.length;i++){
                message += splitLog[i];
            }
            publish(new Object[]{line, date, time, PID, TID, loglevel, tag, message});
        }
        return tableModel;
    }
    
    @Override
    protected void process(List<Object[]> chunks) {
        System.out.println("Adding " + chunks.size() + " rows");
        for(Object[] row: chunks)
            tableModel.insertRow(0,row);
    }
    

    }

解决方案

The key problem is...

try {
    int exitVal = process.waitFor();
    System.out.println("exitVal = " + exitVal);
} catch (InterruptedException e) {
    e.printStackTrace();
}

This is blocking the Event Dispatching Thread, preventing any possible updates from occurring until the Process completes, kind of defeating the purpose of using a SwingWorker.

You'd be better off executing the Process in the SwingWorker directly, something like...

public class TableSwingWorker extends SwingWorker<Integer, Object[]> {

    private DefaultTableModel tableModel;
    private int count;

    public TableSwingWorker(DefaultTableModel tableModel) {
        this.tableModel = tableModel;
    }

    @Override
    protected Integer doInBackground() throws Exception {
        count = 0;

        String[] command = {"CMD", "/C", "adb logcat -t 100"};
        ProcessBuilder probuilder = new ProcessBuilder(command);
        probuilder.directory(new File("c:\\Users\\k.garg\\Desktop\\"));
        Process process = probuilder.start();

        InputConsumer consumer = new InputConsumer(process.getInputStream());
        consumer.start();

        int result = process.waitFor();
        consumer.join();

        return result;
    }

    @Override
    protected void process(List<Object[]> chunks) {
        System.out.println("Adding " + chunks.size() + " rows");
        for (Object[] row : chunks) {
            tableModel.insertRow(0, row);
        }
    }

    protected void processOutput(String text) {
            count++;

            String[] splitLog = text.trim().split("\\s+");
            String line = Integer.toString(count);
            String date = splitLog[0];
            String time = splitLog[1];
            String PID = splitLog[2];
            String TID = splitLog[3];
            String loglevel = splitLog[4];
            String tag = splitLog[5];

            StringBuilder message = new StringBuilder(64);
            for (int i = 6; i < splitLog.length; i++) {
                message.append(splitLog[i]);
            }
            publish(new Object[]{line, date, time, PID, TID, loglevel, tag, message});
    }

    public class InputConsumer extends Thread {

        private InputStream is;

        public InputConsumer(InputStream is) {
            this.is = is;
            start();
        }

        @Override
        public void run() {
            try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
                String text = null;
                while ((text = br.readLine()) != null) {
                    processOutput(text);
                }
            } catch (IOException exp) {
                exp.printStackTrace();
            }
        }
    }
}

Okay, this might look a little "heavy" but it does two important things:

  1. It off loads the reading of the process's InputStream to another Thread, which allows us to...
  2. waitFor the process to exit so we get the exit value, which can be useful in diagnosing why somethings don't work from time to time

Other observations

这篇关于使用SwingWorker在jTable中动态加载大数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆