Editing Label from another Class (Java FX) - java

i have got a question:
i have got a simple Java FX Application where i have a button and when i hit the button a thread task starts which have to change a label every second:
MyController.java
package application;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeUnit.*;
import java.util.*;
import java.text.DateFormat;
public class MyController implements Initializable{
#FXML
private Button myButton;
#FXML
private TextField myCountry;
#FXML
public Label myTime;
#Override
public void initialize(URL location, ResourceBundle resources) {
// TODO Auto-generated method stub
}
public void startTimeThread(ActionEvent event) {
ScheduledThreadPoolExecutor eventPool = new ScheduledThreadPoolExecutor(3);
eventPool.scheduleAtFixedRate
(new CheckSystemTime(), 0, 2, TimeUnit.SECONDS);
myButton.setDisable(true);
}
public void setLabel(String text) {
myTime.setText(text);
}
}
Main.java is the standart one
CheckSystemTime.java
package application;
import java.util.*;
import java.text.DateFormat;
public class CheckSystemTime implements Runnable {
//String locale;
public CheckSystemTime(/**String location**/) {
//this.locale = location;
}
public void run() {
Date rightNow;
DateFormat timeFormatter;
String timeOutput;
rightNow = new Date();
Locale currentLocale = new Locale("de");
timeFormatter = DateFormat.getTimeInstance(DateFormat.DEFAULT, currentLocale);
timeOutput = timeFormatter.format(rightNow);
//e.g. MyController.setLabel(timeOutput); doesnt work
}
}
So my question is, how i am able to access the setLabel Method from the CheckSystemTime class?
i hope you are able to help me how i can solve this problem

Add the MyController or a Label or the textProperty of the Label to the constructor of CheckSystemTime. Then you can keep a local reference inside CheckSystemTime. Then you can access it inside your run method. But make sure to wrap every UI related calls inside Platform.runLater().

Related

Eclipse RCP - ToolItems not rendering with Edge browser until window resized

Hope you can help with a bit of a strange problem I'm having.
Take a very simple RCP application, with a toolbar along the top, where the user can switch between perspectives.
One perspective contains a Browser component.
Normally, when a user switches to the HelpDocumentsView, a browser is displayed and a bunch of red icons (highlighted) appear along the top.
But when using Edge webview2 as the browser component, using the following VM augments:
-Dorg.eclipse.swt.browser.DefaultType=edge -Dorg.eclipse.swt.browser.EdgeDir=path\to\Microsoft.WebView2.FixedVersionRuntime.103.0.1264.37.x64
The red icons are not displayed:
But when the application is resized, they appear:
Somehow the choice of browser rendering engine is changing how the ToolItems are being rendered, and I don't understand why.
I'm trying to use Edge because on Windows it'll use IE, and IE is unable to render the Javascript contained on the page I'd like to render in the browser.
PerspectiveSwitcherToolbar.java:
package com.me.rcp.perspective;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
import com.me.images.ImageProvider;
public class PerspectiveSwitcherToolbar implements EventHandler {
private static final String HELP_ID = "Help"; //$NON-NLS-1$
#Inject
private static MApplication app;
#Inject
private static EPartService partService;
#Inject
private static EModelService modelService;
private static ToolBar toolBar;
#PostConstruct
private static void postConstruct(final Composite parent) {
final Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(new RowLayout(SWT.HORIZONTAL));
toolBar = new ToolBar(composite, SWT.FLAT | SWT.WRAP | SWT.RIGHT);
parent.pack();
perspectiveSwitch("DataDashboard"); //$NON-NLS-1$
}
private static void perspectiveSwitch(final String id) {
final Menu switcherMenu = new Menu(toolBar);
final ToolItem choosePerspective = new ToolItem(toolBar, SWT.DROP_DOWN);
choosePerspective.setImage(ImageProvider.DATA_DASHBOARD);
choosePerspective.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(final SelectionEvent e) {
final Rectangle rect = choosePerspective.getBounds();
final Point pt = switcherMenu.getParent().toDisplay(new Point(rect.x, rect.y));
switcherMenu.setLocation(pt.x, pt.y + rect.height);
switcherMenu.setVisible(true);
}
});
final MenuItem helpMenu = new MenuItem(switcherMenu, SWT.PUSH);
helpMenu.setImage(ImageProvider.HELP);
helpMenu.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(final SelectionEvent e) {
perspectiveSwitch(HELP_ID);
}
});
partService.switchPerspective((MPerspective) modelService.find(id, app));
if (id.equals(HELP_ID)) {
for (int i = 0; i < 10; i++) {
new ToolItem(toolBar, SWT.PUSH).setImage(ImageProvider.USER_GUIDE);
}
}
}
#Override
public void handleEvent(final Event event) {
}
}
HelpDocumentsView.java:
package com.me.rcp.viewpart;
import javax.annotation.PostConstruct;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.widgets.Composite;
public class HelpDocumentsView {
#PostConstruct
public void createPartControl(final Composite parent) {
new Browser(parent, SWT.NONE);
}
}
I think the problem is that the ToolItem doesn't have a text property set, only an image - and because of this one of the nested layout() calls is skipping it
When I set it to a zero-width space (e.g. item.setText("\u200B")) it renders correctly.

Why the items I add to my ObservableList are only accessible from the function they are declared

