微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从另一个线程扩展类更新UI

如何解决从另一个线程扩展类更新UI

我想做什么:

[使用Jsoup进行网页爬取]

从另一个Thread扩展类向TableView添加元素。

单击按钮->启动线程->线程向TableView添加元素。

文件

|javafxapplication5
|-->FXMLDocuments.fxml
|-->FXMLDocumentController.java
|-->JavaFXApplication5.java
|-->Scraper.java

FXMLDocumentController.java

package javafxapplication5;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;


public class FXMLDocumentController implements Initializable {
    Scraper scraper = new Scraper();
    
    @FXML
    private Label label;
    
    @FXML
    private Button shareButton;
    
    @FXML
    private TextField searchInput;

    @FXML
    private Button searchTorrents;

    @FXML
    private void handleButtonAction(ActionEvent event) {
        System.out.println("You clicked me!");
    }
    
    @FXML
    private void setMouseEntered(MouseEvent event)
    {
        searchTorrents.setStyle("-fx-border-color:blue");
    }
    @FXML
    private void setMouseLeaved(MouseEvent event)
    {
        searchTorrents.setStyle("-fx-border-color:black");
    }
    
    @FXML
    private void shareButton(ActionEvent event)
    {
        Alert alert = new Alert(Alert.AlertType.informatION);
        alert.setHeaderText("Hai cliccato il bottone share");
        alert.showAndWait();
    }
    
    @FXML
    private void scrapButton(ActionEvent event)
    {
        scraper.start();
    }
     
    @Override
    public void initialize(URL url,ResourceBundle rb) {
        // Todo
    }    
    
}

Scraper.java

package javafxapplication5;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;


public class Scraper extends Thread{
    public void run()
    {
        Document doc;
        try {
            doc = Jsoup.connect("https://www.allkeyshop.com/blog/daily-deals/").get();
            Elements gamesNames = doc.select(".search-results-row-game-title");
            for (Element element:gamesNames)
            {
                //Update TableView
            }
        } catch (IOException ex) {
            Logger.getLogger(TorrentScraper.class.getName()).log(Level.SEVERE,null,ex);
        }
    }
}

我希望一切都清楚了,否则请给我一个建设性的建议。

解决方法

这是您可以用作指导的示例。您使用的URL没有结果列表。我建议您使用类似https://www.allkeyshop.com/blog/catalogue/search-game/的名称。看起来,连字符后面是正在搜索的内容。您可能需要进行一些复杂的搜索才能了解URL的变化。

此示例使用Task。在Task setOnSuccedded中更新TableView

主要

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

/**
 * JavaFX App
 */
public class App extends Application
{

    @Override
    public void start(Stage primaryStage)
    {
        TableView<JSoupData> tvMain = new TableView();
        ObservableList<JSoupData> tableItems = FXCollections.observableArrayList();
        tvMain.setItems(tableItems);

        TableColumn<JSoupData,String> tcTagName = new TableColumn<>("Tag Name");
        tcTagName.setCellValueFactory(new PropertyValueFactory<>("tagName"));
        TableColumn<JSoupData,String> tcText = new TableColumn<>("Text");
        tcText.setCellValueFactory(new PropertyValueFactory<>("text"));
        tvMain.getColumns().add(tcTagName);
        tvMain.getColumns().add(tcText);

        TextField tfUrl = new TextField("https://www.allkeyshop.com/blog/catalogue/search-game/");
        tfUrl.setPromptText("Enter URL Here!");

        Button btnProcess = new Button("Process URL");
        btnProcess.setOnAction((t) -> {
            btnProcess.setDisable(true);

            Task<List<JSoupData>> task = scrapper(tfUrl.getText());
            task.setOnSucceeded((WorkerStateEvent t1) -> {
                List<JSoupData> tempList = task.getValue();
                tableItems.setAll(tempList);
                btnProcess.setDisable(false);
            });
            Thread thread = new Thread(task);
            thread.setDaemon(true);
            thread.start();
        });
        VBox root = new VBox(tvMain,tfUrl,btnProcess);

        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args)
    {
        launch();
    }

    public Task<List<JSoupData>> scrapper(String url)
    {
        Task<List<JSoupData>> scrapperTask = new Task<List<JSoupData>>()
        {
            @Override
            protected List<JSoupData> call()
            {
                List<JSoupData> jSoupDatas = new ArrayList();
                try {
                    System.out.println("url: " + url);
                    Document document = Jsoup.connect(url).get();
                    System.out.println("Title: " + document.title());
                    Elements gamesNames = document.select(".search-results-row");
                    System.out.println("search-results-row");
                    for (Element element : gamesNames) {
                        jSoupDatas.add(new JSoupData(element.tagName(),element.text()));
                        System.out.println("Tag Name: " + element.tagName() + " - Text: " + element.text());
                    }
                }
                catch (IOException e) {
                    System.out.println(e.toString());
                }

                return jSoupDatas;
            }
        };

        return scrapperTask;
    }
}

JSoupData

 *
 * @author sedrick (sedj601)
 */
public class JSoupData
{

    private String tagName;
    private String text;

    public JSoupData(String tagName,String text)
    {
        this.tagName = tagName;
        this.text = text;
    }

    public String getText()
    {
        return text;
    }

    public void setText(String text)
    {
        this.text = text;
    }

    public String getTagName()
    {
        return tagName;
    }

    public void setTagName(String tagName)
    {
        this.tagName = tagName;
    }

    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
        sb.append("JSoupData{tagName=").append(tagName);
        sb.append(",text=").append(text);
        sb.append('}');
        return sb.toString();
    }
}

enter image description here

,

通常,Platform.runLater()可用于在JavaFX应用程序线程上执行那些更新。

您可以从文档here中获取更多信息,并从here中获取示例

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。