2014-12-23 2 views
3

Ниже скомпилированная программа копия фактического кода проблемы,Запрос на создание отдельной темы в java?

import javax.swing.JOptionPane; 
import javax.swing.SwingUtilities; 

public class Dummy { 

    public static boolean getUserCheck(int size, boolean Check) { 
     if (Check) { 
      int ret = JOptionPane.showConfirmDialog(null, size + " entries, Yes or no?", 
        "Warning", 0); 
      if (ret > 0) { 
       System.out.println("User said No: " + ret); 
       return false; 
      } else if (ret <= 0) { 
       System.out.println("user said Yes: " + ret); 
       return true; 
      } 
     } 
     return true; 
    } 

    public static void workerMethod1() { 
     System.out.println("am worker method 1"); 
    } 

    public static void workerMethod2() { 
     System.out.println("am worker method 2"); 
    } 

    public static void main(String[] args) { 
     System.out.println("mainthread code line 1"); 
     int size = 13; 
     boolean thresholdBreach = true; 

     if (getUserCheck(size, thresholdBreach)) { 
      SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        workerMethod1(); 
       } 
      }); 

      SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        workerMethod2(); 
       } 
      }); 
     } 
     System.out.println("mainthread code line 2"); 
     System.out.println("mainthread code line 3"); 
    } 
} 

, где я хотел бы запустить if{} блок в основной() на отдельном потоке. Из этих 2-х линий,

 System.out.println("mainthread code line 2"); 
     System.out.println("mainthread code line 3"); 

не нужно ждать завершения if(){} блока

Другой проблемой является, специалисты рекомендуют запускать ПОДТВЕРДИТЕ-диалог методы потока событий.

int ret = JOptionPane.showConfirmDialog(null, size + " entries, Yes or no?", 
        "Warning", 0); 

Пожалуйста, помогите мне !!!!

+2

да, вы можете, но зачем вам это нужно? –

+2

Это может быть вопрос типа проблемы XY, но независимо от того, есть он или нет, вопрос может быть полезен из гораздо большего контекста. Почему вы думаете об этом? Какую общую цель вы пытаетесь достичь? –

+1

Почему вы думаете, что вы не можете вложить его на произвольную глубину? Те же моменты, которые вы считаете при тестировании любого кода. Покрытие всех точек тестирования программного обеспечения является слишком широким вопросом. –

ответ

0

Да; SwingUtilities.invokeLater() просто помещает вашу runnable в очередь событий AWT для последующей обработки, и это безопасно в любое время.

3

