【问题标题】:Display JTable with JavaFX使用 JavaFX 显示 JTable
【发布时间】:2015-11-30 07:39:57
【问题描述】:

我想从网页中读取数字并在程序中使用它们。该程序显示网页,但是如何在网页下方显示表格?以及如何使用网页中的日期和价格填充表格。

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.paint.Color;

public class Step4 {

    private void initAndShowGUI(final String url) {
        // This method is invoked on the EDT thread
        JFrame frame = new JFrame("Swing and JavaFX");

        final JFXPanel fxPanel = new JFXPanel();
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout());
        mainPanel.add(fxPanel, BorderLayout.NORTH);

        TableModel dataModel = new AbstractTableModel() {
            private static final long serialVersionUID = -147208558114868864L;
            public int getColumnCount() { return 10; }
            public int getRowCount() { return 10;}
            public Object getValueAt(int row, int col) { return new Integer(row*col); }
        };
        JTable table = new JTable(dataModel);
        JScrollPane tableContainer = new JScrollPane(table);

        JPanel display = new JPanel();
        display.setLayout(new BorderLayout());
        display.add(tableContainer, BorderLayout.CENTER);
        mainPanel.add(display, BorderLayout.SOUTH);

        frame.add(mainPanel);

        frame.pack();
        frame.setSize(1000, 650);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                initFX(fxPanel, url);
            }
       });
    }

    private void initFX(JFXPanel fxPanel, String url2) {
        // This method is invoked on the JavaFX thread
        Scene scene = createScene(url2);
        fxPanel.setScene(scene);
    }

    private Scene createScene(String url2) {

        Scene scene = new Scene(new Browser_1(url2),750,500, Color.web("#666970"));
        return (scene);
    }

    public static void main(String[] args) {

        final String url = "https://www.tsp.gov/investmentfunds/shareprice/sharePriceHistory.shtml";
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                Step4 s = new Step4();
                s.initAndShowGUI(url);
            }
        });
    }
}

class Browser_1 extends Region {

    final WebView browser = new WebView();
    final WebEngine webEngine = browser.getEngine();

    public Browser_1(String url) {
        //apply the styles
        getStyleClass().add("browser");
        // load the web page
        webEngine.load(url);
        //add the web view to the scene
        getChildren().add(browser);
    }

    @SuppressWarnings("unused")
    private Node createSpacer() {
        Region spacer = new Region();
        HBox.setHgrow(spacer, Priority.ALWAYS);
        return spacer;
    }

    @Override protected void layoutChildren() {
        double w = getWidth();
        double h = getHeight();
        layoutInArea(browser,0,0,w,h,0, HPos.CENTER, VPos.CENTER);
    }

    @Override protected double computePrefWidth(double height) {
        return 750;
    }

    @Override protected double computePrefHeight(double width) {
        return 500;
    }
}

【问题讨论】:

    标签: java swing javafx web-scraping jtable


    【解决方案1】:

    概括地说,

    • WebEngine使用的背景Worker中添加合适的监听器。

    • 在合适的监听器中,traverseDocument Object Model 网页的感兴趣的结果,可能使用显示的方法here

    • 构造一个TableModel,在请求时将结果提供给JTable,可能使用here所示的方法。

    • 发布一个使用更新的TableModel 调用setModel() 的Swing 事件;该表将相应地自行更新。

    基于这个example,下面的InvalidationListener会显示getDocumentURI()返回的结果。

    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import javax.swing.JFrame;
    import javafx.application.Platform;
    import javafx.beans.Observable;
    import javafx.concurrent.Worker;
    import javafx.embed.swing.JFXPanel;
    import javafx.scene.Scene;
    import javafx.scene.layout.StackPane;
    import javafx.scene.web.WebEngine;
    import javafx.scene.web.WebView;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.table.AbstractTableModel;
    
    /**
     * @see https://stackoverflow.com/a/32396344/230513
     * @see https://stackoverflow.com/a/31576647/230513
     */
    public class WebViewTable {
    
        private JTable table;
        private WebView webView;
    
        private void initAndShowGUI() {
            // This method is invoked on the EDT thread
            JFrame frame = new JFrame("WebViewTable");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            final JFXPanel fxPanel = new JFXPanel(){
    
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(800, 400);
                }
            };
            frame.add(fxPanel, BorderLayout.CENTER);
            table = new JTable(){
    
                @Override
                public Dimension getPreferredScrollableViewportSize() {
                    return new Dimension(800, 100);
                }
            };
            frame.add(new JScrollPane(table), BorderLayout.SOUTH);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
    
            Platform.runLater(() -> {
                initFX(fxPanel);
            });
        }
    
        private void initFX(JFXPanel fxPanel) {
            // This method is invoked on the JavaFX thread
            Scene scene = createScene();
            fxPanel.setScene(scene);
        }
    
        private Scene createScene() {
            StackPane root = new StackPane();
            Scene scene = new Scene(root);
            webView = new WebView();
            WebEngine webEngine = webView.getEngine();
            Worker worker = webEngine.getLoadWorker();
            worker.stateProperty().addListener((Observable o) -> {
                if (worker.getState() == Worker.State.SUCCEEDED) {
                    EventQueue.invokeLater(() -> {
                        table.setModel(new AbstractTableModel() {
                            @Override
                            public String getColumnName(int col) {
                                return "Document URI";
                            }
    
                            @Override
                            public int getColumnCount() {
                                return 1;
                            }
    
                            @Override
                            public int getRowCount() {
                                return 1;
                            }
    
                            @Override
                            public Object getValueAt(int row, int col) {
                                return webEngine.getDocument().getDocumentURI();
                            }
                        });
                    });
                }
            });
            webEngine.load("https://example.com");
            root.getChildren().add(webView);
            return scene;
        }
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new WebViewTable()::initAndShowGUI);
        }
    }
    

    【讨论】:

    • 这已涵盖here。您现在有了一个完整的工作示例;如果您有困难,请在专注于解析的新问题中使用/引用它。您可以通过点击左侧的empty check mark 来接受这个答案。
    • 问题是显示页面并读取表格数据。您的代码和解释非常适合显示和访问 DOM,但我不明白如何遍历 DOM 以提取值。您能否修改您的答案以包括遍历 DOM 以提取值。示例是
      Date Col A
      2015 年 9 月 4 日 17.5
      2015 年 9 月 5 日 18.3
    • 还有,你怎么反应这么快?我还在改写评论...我会检查你的链接。
    • 可能是矩阵中的故障。 :-)
    猜你喜欢
    • 1970-01-01
    • 2014-09-15
    • 1970-01-01
    • 1970-01-01
    • 2011-10-03
    • 2015-03-01
    • 2012-01-05
    • 1970-01-01
    相关资源
    最近更新 更多