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

huangapple go评论242阅读模式
英文:

Updating UI from another Thread extended Class

问题

我想要做的事情:

[使用Jsoup进行网页抓取]

从另一个扩展了Thread类的线程中将元素添加到TableView中。

按钮点击 -> 启动线程 -> 线程将元素添加到TableView中。

文件

  1. |javafxapplication5
  2. |-->FXMLDocuments.fxml
  3. |-->FXMLDocumentController.java
  4. |-->JavaFXApplication5.java
  5. |-->Scraper.java

FXMLDocumentController.java

  1. package javafxapplication5;
  2. import java.net.URL;
  3. import java.util.ResourceBundle;
  4. import javafx.event.ActionEvent;
  5. import javafx.fxml.FXML;
  6. import javafx.fxml.Initializable;
  7. import javafx.scene.control.Alert;
  8. import javafx.scene.control.Button;
  9. import javafx.scene.control.Label;
  10. import javafx.scene.control.TextField;
  11. import javafx.scene.input.MouseEvent;
  12. public class FXMLDocumentController implements Initializable {
  13. Scraper scraper = new Scraper();
  14. @FXML
  15. private Label label;
  16. @FXML
  17. private Button shareButton;
  18. @FXML
  19. private TextField searchInput;
  20. @FXML
  21. private Button searchTorrents;
  22. @FXML
  23. private void handleButtonAction(ActionEvent event) {
  24. System.out.println("You clicked me!");
  25. }
  26. @FXML
  27. private void setMouseEntered(MouseEvent event)
  28. {
  29. searchTorrents.setStyle("-fx-border-color:blue");
  30. }
  31. @FXML
  32. private void setMouseLeaved(MouseEvent event)
  33. {
  34. searchTorrents.setStyle("-fx-border-color:black");
  35. }
  36. @FXML
  37. private void shareButton(ActionEvent event)
  38. {
  39. Alert alert = new Alert(Alert.AlertType.INFORMATION);
  40. alert.setHeaderText("Hai cliccato il bottone share");
  41. alert.showAndWait();
  42. }
  43. @FXML
  44. private void scrapButton(ActionEvent event)
  45. {
  46. scraper.start();
  47. }
  48. @Override
  49. public void initialize(URL url, ResourceBundle rb) {
  50. // TODO
  51. }
  52. }

Scraper.java

  1. package javafxapplication5;
  2. import java.io.IOException;
  3. import java.util.logging.Level;
  4. import java.util.logging.Logger;
  5. import org.jsoup.Jsoup;
  6. import org.jsoup.nodes.Document;
  7. import org.jsoup.nodes.Element;
  8. import org.jsoup.select.Elements;
  9. public class Scraper extends Thread{
  10. public void run()
  11. {
  12. Document doc;
  13. try {
  14. doc = Jsoup.connect("https://www.allkeyshop.com/blog/daily-deals/").get();
  15. Elements gamesNames = doc.select(".search-results-row-game-title");
  16. for (Element element:gamesNames)
  17. {
  18. //Update TableView
  19. }
  20. } catch (IOException ex) {
  21. Logger.getLogger(TorrentScraper.class.getName()).log(Level.SEVERE, null, ex);
  22. }
  23. }
  24. }

希望一切都清楚,如果不清楚,请用建设性的建议回答我。

英文:

What I want to do:

[Web Scraping with Jsoup]

Adding elements to a TableView from an another Thread extended Class.

Button click -> start Thread -> Thread add elements to TableView.

Files

  1. |javafxapplication5
  2. |-->FXMLDocuments.fxml
  3. |-->FXMLDocumentController.java
  4. |-->JavaFXApplication5.java
  5. |-->Scraper.java

