新手在这里,我遇到了问题,将输出重定向到Jtable。数据来自执行实际工作的另一个类Scanner.java。

如此说来,Scanner.java可以在控制台上打印我想要的内容,但是由于我添加了仍在学习的gui,所以我创建了一个新类MainFrame.java,并且我希望将搜索或扫描结果表格Scanner.java填充到JTable中,发现很难登录。

扫描器

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", "bingo@codejava.net", "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]


这就是我们想要达到的目标。
我的另一个想法是将内容从Scanner.java类文件写入CSV并读取要填充表格的文件。但是,就像我说的那样,作为一个初学者,仍然不认为那样容易。因此,我需要有人指出正确的方向。

最佳答案

基本上,您想从事件调度线程外部加载数据,以免阻塞UI并使它“挂起”。

接下来,您需要某种方式使Scanner发布它生成的信息,您可以通过多种方式来执行此操作,但是最简单的方式可能是使用生产/消费者模式。

Scanner充当生产者的情况下,我们需要某种方式通知消费者新内容可用。从简单的界面开始...

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并生成数据,首先我们创建基本的UI,然后启动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 SwingWorkerHow to Use Tables

10-07 19:06
查看更多