Java - как сделать «работающий» JTable? - PullRequest
1 голос
/ 22 февраля 2010

У меня проблема с созданием JTable, который будет показывать каждую секунду текст. Я делаю MainView, размещаю JTable и имею класс "TableHandler (таблица JTable) реализует Runnable", который должен добавить некоторый текст в интервалах к JTable ... Вот метод запуска:

public void run() {
    for (int i=0; i<5; i++) {
        table.setValueAt("text", i, i);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

Проблема в том, что MainView не будет отображаться до тех пор, пока Jtable не будет заполнен данными, поэтому пользователь не увидит заполнение: - (

РЕДАКТИРОВАТЬ: больше кода

public MyView(SingleFrameApplication app) {
    super(app);

    initComponents();
    // log of GUI stuff here
   TableHandler th = new TableHandler(myTable);
   th.createTable(); // just loads data
   Timer t = new Timer(100,new ActionListener() {
   public void actionPerformed(ActionEvent e) {
       th.run();
      }
   });
   t.start();

Ответы [ 6 ]

3 голосов
/ 22 февраля 2010

Если вы используете Swing и хотите выполнить действие в течение определенного промежутка времени, вы должны использовать таймер колебания, как описано в руководстве .

Преобразовав ваш цикл в последовательность вызовов actionPerformed, вы получите:

    new Timer ( 1000, new ActionListener () {
        int i = 0; // moved out of loop 

        @Override
        public void actionPerformed ( ActionEvent event ) {
            if ( i < 5 ) {
                i++;

                table.setValueAt ( "text", i, i );

            } else {
                // stop the timer firing events when the loop end 
                // condition is reached
                ( ( Timer ) event.getSource() ).setRepeats ( false );
            }
        }
    } ).start();
2 голосов
/ 23 февраля 2010

Вам необходимо обновить из потока AWT:

public void run() {
    for (int i=0; i<5; i++) {
        final int x = i;
        SwingUtilities.invokeLater( new Runnable() {
          public void run() {
            table.setValueAt("text", x, x);
           }});
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

См. http://java.sun.com/javase/6/docs/api/javax/swing/SwingUtilities.html#invokeLater(java.lang.Runnable)

1 голос
/ 22 февраля 2010

Наиболее вероятная проблема описываемого вами поведения заключается в том, что вы не используете отдельный поток для запуска метода run. Если метод run вызывается напрямую, экран не будет обновляться до тех пор, пока основной поток снова не станет доступным, что произойдет только после завершения метода run.

Убедитесь, что вы нигде не вызываете run () в вашем коде, поскольку это должно обрабатываться в потоке.

РЕДАКТИРОВАТЬ: код для запуска класса должен выглядеть примерно так:

new Thread(new TableHandler(table)).start();
0 голосов
/ 23 февраля 2010

Согласно вашим комментариям.

Звоните start, а не run, так как mmyers указывает правильное использование первого

Так и должно быть:

Thread t = new Thread( this.table ); // or new Thread( this )

t.start(); // call start on the read 

а не

this.table.run();

или

t.run();
0 голосов
/ 22 февраля 2010

Вы должны использовать SwingUtilities.invokeLater, если вы запускаете его в потоке.

Это просто поставит в очередь запросы к вашей процедуре рисования, поэтому вам нужно быть уверенным, что они вызваны, поставив паузу. Это должно выглядеть примерно так:

in your main--or somewhere equivilent:
    new myThread
    myThread.start()

myThread.run()
   new myRoutine();
   while(activelyUpdating)
       invokeLater(myRoutine);
       sleep(something reasonable, like 1000 for updates every second);


myRoutine
    do all your drawing crap
    return (do not loop here, that's done in the thread.  Just return)

Вероятно, есть способ заставить ваш сон ждать, пока очередь invokeLater не опустеет, но убедитесь, что вы тоже спите, потому что в противном случае поток AWT (поток "myRoutine" будет работать) никогда не получит шанса на запуск и Потоки invokeLater будут просто стоять в очереди.

0 голосов
/ 22 февраля 2010

Попробуйте сделать вызов перекрасить после вашего вызова setValueAt (). Предпочтительно завернутый в SwingUtilities.invokeLater .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...