FXMLDocumentController.java

  1. package javafxapplication5;
  2. import java.net.URL;
  3. import java.util.ResourceBundle;
  4. import javafx.event.ActionEvent;
  5. import javafx.fxml.FXML;
  6. import javafx.fxml.Initializable;
  7. import javafx.scene.control.Alert;
  8. import javafx.scene.control.Button;
  9. import javafx.scene.control.Label;
  10. import javafx.scene.control.TextField;
  11. import javafx.scene.input.MouseEvent;
  12. public class FXMLDocumentController implements Initializable {
  13. Scraper scraper = new Scraper();
  14. @FXML
  15. private Label label;
  16. @FXML
  17. private Button shareButton;
  18. @FXML
  19. private TextField searchInput;
  20. @FXML
  21. private Button searchTorrents;
  22. @FXML
  23. private void handleButtonAction(ActionEvent event) {
  24. System.out.println("You clicked me!");
  25. }
  26. @FXML
  27. private void setMouseEntered(MouseEvent event)
  28. {
  29. searchTorrents.setStyle("-fx-border-color:blue");
  30. }
  31. @FXML
  32. private void setMouseLeaved(MouseEvent event)
  33. {
  34. searchTorrents.setStyle("-fx-border-color:black");
  35. }
  36. @FXML
  37. private void shareButton(ActionEvent event)
  38. {
  39. Alert alert = new Alert(Alert.AlertType.INFORMATION);
  40. alert.setHeaderText("Hai cliccato il bottone share");
  41. alert.showAndWait();
  42. }
  43. @FXML
  44. private void scrapButton(ActionEvent event)
  45. {
  46. scraper.start();
  47. }
  48. @Override
  49. public void initialize(URL url, ResourceBundle rb) {
  50. // TODO
  51. }
  52. }

Scraper.java

  1. package javafxapplication5;
  2. import java.io.IOException;
  3. import java.util.logging.Level;
  4. import java.util.logging.Logger;
  5. import org.jsoup.Jsoup;
  6. import org.jsoup.nodes.Document;
  7. import org.jsoup.nodes.Element;
  8. import org.jsoup.select.Elements;
  9. public class Scraper extends Thread{
  10. public void run()
  11. {
  12. Document doc;
  13. try {
  14. doc = Jsoup.connect("https://www.allkeyshop.com/blog/daily-deals/").get();
  15. Elements gamesNames = doc.select(".search-results-row-game-title");
  16. for (Element element:gamesNames)
  17. {
  18. //Update TableView
  19. }
  20. } catch (IOException ex) {
  21. Logger.getLogger(TorrentScraper.class.getName()).log(Level.SEVERE, null, ex);
  22. }
  23. }
  24. }

I hope is everything clear, if not please answer me with a constructive suggestion.

答案1

得分: 1

以下是您要翻译的内容:

这里有一个示例,您可以用作指南。您使用的URL没有结果列表。我建议您使用类似于https://www.allkeyshop.com/blog/catalogue/search-game/的内容。看起来,连字符后面的内容是被搜索的内容。您可能需要进行一些复杂的搜索,以查看URL如何变化。

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

