2015-03-27 2 views
0

Новичок здесь, у меня есть проблема, перенаправление моего вывода на Jtable. Данные поступают из другого класса, который выполняет настоящую работу Scanner.java.Перенаправление вывода в таблицу в Java Swing

Сказанное сказало, что Scanner.java может печатать то, что я хочу на консоли, но так как я добавил gui, который все еще учился, я создал новый класс MainFrame.java, и я хочу, чтобы результат поиска или сканирования был заполнен Scanner.java в моем JTable, но мне трудно получить логин.

Scanner.java

public void getCompanyProfile(){ 
    Document sourceCode; 

      EventQueue.invokeLater(new Runnable() { 
       public void run() { 
        try { 
         List<String> allLinks = results(); 
         Document sourceCode; 
         int counter = 1; 
         for (String link : allLinks){ 
          System.out.println("Link #:" + counter + " " + link); 
          sourceCode = PageVisitor.getHtmlSource(link); 
          Elements profile = sourceCode.select("div.company a.cd"); 
          for (Element links : profile) { 
           String linkHref = links.attr("href"); 
           System.out.println(linkHref); 
           setUserData(linkHref); 
          } 
          counter++; 
         } 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
       } 
      }); 

     } 

     private void setUserData(String url) throws IOException{ 
      Extractor data = new Extractor(); 
      // Scan each page alibaba initial result 
      data.setProfile(url); 
      this.companyName = data.getName(); 
      this.country = data.getCountry(); 
      HashSet<String> webites = data.getSellerUrls(); 

      this.webAndEmail = new HashMap<String, HashSet<String>>(); 
      HashSet<String> emails; 

      for (String webs: webites){ 
       emails = data.emailExtractor(webs); 
       webAndEmail.put(webs, emails); 
       for (String anEmail : emails){ 
//This is the part i want to be displayed in my JTable Component. 
        System.out.println("Company=" +companyName + ", country=" + country + ", web=" 
       + webs + ", email=" + anEmail); 
       } 
      } 

     } 

     public String getProductName(){ 
      return this.product; 
     } 
     public String getSource(){ 
      return this.source; 
     } 
     public String getCompanyName(){ 
      return this.companyName; 
     } 
     public String getCountry(){ 
      return this.country; 
     } 
     public Map<String, HashSet<String>> getWebandEmail(){ 
      return this.webAndEmail; 
     } 

Наконец, это мой MainFrame.java файл ниже.

![JButton btnStart = new JButton("Start"); 
     btnStart.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 


      } 
     }); 
     btnStart.setBounds(197, 166, 75, 29); 
     frame.getContentPane().add(btnStart); 



    //more statements like the above to establish all col. titles  
     String\[\] columnNames = {"Company Name", "Email", "Website", "Country", "Product", "Source"}; 
     //Sample data to be printed 
      Object\[\]\[\] data = 
      { 
       {"Code Java Ltd", "[email protected]", "http://www.codejava.com", "Universe", "Polythecnic", "Ebay - B2B"}, 

      }; 

      DefaultTableModel model = new DefaultTableModel(data, columnNames) { 

       @Override 
       public boolean isCellEditable(int row, int column) { 
        //all cells false 
        return false; 
       } 
      }; 



     resultTable = new JTable(model); 
     //resultTable.setBounds(37, 259, 553, 143); 
     resultTable.getColumnModel().getColumn(0).setPreferredWidth(150); 
     resultTable.getColumnModel().getColumn(1).setPreferredWidth(150); 
     resultTable.getColumnModel().getColumn(2).setPreferredWidth(150); 
     resultTable.getColumnModel().getColumn(3).setPreferredWidth(150); 
     resultTable.getColumnModel().getColumn(4).setPreferredWidth(100); 
     resultTable.getColumnModel().getColumn(5).setPreferredWidth(100); 

     resultTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 

     JScrollPane scrollPane = new JScrollPane(resultTable); 
     scrollPane.setBounds(37, 259, 806, 143); 
     frame.getContentPane().add(scrollPane); 
     //frame.add(resultTable); 

     JButton button = new JButton("Stop"); 
     button.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
      } 
     }); 
     button.setBounds(289, 166, 75, 29); 
     frame.getContentPane().add(button);][1] 

Это то, чего я пытаюсь достичь. Моя другая идея - записать содержимое в CSV из файла класса Scanner.java и прочитать файл, заполненный для заполнения таблицы. Но, как я уже сказал, новичок все еще не думает, что это будет так просто. Поэтому мне нужно, чтобы кто-то указал мне в правильном направлении.

+2