Context
I just started to learn JavaFX so I'm developing a program to discover it. The program I'm on needs a array, so I used ObservableList. But here is the problem, the items I add to the list are only accessible from the function itself.
Here is the situation :
package fr.cartes;
import fr.cartes.model.MapModel;
import fr.cartes.view.ListMapsController;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
import java.util.ArrayList;
public class MainApp extends Application {
private Stage primaryStage;
private ObservableList<MapModel> maps = FXCollections.observableArrayList();
public static void main(String[] args){
launch(args);
}
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("/!\\ Explorateur /!\\");
this.primaryStage.setAlwaysOnTop(true);
initializationOfProgram();
}
public void initializationOfProgram(){
initializeListMaps();
maps.add(new MapModel("Les Etats-Unis d'Amérique", "EU.jpg"));
maps.add(new MapModel("La France d'aujourdh'ui", "FR.jpg"));
for(MapModel mapModel : maps){
System.out.println(mapModel.getMapName());
}
}
public void initializeListMaps(){
for(MapModel map : maps){
System.out.println(map.getMapName());
}
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("view/ListMaps.fxml"));
Scene scene = new Scene(loader.load());
primaryStage.setScene(scene);
primaryStage.show();
ListMapsController controller = new ListMapsController();
controller.setMainApp(this);
controller.loadMapsOnListView(maps);
}catch(IOException exception){exception.printStackTrace();}
}
public ObservableList<MapModel> getMapsLists(){
return maps;
}
}
For example, if I put a println() test in the initializationOfProgram(), I will have "Les Etats-Unis d'Amérique" and "La France d'aujourd'hui" written on the console, but if I do this println() test in initializeListMaps(), it won't display anything.
Am I missing something obvious here ? Can you help me ?

Cannot find symbol error when calling method from different class file

I'm trying to call a method form a separate class file to my main program java file but when I try to call the method on an object, I get the error symbol cannot be found for the method. Both files are in the same directory.
//This is my main java file for the program
package pwmanager;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* #author 176878
*/
public class PWManager extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Login.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setTitle("Password Manager");
stage.setPrevStage(); //Error occurs here.
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
//This is the other .java file where the method is declared.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package pwmanager;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.event.EventType;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javax.xml.crypto.Data;
/**
*
* #author 176878
*/
public class FXMLDocumentController implements Initializable {
#FXML
private Button loginButton;
private Button addAcct;
private Button removeAcct;
#FXML
public Stage prevStage;
public Stage currentStage;
#FXML
public void loginButtonAction(ActionEvent event) throws IOException {
System.out.println("You clicked me, logging in!");
Stage stage = new Stage();
FXMLLoader loader = new FXMLLoader(getClass().getResource("MainScreen.fxml"));
Parent mainScreen = (Parent)loader.load();
Scene scene = new Scene(mainScreen);
stage.setScene(scene);
stage.setTitle("Password Manager");
//prevStage.close();
stage.show();
}
#FXML
public void addAcctAction(ActionEvent event) throws IOException {
System.out.println("You clicked me, adding account!");
}
#FXML
public void removeAcctAction(ActionEvent event) throws IOException {
System.out.println("You clicked me, removing account!");
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
I need to store the current stage so I can call it back or close the stage out.
setPrevStage is defined in FXMLDocumentController not Stage. You need to inject the former into the main PWManager class so that it can be invoked
controller.setPrevStage(stage);

How do you add a tick to javafx?

I was wondering how to add a tick to javafx. By tick i mean a repetitive thread that updates the scene. I have tried an normal thread but I keep getting error that is is not the application thread. I would like it to start in the initialize method here is a heavily simplified version of my MainContol class:
package application;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.Initializable;
public class MainControl implements Initializable{
public void initialize(URL arg0, ResourceBundle arg1) {
// Tick goes here
}
}
I think what you are looking for is a Timeline. A timeline creates a thread that repeats a set amount of times or infinitely until you terminate it.
Here is how you would at it:
MainControl:
package application;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.animation.TimelineBuilder;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.Initializable;
import javafx.util.Duration;
#SuppressWarnings("deprecation")
public class MainControl implements Initializable{
public void initialize(URL arg0, ResourceBundle arg1) {
Timeline tick = TimelineBuilder.create()//creates a new Timeline
.keyFrames(
new KeyFrame(
new Duration(10),//This is how often it updates in milliseconds
new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
//You put what you want to update here
}
}
)
)
.cycleCount(Timeline.INDEFINITE)
.build();
tick.play();//Starts the timeline
}
}
I hope this helps
If you happen to use Java 8, here is the same thing using ReactFX:
public class MainControl implements Initializable{
public void initialize(URL arg0, ResourceBundle arg1) {
EventStreams.ticks(Duration.ofMillis(10)).subscribe(() -> {
//You put what you want to update here
});
}
}

setText into TextFiend JavaFX with FXML

I have that java class. It's initialized in JavaClassContainer. The problem is that it returns that error: java.lang.NullPointerException. A no set the text to the textfield.
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Enumeration;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
public class RXTX implements SerialPortEventListener{
#FXML private static TextField carlos;
// MORE CODE
#FXML
private void GetData(String Data) {
if(Data.contains("Temperature")){
carlos.setText("Hola");
}
}
}
If I put a System.Out.Println for instance it works. So, The problem is in the setText to the TextField no in GetData class.
Ok, I will put also the main controller:
public class FXMLDocumentController implements Initializable {
#FXML
private Label label;
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
}
#Override
public void initialize(URL url, ResourceBundle rb) {
RXTX main = new RXTX();
main.initialize();
Thread t=new Thread() {
public void run() {
//the following line will keep this app alive for 1000 seconds,
//waiting for events to occur and responding to them (printing incoming messages to console).
try {Thread.sleep(1000000);} catch (InterruptedException ie) {}
}
};
t.start();
System.out.println("Started");
}
}
Well - what makes you believe that your RXTX.carlos is injected a value? You are creating the instance yourself so you are responsible to set a value to the STATIC field there.
I think you should:
learn about how to use a debugger in your IDE
learn more about how FXML works

Categories

Resources