Main

  1. import java.io.IOException;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import javafx.application.Application;
  5. import javafx.collections.FXCollections;
  6. import javafx.collections.ObservableList;
  7. import javafx.concurrent.Task;
  8. import javafx.concurrent.WorkerStateEvent;
  9. import javafx.scene.Scene;
  10. import javafx.scene.control.Button;
  11. import javafx.scene.control.TableColumn;
  12. import javafx.scene.control.TableView;
  13. import javafx.scene.control.TextField;
  14. import javafx.scene.control.cell.PropertyValueFactory;
  15. import javafx.scene.layout.VBox;
  16. import javafx.stage.Stage;
  17. import org.jsoup.Jsoup;
  18. import org.jsoup.nodes.Document;
  19. import org.jsoup.nodes.Element;
  20. import org.jsoup.select.Elements;
  21. public class App extends Application {
  22. @Override
  23. public void start(Stage primaryStage) {
  24. TableView<JSoupData> tvMain = new TableView();
  25. ObservableList<JSoupData> tableItems = FXCollections.observableArrayList();
  26. tvMain.setItems(tableItems);
  27. TableColumn<JSoupData, String> tcTagName = new TableColumn<>("Tag Name");
  28. tcTagName.setCellValueFactory(new PropertyValueFactory<>("tagName"));
  29. TableColumn<JSoupData, String> tcText = new TableColumn<>("Text");
  30. tcText.setCellValueFactory(new PropertyValueFactory<>("text"));
  31. tvMain.getColumns().add(tcTagName);
  32. tvMain.getColumns().add(tcText);
  33. TextField tfUrl = new TextField("https://www.allkeyshop.com/blog/catalogue/search-game/");
  34. tfUrl.setPromptText("Enter URL Here!");
  35. Button btnProcess = new Button("Process URL");
  36. btnProcess.setOnAction((t) -> {
  37. btnProcess.setDisable(true);
  38. Task<List<JSoupData>> task = scrapper(tfUrl.getText());
  39. task.setOnSucceeded((WorkerStateEvent t1) -> {
  40. List<JSoupData> tempList = task.getValue();
  41. tableItems.setAll(tempList);
  42. btnProcess.setDisable(false);
  43. });
  44. Thread thread = new Thread(task);
  45. thread.setDaemon(true);
  46. thread.start();
  47. });
  48. VBox root = new VBox(tvMain, tfUrl, btnProcess);
  49. Scene scene = new Scene(root);
  50. primaryStage.setScene(scene);
  51. primaryStage.show();
  52. }
  53. public static void main(String[] args) {
  54. launch();
  55. }
  56. public Task<List<JSoupData>> scrapper(String url) {
  57. Task<List<JSoupData>> scrapperTask = new Task<List<JSoupData>>() {
  58. @Override
  59. protected List<JSoupData> call() {
  60. List<JSoupData> jSoupDatas = new ArrayList();
  61. try {
  62. System.out.println("url: " + url);
  63. Document document = Jsoup.connect(url).get();
  64. System.out.println("Title: " + document.title());
  65. Elements gamesNames = document.select(".search-results-row");
  66. System.out.println("search-results-row");
  67. for (Element element : gamesNames) {
  68. jSoupDatas.add(new JSoupData(element.tagName(), element.text()));
  69. System.out.println("Tag Name: " + element.tagName() + " - Text: " + element.text());
  70. }
  71. } catch (IOException e) {
  72. System.out.println(e.toString());
  73. }
  74. return jSoupDatas;
  75. }
  76. };
  77. return scrapperTask;
  78. }
  79. }

JSoupData

  1. public class JSoupData {
  2. private String tagName;
  3. private String text;
  4. public JSoupData(String tagName, String text) {
  5. this.tagName = tagName;
  6. this.text = text;
  7. }
  8. public String getText() {
  9. return text;
  10. }
  11. public void setText(String text) {
  12. this.text = text;
  13. }
  14. public String getTagName() {
  15. return tagName;
  16. }
  17. public void setTagName(String tagName) {
  18. this.tagName = tagName;
  19. }
  20. @Override
  21. public String toString() {
  22. StringBuilder sb = new StringBuilder();
  23. sb.append("JSoupData{tagName=").append(tagName);
  24. sb.append(", text=").append(text);
  25. sb.append('}');
  26. return sb.toString();
  27. }
  28. }

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

英文:

Here is an example you can use as a guide. The URL you use does not have a result list. I would suggest you use something like 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.

This example uses Task. In the Task setOnSuccedded updates the TableView.