'' SwingWorker' и TableModel' ты друг здесь - см. [Рабочие темы и SwingWorker] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html) и [Как использовать таблицы] (http://docs.oracle.com/javase /tutorial/uiswing/components/table.html) – MadProgrammer

+0

В принципе, вы хотите каким-то образом t o отправлять информацию из класса Scanner в 'TableModel'. Я бы изменил 'getCompanyProfile', чтобы работать в текущем потоке и возвращать нужную вам информацию.В равной степени вы можете предоставить своего рода «потребителю», и каждый раз, когда вы обрабатываете другой результат, отправляйте эту информацию через «потребитель», который может обновить «TableModel» – MadProgrammer

+0

@MadProgrammer. Да, я пытаюсь сделать именно это. Скажем, это похоже на log, но на этот раз они являются разделенным запятой значением, которое я хочу хранить в Excel и отображаться в таблице, пока программирование все еще обрабатывается в цикле. –

ответ

1

В принципе, вы хотите загрузить свои данные извне Диспетчер событий, чтобы не блокировать пользовательский интерфейс и не зависеть от него.

Для того, чтобы опубликовать информацию, которую он сгенерировал, вам понадобится какой-то способ для публикации информации, существует несколько способов, которыми вы могли бы это сделать, но самый простой способ - использовать что-то вроде шаблона Produce/Consumer.

В качестве продюсера нам необходимо сообщить потребителю, что новый контент доступен. Начните с простым интерфейсом ...

public interface Consumer { 

    public void publish(String company, String country, String webLink, String email); 

} 

Примечания, я обычно предпочитаю использовать объекты (например, POJO), но я стараюсь держать его просто.

Далее, мы должны изменить Scannner работать с нашим Consumer ...

public class Scanner { 

    public void getCompanyProfile(Consumer consumer) { 
     Document sourceCode; 
     List<String> allLinks = results(); 
     Document sourceCode; 
     int counter = 1; 
     for (String link : allLinks) { 
      System.out.println("Link #:" + counter + " " + link); 
      sourceCode = PageVisitor.getHtmlSource(link); 
      Elements profile = sourceCode.select("div.company a.cd"); 
      for (Element links : profile) { 
       String linkHref = links.attr("href"); 
       System.out.println(linkHref); 
       setUserData(linkHref); 
      } 
      counter++; 
     } 
    } 

    private void setUserData(String url, Consumer consumer) throws IOException { 
     Extractor data = new Extractor(); 
     // Scan each page alibaba initial result 
     data.setProfile(url); 
     this.companyName = data.getName(); 
     this.country = data.getCountry(); 
     HashSet<String> webites = data.getSellerUrls(); 

     this.webAndEmail = new HashMap<String, HashSet<String>>(); 
     HashSet<String> emails; 

     for (String webs : webites) { 
      emails = data.emailExtractor(webs); 
      webAndEmail.put(webs, emails); 
      for (String anEmail : emails) { 
       consumer.publish(companyName, country, webs, anEmail); 
      } 
     } 

    } 

    public String getProductName() { 
     return this.product; 
    } 

    public String getSource() { 
     return this.source; 
    } 

    public String getCompanyName() { 
     return this.companyName; 
    } 

    public String getCountry() { 
     return this.country; 
    } 

    public Map<String, HashSet<String>> getWebandEmail() { 
     return this.webAndEmail; 
    } 
} 

Теперь нам нужно каким-то образом, чтобы получить Scanner созданные и продуцирующие данные, первым мы создаем базовый пользовательский интерфейс, а затем мы начинаем SwingWorker, передавая ссылку TableModel, чтобы он мог добавлять новые строки.

EventQueue.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      try { 
       UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
      } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       ex.printStackTrace(); 
      } 

      DefaultTableModel model = new DefaultTableModel(new String[]{"Company Name", "Email", "Website", "Country", "Product", "Source"}, 0); 
      JTable table = new JTable(model); 
      // Initialise remainder of the UI... 

      ScannerWorker worker = new ScannerWorker(model); 
      worker.execute(); 
     } 
    }); 

И SwingWorker держать все это вместе ...

public class ScannerWorker extends SwingWorker<Object, String[]> implements Consumer { 

    private DefaultTableModel tableModel; 

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

    @Override 
    protected Object doInBackground() throws Exception { 
     Scanner scanner = new Scanner(); 
     scanner.getCompanyProfile(this); 
     return null; 
    } 

    @Override 
    public void publish(String company, String country, String webLink, String email) { 
     publish(new String[]{company, email, webLink, country, "", ""}); 
    } 

    @Override 
    protected void process(List<String[]> chunks) { 
     for (String[] rowData : chunks) { 
      tableModel.addRow(rowData); 
     } 
    } 

} 

Присмотритесь на Worker Threads and SwingWorker и How to Use Tables для получения более подробной информации

+0

спасибо, но как я могу захватить вывод. Он работает, но ничего не обновляется в таблице. Я предполагаю, что мне нужно использовать возвращаемое значение для worker.execute() или по крайней мере поместить что-то в DefaultTableModel model = new DefaultTableModel (new String [] {«Название компании», «Электронная почта», «Веб-сайт», «Страна», Продукт "," Источник "}, 0); –

+0

'consumer.publish (companyName, country, webs, anEmail);' вызывает публикацию public void (String company, String country, String webLink, String email) {'в' ScannerWorker', который вызывает 'publish (String [ ]) 'на' SwingWorker', который (в итоге) вызывает 'process (List )', который обновляет 'TableModel'. До тех пор, пока 'TableModel' был назначен для JTable и JTable, добавьте на экран какие-то способы, он должен просто работать – MadProgrammer

+0

Но поскольку у меня есть всего лишь куча вне контекстного кода, невозможно быть уверенным, что могло бы пойти не так – MadProgrammer