在 Java Swing 中将输出重定向到 table
Redirecting output to table in Java Swing
这里是新手,我有一个问题,将我的输出重定向到 Jtable。数据来自不同的 class,它完成真正的工作,即 Scanner.java。
话虽如此,Scanner.java 可以在控制台上打印我想要的内容,但是自从我添加了仍在学习的 gui 后,我创建了一个新的 class 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", "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 class 文件写入 CSV,然后读取延迟填充 table 的文件。但是就像我说的,我是一个初学者仍然不认为这会那么容易。所以我需要有人为我指明正确的方向。
基本上,您想从事件调度线程外部加载数据,以免阻塞 UI 并使其成为 "hang".
接下来,您需要某种方式让 Scanner
发布它生成的信息,有多种方式可以做到这一点,但最简单的可能是使用类似 Produce/Consumer 的方式图案。
在 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 and How to Use Tables 了解更多详情
这里是新手,我有一个问题,将我的输出重定向到 Jtable。数据来自不同的 class,它完成真正的工作,即 Scanner.java。
话虽如此,Scanner.java 可以在控制台上打印我想要的内容,但是自从我添加了仍在学习的 gui 后,我创建了一个新的 class 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", "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 class 文件写入 CSV,然后读取延迟填充 table 的文件。但是就像我说的,我是一个初学者仍然不认为这会那么容易。所以我需要有人为我指明正确的方向。
基本上,您想从事件调度线程外部加载数据,以免阻塞 UI 并使其成为 "hang".
接下来,您需要某种方式让 Scanner
发布它生成的信息,有多种方式可以做到这一点,但最简单的可能是使用类似 Produce/Consumer 的方式图案。
在 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 and How to Use Tables 了解更多详情