简体   繁体   English

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

[英]Updating UI from another Thread extended Class

What I want to do:我想做的事:

[Web Scraping with Jsoup] 【用Jsoup爬网】

Adding elements to a TableView from an another Thread extended Class.从另一个 Thread 扩展类向 TableView 添加元素。

Button click -> start Thread -> Thread add elements to TableView.按钮单击-> 启动线程-> 线程将元素添加到TableView。

Files文件

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

FXMLDocumentController.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);
        }
    }
}

I hope is everything clear, if not please answer me with a constructive suggestion.我希望一切都清楚,如果没有,请用建设性的建议回答我。

Here is an example you can use as a guide.这是您可以用作指南的示例。 The URL you use does not have a result list.您使用的URL没有结果列表。 I would suggest you use something like https://www.allkeyshop.com/blog/catalogue/search-game/ .我建议你使用类似https://www.allkeyshop.com/blog/catalogue/search-game/东西。 It appears, what comes after the hyphen is what is being searched.看来,连字符后面的就是正在搜索的内容。 You may need to do a few complicated searches to see how the URL changes.您可能需要进行一些复杂的搜索才能查看URL变化情况。

This example uses Task .此示例使用Task In the Task setOnSuccedded updates the TableView .Task setOnSuccedded更新TableView

Main主要的

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 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();
    }
}

在此处输入图片说明

Usually, Platform.runLater() can be used to execute those updates on the JavaFX application thread.通常, Platform.runLater()可用于在 JavaFX 应用程序线程上执行这些更新。

You can get more information from documentation here and an example from here你可以从文档的详细信息在这里,并从一个例子在这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM