Multithreading in JavaFX same application - java

I have an issue with JavaFX and multithreading. Basically I have an application and the task at hand asks me that I should have multiple users. Like for example I have a bug-testing application which shows a list of bugs and users and testers can choose to add/delete bugs from this list(a tableview in my case). Building the application was not a problem, but I don't understand how to 'simulate' multiple users. The task says that when I run my program, 3 windows should appear(2 for users and 1 for a tester), and when I add/delete a bug, the tableview should get updated.
I believe I need to do this with threads, as my last course involved multithreading, but I'm at a loss here. My main class looks like this:
import controller.OfertaCtrl;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import repository.OfertaRepo;
import view.OfertaFXML;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main extends Application {
private static Stage primaryStage;
private static Scene MyPage;
#Override
public void start(Stage primaryStage) throws Exception{
//Platform.setImplicitExit(false);
Main.primaryStage = primaryStage;
setPage();
}
public void setPage() throws IOException {
primaryStage.setTitle("Oferte");
FXMLLoader loader = new FXMLLoader(getClass().getResource("oferta.fxml"));
Pane pane = loader.load();
pane.setId("pane");
MyPage = new Scene(pane);
OfertaRepo repo = new OfertaRepo("C:\\Users\\Mihai\\workspace\\lalal\\newGUI\\src\\oferte.txt");
OfertaCtrl ctrl = new OfertaCtrl(repo);
OfertaFXML ctrl2 = loader.getController();
ctrl2.loadData(ctrl);
primaryStage.setScene(MyPage);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
So basically I take a list of 'offers' in this example from a .txt file and put them in an ObservableArrayList with which I work with in my Controller class. The problem lies in the fact that I don't understand how I need to run multiple threads of the same application. Also, how would I update my tableview for all windows when I modify it in an open window? I was thinking of doing light pooling on my ObservableArrayList and checking for alterations every 1 second or so.
I can provide more information or whatever is needed, I just need a few points on how to go about solving this problem.
Here's how the application looks right now:

Related

I'm trying to import an fxml file into my main class and Parent root = FXMLLoader.load(getClass().getResource()); returns null

I'm trying to import an fxml file into my main class and Parent root = FXMLLoader.load(getClass().getResource(/View/Main_Form.fxml)); returns null.
It basically is telling me that it can't find the "Main_Form.fxml" file that I am asking it to find.
I have it in a package labeled "View" which is the path I specified.
code is as follows:
`package com.example.c482_1;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class HelloApplication extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/view/Main_Form.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}`
file structure of the project
I have tried checking the path, I made my main project the resource root with no luck as well.
Not quite sure but I would try checking to make sure the path is relative

Couldn't find or load main class in JavaFx sample [duplicate]

I'm trying to build a small user interface using JavaFX, But I'm getting an error like this:
Error: Could not find or load main class myApp Caused by:
java.lang.NoClassDefFoundError: javafx/application/Application
This is my code:
and im using jdk 12.0.2
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class myApp extends Application{
public static void main(String[] args) {
Phonebook mybook = new Phonebook();
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
Group group = new Group();
Scene scene = new Scene(group, 600, 300);
scene.setFill(Color.GRAY);
primaryStage.setTitle("Phone Book");
primaryStage.setScene(scene);
primaryStage.show();
}
This is the Libraries and jdk I'm using:
Image1
I think JavaFX is not a part of the JDK > 9 any more. (Your version is 12.x.x)
Probably this could help you:
https://openjfx.io/openjfx-docs/#install-javafx
(Assuming you are using Maven) If this does not help, try to clean and build your Application.
Sometimes Maven does not recognize newly added dependencies.

Context Click doesn't work with Marathon Java Driver

I am currently trying to automate JMeter (as an sample application) using Marathon Java Drivers. I am able to open JMeter but when i try to right click on Test Plan under the left pane, i am not able to do so. Can you please tell me what i am doing wrong. Thanks.
package javadriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriver.Window;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import net.sourceforge.marathon.javadriver.JavaDriver;
import net.sourceforge.marathon.javadriver.JavaProfile;
import net.sourceforge.marathon.javadriver.JavaProfile.LaunchMode;
import net.sourceforge.marathon.javadriver.JavaProfile.LaunchType;
import org.openqa.selenium.support.PageFactory;
public class JavaDriverTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
JavaProfile profile = new JavaProfile(LaunchMode.JAVA_COMMAND_LINE);
profile.setLaunchType(LaunchType.SWING_APPLICATION);
profile.setMainClass("org.apache.jmeter.NewDriver");
profile.addClassPath("C:\\apache-jmeter-5.1.1\\bin\\ApacheJMeter.jar");
profile.setWorkingDirectory("C:\\\\apache-jmeter-5.1.1\\\\bin");
WebDriver driver = new JavaDriver(profile);
Window window = driver.manage().window();
window.maximize();
WebElement elementLocator = driver.findElement(By.cssSelector("label[text='Test Plan']"));
new Actions(driver).moveToElement(elementLocator, 50, 25).contextClick(elementLocator).build().perform();
//new Actions(driver).clickAndHold(elementLocator);
//new Actions(driver).contextClick(elementLocator).perform();
//driver.quit();
}
}
Looks like you are trying to get the components before the application is completely opened. So Marathon is not able to find the component.
The right click you wanted to perform is a tree item so you need to find the tree and then get node from that.
Check this link for how to locate different types of components where for Swing and JavaFX both are defined. https://marathontesting.com/marathonite-user-guide/selenium-webdriver-bindings/
Please check the following code this will give a better understanding.
package javadriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import net.sourceforge.marathon.javadriver.JavaDriver;
import net.sourceforge.marathon.javadriver.JavaProfile;
import net.sourceforge.marathon.javadriver.JavaProfile.LaunchMode;
import net.sourceforge.marathon.javadriver.JavaProfile.LaunchType;
public class JMeterTest {
private JavaDriver driver;
#BeforeTest
public void createJavaProfile_ExecJarLauncher() {
// We prefer Executable jar rather than using Java Command Line
// launcher as the application loads with a blurb and then the main
// window opens. So that we can specify the Start window from where the
// operations are performed. Other wise after creating driver you need to put sleep until the main window is opens.
JavaProfile profile = new JavaProfile(LaunchMode.EXECUTABLE_JAR);
profile.setLaunchType(LaunchType.SWING_APPLICATION);
profile.setExecutableJar("/Users/adityakarra/Projects/apache-jmeter-5.2.1/bin/ApacheJMeter.jar");
profile.setWorkingDirectory("/Users/adityakarra/Projects/apache-jmeter-5.2.1/bin");
// As the application title differs based on the Version number we have
// passed regex to match the window title.
profile.setStartWindowTitle("/^Apache JMeter.*");
driver = new JavaDriver(profile);
// Finally printing the window title after every thing is loaded.
System.out.println("Window Title ::: " + driver.getTitle());
}
#Test
public void getTreeItem() throws InterruptedException {
// As the context menu you wanted to click is a tree item. So find the
// tree initally.
WebElement tree = driver.findElementByTagName("tree");
// Now for getting the tree item we use select by properties and get the
// node.
WebElement node = tree.findElement(By.cssSelector(".::select-by-properties('{\"select\":\"/Test Plan\"}')"));
// Performing right click on the tree item
new Actions(driver).moveToElement(node, 50, 25).contextClick(node).build().perform();
// Clicking on one of the menu items in the context menu.
driver.findElementByCssSelector("menu-item[text='Disable']").click();
new Actions(driver).moveToElement(node, 50, 25).contextClick(node).build().perform();
driver.findElementByCssSelector("menu-item[text='Enable']").click();
}
#AfterTest
public void tearDown() {
if (driver != null)
driver.quit();
}
}
Note: I'm one of the contributor for Marathon.

Run JavaFX app from the command line without GUI

I have a JavaFX in which the user can select files to be processed. Now I want to automate it so that you can run the application from the command line and pass those files as a parameter. I tried to do this:
java -jar CTester.jar -cl file.txt
public static void main(String[] args)
{
if (Arrays.asList(args).contains("-cl"))
{
foo();
}
else
{
launch(args);
}
}
The main is executed and the argument is correct, but this still creates the GUI.
From the docs:
The entry point for JavaFX applications is the Application class. The
JavaFX runtime does the following, in order, whenever an application
is launched:
Constructs an instance of the specified Application class
Calls the init() method
Calls the start(javafx.stage.Stage) method
Waits for the application to finish, which happens when either of the following
occur:
the application calls Platform.exit()
the last window has been closed and the implicitExit attribute on Platform is true
Calls the stop() method
So if I cannot use the main method, how can I create this "alterantive" flow? I thought about creating a normal java application as a wrapper but that seems a little bit overkill for such a simple task. Is there a more elegant way of doing this?
Simply exit the application after calling your foo() method:
Platform.exit();
Here is a quick sample application to demonstrate:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class CLSample extends Application {
public static void main(String[] args) {
if (Arrays.asList(args).contains("-cl")) {
commandLine();
Platform.exit();
} else {
launch(args);
}
}
public static void commandLine() {
System.out.println("Running only command line version...");
}
#Override
public void start(Stage primaryStage) {
// Simple Interface
VBox root = new VBox(10);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(10));
root.getChildren().add(new Label("GUI Loaded!"));
// Show the stage
primaryStage.setScene(new Scene(root));
primaryStage.setTitle("CLSample Sample");
primaryStage.show();
}
}
If you pass -cl, then only the commandLine() method gets called.

How to keep Java FXML active while file is loading

I am using JAVA FXML GUI to parse a text file. The user can select which file to parse and then press "load". When the user clicks on "load" the file gets parse and many lines gets added to an ArrayList. The user then search and manipulate the text that was parse that is store in the ArrayList.
Sometimes while loading/writing the file to the ArrayList or manipulating some lines, the GUI is not responsive. How can I separate the GUI process vs. the ArrayList handling in order for the GUI to always be accessible to the user ?
The code below launches my application:
package javafxapp;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Javafxapp extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
FXMLDocumentController controller = new FXMLDocumentController();
controller.openingSound();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
This is a textbook case for the use of multithreading.
See this JavaFX documentation for information and tutorials on how to begin using it.

Categories

Resources