JOptionPane является метод качания и должен быть вызван на EDT, то E вентиляционный D ispatch T hread, и только на этой теме, и поэтому можно предположить, что все ваш код выше, должен быть на EDT, и что большинство ваших звонков SwingUtilities.invokeLater(new Runnable() совершенно не нужны. Единственными необходимыми являются основные, где вы запускаете свой код GUI Swing и любые области, в которых вызовы Swing должны выполняться из фоновых потоков. Опять же, если какой-либо из вышеуказанного кода выполняется в фоновых потоках, тогда JOptionPane не должен находиться в этом потоке.

Для получения более конкретной информации в этом или другом ответе предоставьте более подробную информацию в своем вопросе. Покончим с путаницей. Лучший способ получить нас в полной мере и быстро понять вашу проблему будет, если вы должны были создать и опубликовать minimal example program, небольшую, но полную программу, которая имеет только необходимый код, чтобы продемонстрировать вашу проблему, чтобы мы могли копировать, вставлять, компилировать и работать без изменений.

У меня есть подозрительное подозрение, что достойный рефакторинг по линиям MVC может решить большинство ваших проблем. Ваш код очень линейный, с его строками кода, которые должны следовать друг за другом и его блоками if, а также тесно связаны с вашим графическим интерфейсом, двумя красными флагами для меня. Возможно, лучше бы был менее линейный код, больше кода событий и состояний, код, в котором ваш фоновый код взаимодействует с графическим интерфейсом через уведомление наблюдателя, и где фоновый код также реагирует на изменения состояния в графическом интерфейсе из управляющего уведомления.


Элемент управления нуждается в два SwingWorkers, один, чтобы получить количество строк, а другие, чтобы получить остальную часть данных, если пользователь решит сделать это. Я добавлю PropertyChangeListener в первый SwingWorker, чтобы получать уведомления, когда данные подсчета строк готовы, а затем, когда они есть, представите его для представления, чтобы пользователь мог выбрать, продолжать или нет. Если он решит продолжить, я бы назвал второй SwingWorker, чтобы получить основную часть данных.


Например, грубый набросок того, что я говорю:

import java.awt.Dialog.ModalityType; 
import java.awt.Dimension; 
import java.awt.Window; 
import java.awt.event.ActionEvent; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Random; 
import java.util.concurrent.ExecutionException; 

import javax.swing.*; 

@SuppressWarnings("serial") 
public class SwingWorkerFooView extends JPanel { 
    private static final int PREF_W = 400; 
    private static final int PREF_H = 300; 
    private JProgressBar progressBar; 
    private JDialog dialog; 

    public SwingWorkerFooView() { 
     add(new JButton(new ButtonAction("Foo", this))); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
     return super.getPreferredSize(); 
     } 
     return new Dimension(PREF_W, PREF_H); 
    } 

    public boolean showOptionGetAllData(int numberOfRows) { 
     String message = "Number of rows = " + numberOfRows + ". Get all of the data?"; 
     String title = "Get All Of Data?"; 
     int optionType = JOptionPane.YES_NO_OPTION; 
     int result = JOptionPane.showConfirmDialog(this, message, title, optionType); 

     return result == JOptionPane.YES_OPTION; 
    } 

    public void showProgressBarDialog() { 
     progressBar = new JProgressBar(); 
     progressBar.setIndeterminate(true); 
     Window window = SwingUtilities.getWindowAncestor(this); 
     dialog = new JDialog(window, "Hang on", ModalityType.APPLICATION_MODAL); 
     JPanel panel = new JPanel(); 
     panel.add(progressBar); 
     dialog.add(panel); 
     dialog.pack(); 
     dialog.setLocationRelativeTo(this); 
     dialog.setVisible(true); 
    } 

    public void closeProgressBarDialog() { 
     dialog.dispose(); 
    } 

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("SwingWorkerFoo"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new SwingWorkerFooView()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

@SuppressWarnings("serial") 
class ButtonAction extends AbstractAction { 
    Workers workers = new Workers(); 
    private SwingWorker<Integer, Void> firstWorker; 
    private SwingWorker<List<String>, Void> secondWorker; 
    private SwingWorkerFooView mainGui; 

    public ButtonAction(String name, SwingWorkerFooView mainGui) { 
     super(name); 
     this.mainGui = mainGui; 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     firstWorker = workers.createFirstWorker(); 
     firstWorker.addPropertyChangeListener(new FirstPropertyChangeListener()); 
     firstWorker.execute(); 
     mainGui.showProgressBarDialog(); 
    } 

    private class FirstPropertyChangeListener implements PropertyChangeListener { 

     @Override 
     public void propertyChange(PropertyChangeEvent evt) { 
     if (evt.getNewValue() == SwingWorker.StateValue.DONE) { 
      mainGui.closeProgressBarDialog(); 
      try { 
       int numberOfRows = firstWorker.get(); 
       boolean getAllData = mainGui.showOptionGetAllData(numberOfRows); 
       if (getAllData) { 
        secondWorker = workers.createSecondWorker(); 
        secondWorker.addPropertyChangeListener(new SecondPropertyChangeListener()); 
        secondWorker.execute(); 
        mainGui.showProgressBarDialog(); 
       } else { 
        // user decided not to get all data 
        workers.cleanUp(); 
       } 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } catch (ExecutionException e) { 
       e.printStackTrace(); 
      } 
     } 
     } 
    } 

    private class SecondPropertyChangeListener implements PropertyChangeListener { 
     @Override 
     public void propertyChange(PropertyChangeEvent evt) { 
     if (evt.getNewValue() == SwingWorker.StateValue.DONE) { 
      mainGui.closeProgressBarDialog(); 
      try { 
       List<String> finalData = secondWorker.get(); 

       // display finalData in the GUI 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } catch (ExecutionException e) { 
       e.printStackTrace(); 
      } 
     } 

     } 
    } 

} 

class Workers { 
    // database object that may be shared by two SwingWorkers 
    private Object someDataBaseVariable; 
    private Random random = new Random(); // just for simulation purposes 

    private class FirstWorker extends SwingWorker<Integer, Void> { 
     @Override 
     protected Integer doInBackground() throws Exception { 

     // The Thread.sleep(...) is not going to be in final production code 
     // it's just to simulate a long running task 
     Thread.sleep(4000); 

     // here we create our database object and check how many rows there are 
     int rows = random.nextInt(10 + 10); // this is just for demonstration purposes only 

     // here we create any objects that must be shared by both SwingWorkers 
     // and they will be saved in a field of Workers 
     someDataBaseVariable = "Fubar"; 

     return rows; 
     } 
    } 

    private class SecondWorker extends SwingWorker<List<String>, Void> { 
     @Override 
     protected List<String> doInBackground() throws Exception { 

     // The Thread.sleep(...) is not going to be in final production code 
     // it's just to simulate a long running task 
     Thread.sleep(4000); 

     List<String> myList = new ArrayList<>(); 
     // here we go through the database filling the myList collection 

     return myList; 
     } 
    } 

    public SwingWorker<Integer, Void> createFirstWorker() { 
     return new FirstWorker(); 
    } 

    public void cleanUp() { 
     // TODO clean up any resources and database stuff that will not be used. 
    } 

    public SwingWorker<List<String>, Void> createSecondWorker() { 
     return new SecondWorker(); 
    } 
} 

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

Это по существу:

  • создать работнику
  • добавить наблюдателя работника (слушатель недвижимости изменить)
  • выполнить рабочий диалог
  • показать прогресс бар или уведомления пользователя каким-то образом, что работник выполняет ,

  • Слушатель будет уведомлен о выполнении работника, а затем вы можете запросить у работника (здесь через вызов метода get()) относительно его конечного результата.

  • Затем можно открыть диалог выполнения
  • И представление может отображать результат или получать дополнительную информацию от пользователя.
+0

Я думаю, что добавил дополнительную информацию в запрос, пожалуйста, посмотрите – overexchange

+0

это [скомпилированная программа] (https://github.com/shamhub/CS61B_Fall2006/blob/master/JavaCode/src/dummy.java), где я хотел бы запустить блок 'if {}' в отдельном потоке, потому что 'mainteread code line 2' и' mainthread code line 3 'в основном потоке не должны ждать блока 'if {}'. Другая проблема с этим кодом заключается в том, что я не запускаю диалог в потоке событий, как вы сказали выше: «Все диалоги должны запускаться в потоке событий» – overexchange

+0

@overexchange: см. код примера запуска. –

Смежные вопросы