新手在这里,我遇到了问题,将输出重定向到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 SwingWorker和How to Use Tables