Main

  1. import java.io.IOException;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import javafx.application.Application;
  5. import javafx.collections.FXCollections;
  6. import javafx.collections.ObservableList;
  7. import javafx.concurrent.Task;
  8. import javafx.concurrent.WorkerStateEvent;
  9. import javafx.scene.Scene;
  10. import javafx.scene.control.Button;
  11. import javafx.scene.control.TableColumn;
  12. import javafx.scene.control.TableView;
  13. import javafx.scene.control.TextField;
  14. import javafx.scene.control.cell.PropertyValueFactory;
  15. import javafx.scene.layout.VBox;
  16. import javafx.stage.Stage;
  17. import org.jsoup.Jsoup;
  18. import org.jsoup.nodes.Document;
  19. import org.jsoup.nodes.Element;
  20. import org.jsoup.select.Elements;
  21. /**
  22. * JavaFX App
  23. */
  24. public class App extends Application
  25. {
  26. @Override
  27. public void start(Stage primaryStage)
  28. {
  29. TableView&lt;JSoupData&gt; tvMain = new TableView();
  30. ObservableList&lt;JSoupData&gt; tableItems = FXCollections.observableArrayList();
  31. tvMain.setItems(tableItems);
  32. TableColumn&lt;JSoupData, String&gt; tcTagName = new TableColumn&lt;&gt;(&quot;Tag Name&quot;);
  33. tcTagName.setCellValueFactory(new PropertyValueFactory&lt;&gt;(&quot;tagName&quot;));
  34. TableColumn&lt;JSoupData, String&gt; tcText = new TableColumn&lt;&gt;(&quot;Text&quot;);
  35. tcText.setCellValueFactory(new PropertyValueFactory&lt;&gt;(&quot;text&quot;));
  36. tvMain.getColumns().add(tcTagName);
  37. tvMain.getColumns().add(tcText);
  38. TextField tfUrl = new TextField(&quot;https://www.allkeyshop.com/blog/catalogue/search-game/&quot;);
  39. tfUrl.setPromptText(&quot;Enter URL Here!&quot;);
  40. Button btnProcess = new Button(&quot;Process URL&quot;);
  41. btnProcess.setOnAction((t) -&gt; {
  42. btnProcess.setDisable(true);
  43. Task&lt;List&lt;JSoupData&gt;&gt; task = scrapper(tfUrl.getText());
  44. task.setOnSucceeded((WorkerStateEvent t1) -&gt; {
  45. List&lt;JSoupData&gt; tempList = task.getValue();
  46. tableItems.setAll(tempList);
  47. btnProcess.setDisable(false);
  48. });
  49. Thread thread = new Thread(task);
  50. thread.setDaemon(true);
  51. thread.start();
  52. });
  53. VBox root = new VBox(tvMain, tfUrl, btnProcess);
  54. Scene scene = new Scene(root);
  55. primaryStage.setScene(scene);
  56. primaryStage.show();
  57. }
  58. public static void main(String[] args)
  59. {
  60. launch();
  61. }
  62. public Task&lt;List&lt;JSoupData&gt;&gt; scrapper(String url)
  63. {
  64. Task&lt;List&lt;JSoupData&gt;&gt; scrapperTask = new Task&lt;List&lt;JSoupData&gt;&gt;()
  65. {
  66. @Override
  67. protected List&lt;JSoupData&gt; call()
  68. {
  69. List&lt;JSoupData&gt; jSoupDatas = new ArrayList();
  70. try {
  71. System.out.println(&quot;url: &quot; + url);
  72. Document document = Jsoup.connect(url).get();
  73. System.out.println(&quot;Title: &quot; + document.title());
  74. Elements gamesNames = document.select(&quot;.search-results-row&quot;);
  75. System.out.println(&quot;search-results-row&quot;);
  76. for (Element element : gamesNames) {
  77. jSoupDatas.add(new JSoupData(element.tagName(), element.text()));
  78. System.out.println(&quot;Tag Name: &quot; + element.tagName() + &quot; - Text: &quot; + element.text());
  79. }
  80. }
  81. catch (IOException e) {
  82. System.out.println(e.toString());
  83. }
  84. return jSoupDatas;
  85. }
  86. };
  87. return scrapperTask;
  88. }
  89. }

JSoupData

  1. *
  2. * @author sedrick (sedj601)
  3. */
  4. public class JSoupData
  5. {
  6. private String tagName;
  7. private String text;
  8. public JSoupData(String tagName, String text)
  9. {
  10. this.tagName = tagName;
  11. this.text = text;
  12. }
  13. public String getText()
  14. {
  15. return text;
  16. }
  17. public void setText(String text)
  18. {
  19. this.text = text;
  20. }
  21. public String getTagName()
  22. {
  23. return tagName;
  24. }
  25. public void setTagName(String tagName)
  26. {
  27. this.tagName = tagName;
  28. }
  29. @Override
  30. public String toString()
  31. {
  32. StringBuilder sb = new StringBuilder();
  33. sb.append(&quot;JSoupData{tagName=&quot;).append(tagName);
  34. sb.append(&quot;, text=&quot;).append(text);
  35. sb.append(&#39;}&#39;);
  36. return sb.toString();
  37. }
  38. }

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

答案2

得分: 0

通常,可以使用 Platform.runLater() 来在 JavaFX 应用程序线程上执行这些更新。

您可以从文档中获取更多信息 此处,以及从 此处 获取示例。

英文:

Usually, Platform.runLater() can be used to execute those updates on the JavaFX application thread.

You can get more information from documentation here and an example from here

huangapple
  • 本文由 发表于 2020年10月22日 03:20:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/64470319.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定