This question already has an answer here:
App hangs up or "Not on FX application thread" occurs during app activity
(1 answer)
Closed 7 years ago.
Help me to realize the Line Chart and how to do better.
I need to add a Line Chart 2-3 The schedule of 30 - the values reach from the database. I wanted to make a separate stream, but there are errors.
ERROR : 'Exception in thread "Thread-4"
java.lang.IllegalStateException: Not on FX application thread;
currentThread = Thread-4''
import extfx.scene.chart.DateAxis;
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import java.util.Date;
import java.util.GregorianCalendar;
public class main extends Application{
public static void main(String[] args) {
launch(args);
}
public static LineChart<Date, Number> lineChart;
public static Thread threadInTrendFlow;
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("-----------------------");
NumberAxis numberAxis = new NumberAxis();
DateAxis dateAxis = new DateAxis();
lineChart = new LineChart<Date, Number>(dateAxis,numberAxis);
lineChart.getData().add(scFlow.series);
BorderPane pane = new BorderPane();
pane.setCenter(lineChart);
///
Button inLineChart = new Button("insert");
inLineChart.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Task<Void> loaded = new scFlow();
threadInTrendFlow = new Thread(loaded);
threadInTrendFlow.start();
}
});
pane.setTop(inLineChart);
Scene scene = new Scene(pane,800,600);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Use Platform.runlater(()->{}) when invoking stuff that goes on the application thread.
There are plenty of threads related to somewhat similar problems. Just search multithreading javafx.
Related
Correction: this works fine, I was being stupid.
I'm trying to disable a JavaFx ChoiceBox. Thought this would work:
shapeList = FXCollections.observableArrayList(CShape.DOT, CShape.RIGHT_GLIDER, CShape.LEFT_GLIDER);
choiceBox = new ChoiceBox<>(shapeList);
choiceBox.setDisable(true);
but it doesn't seem to.
Everything with disable/enable works just fine. You should provide more of your code to find the flaw.
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class ChoiceBoxDisableApp extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
ObservableList<String> items = FXCollections.observableArrayList("one", "two", "three");
ChoiceBox<String> choiceBox = new ChoiceBox<>(items);
Button button = new Button("Disable");
HBox hBox = new HBox(choiceBox, button);
button.setOnMouseClicked(mouseEvent -> {
boolean disable = !choiceBox.isDisabled();
choiceBox.setDisable(disable);
button.setText(disable ? "Enable" : "Disable");
});
stage.setScene(new Scene(hBox));
stage.show();
}
}
i am using javafx and working on a application CRUD. i nedd data in a combobox and when i select any of the data from one combobox the related data should be display on another combobox. the data source is mysql.
This is just a simple example you need to add data form mysql to combo box see this ? code post a comment if any ?s.
Example
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Table extends Application {
private Stage primaryStage;
private AnchorPane pane;
#Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("AddressApp");
VBox v = new VBox(10);
ComboBox<String> c = new ComboBox<String>();
ComboBox<String> c1 = new ComboBox<String>();
ObservableList<String> sList = FXCollections.observableArrayList();
sList.addAll("b", "c", "dd", "dcd", "dddf");
c.setItems(sList);
c1.setItems(sList);
// c1.valueProperty().bind(c.valueProperty());
c1.valueProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
c.setValue(newValue);
}
});
v.getChildren().addAll(c, c1);
Scene Scene = new Scene(v);
primaryStage.setScene(Scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I want to draw red borders around arbitrary javafx.scene.text.Text nodes in my JavaFX scenegraph, for example those in a Button object.
It is easy to retrieve all the Text nodes but not to find where they are in the scene, they have an x and y property which doesn't seem to get set properly but they do not have a width and height.
So far I have tried to add rectangles with a red stroke to a stack pane but the x and y are always wrong and I can't get the size.
One solution is to wrap the text nodes in layout pane (such as an HBox) and use CSS on the layout pane:
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class TextBorderExample extends Application {
#Override
public void start(Stage primaryStage) {
final HBox root = new HBox(5);
root.getChildren().addAll(
new Text("This"), new Text("Is"), new Text("A"), createBorderedText("Red"), new Text("Bordered"), new Text("Text")
);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
private Node createBorderedText(String text) {
final HBox hbox = new HBox();
hbox.getChildren().add(new Text(text));
hbox.setStyle("-fx-border-color: red;");
return hbox ;
}
public static void main(String[] args) {
launch(args);
}
}
Another way is to use a Rectangle, as follows:
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class TextBorderExample extends Application {
#Override
public void start(Stage primaryStage) {
final HBox root = new HBox(5);
final Text red = new Text("Red");
final Rectangle redBorder = new Rectangle(0, 0, Color.TRANSPARENT);
redBorder.setStroke(Color.RED);
redBorder.setManaged(false);
red.boundsInParentProperty().addListener(new ChangeListener<Bounds>() {
#Override
public void changed(ObservableValue<? extends Bounds> observable,
Bounds oldValue, Bounds newValue) {
redBorder.setLayoutX(red.getBoundsInParent().getMinX());
redBorder.setLayoutY(red.getBoundsInParent().getMinY());
redBorder.setWidth(red.getBoundsInParent().getWidth());
redBorder.setHeight(red.getBoundsInParent().getHeight());
}
});
root.getChildren().addAll(new Text("This"), new Text("Is"), new Text("A"), red, new Text("Bordered"), new Text("Text"));
root.getChildren().add(redBorder);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
actually i'm looking for something very similar to this thread:
How to hide the controls of HTMLEditor?
so basically i try to add a custom button to the javafx html editor but with the difference that it's implemented through FXML.
So my question is:
Is there a "work-around" to add custom buttons to the html-editor when it's implemented through FXML?
Sample solution is :
htmlEditor.setVisible(false);
Platform.runLater(new Runnable() {
#Override
public void run() {
Node[] nodes = htmlEditor.lookupAll(".tool-bar").toArray(new Node[0]);
for (Node node : nodes) {
node.setVisible(false);
node.setManaged(false);
}
htmlEditor.setVisible(true);
}
});
I have modified the #jewelsea answer for javaFX9.
I have also added some customization to move toolbars. The main idea is to get all the components by css selector, then modify or hide them. Read the class HTMLEditorSkin to get the CSS classes names, like ".html-editor-align-center" for the align button.
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Pattern;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.MenuButton;
import javafx.scene.control.MenuItem;
import javafx.scene.control.RadioMenuItem;
import javafx.scene.control.ToolBar;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.web.HTMLEditor;
import javafx.stage.Stage;
public class HTMLEditorCustomizationSample2 extends Application {
// limits the fonts a user can select from in the html editor.
private static final ObservableList<String> limitedFonts = FXCollections.observableArrayList("Arial",
"Times New Roman", "Courier New", "Comic Sans MS");
private HTMLEditor htmlEditor;
public static void main(String[] args) {
launch(args);
}
#SuppressWarnings("unchecked")
#Override
public void start(Stage stage) {
htmlEditor = new HTMLEditor();
stage.setScene(new Scene(htmlEditor));
stage.show();
customizeEditor(htmlEditor);
}
private void customizeEditor(HTMLEditor htmlEditor) {
// hide controls we don't need.
Node seperator = htmlEditor.lookup(".separator");
seperator.setVisible(false);
seperator.setManaged(false);
hideByClass(htmlEditor, ".separator");
hideByClass(htmlEditor, ".html-editor-cut", ".html-editor-copy", ".html-editor-paste", ".html-editor-strike",
".html-editor-hr");
hideByClass(htmlEditor, ".html-editor-align-left"
, ".html-editor-align-center"
, ".html-editor-align-right"
, ".html-editor-align-justify", ".html-editor-outdent"
, ".html-editor-indent", ".html-editor-bullets"
, ".html-editor-numbers");
// Move the toolbars
Node top= htmlEditor.lookup(".top-toolbar");
GridPane.setConstraints(top,1,0,1,1);
Node bottom= htmlEditor.lookup(".bottom-toolbar");
GridPane.setConstraints(bottom,0,0,1,1);
Node web= htmlEditor.lookup("WebView");
GridPane.setConstraints(web,0,1,2,1);
// modify font selections.
int i = 0;
Set<Node> fonts = htmlEditor.lookupAll(".font-menu-button");
Iterator<Node> fontsIterator = fonts.iterator();
fontsIterator.next();
ComboBox<String> formatComboBox = (ComboBox<String>) fontsIterator.next();
formatComboBox.itemsProperty().addListener((obs, old, value) -> {
if (value.size() != limitedFonts.size()) {// should loop on array for equality
Platform.runLater(() -> {
value.clear();
// stop.set(true);
value.addAll(limitedFonts);
formatComboBox.setValue(limitedFonts.get(0));
});
}
});
// add a custom button to the top toolbar.
Node node = htmlEditor.lookup(".top-toolbar");
if (node instanceof ToolBar) {
ToolBar bar = (ToolBar) node;
ImageView graphic = new ImageView(
new Image("http://bluebuddies.com/gallery/title/jpg/Smurf_Fun_100x100.jpg", 16 , 16, true, true));
graphic.setEffect(new DropShadow());
Button smurfButton = new Button("", graphic);
bar.getItems().add(smurfButton);
smurfButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
htmlEditor.setHtmlText("<font face='Comic Sans MS' color='blue'>Smurfs are having fun :-)</font>");
}
});
}
}
private void hideByClass(HTMLEditor htmlEditor, String... selectors) {
for (String selector : selectors) {
Set<Node> nodes = htmlEditor.lookupAll(selector);
for (Node node : nodes) {
node.setVisible(false);
node.setManaged(false);
}
}
}
#Override
public void stop() throws Exception {
super.stop();
System.out.println(htmlEditor.getHtmlText());
}
}
Here is some sample code which customizes the HTMLEditor and adds a custom button to it. The sample code does not use fxml but really it's very similar if fxml is used. You could define the HTMLEditor in fxml and inject it into your Controller using the standard #FXML annotation. Once you have a reference to the editor, customize it in Java code using an appropriate variation of the sample code. For the added button, just create it in Java rather than fxml and it will be simpler.
This is not working for me, the context menu doesn't get displayed:
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
/**
*
* #author Alvaro
*/
public class TextAreaContextMenu extends Application {
Group root = new Group();
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setScene(new Scene(root));
TextArea t = new TextArea();
ContextMenu m = new ContextMenu();
m.setOnShowing(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent arg0) {
System.out.println("Showing...");
}
});
MenuItem item = new MenuItem("Item");
m.getItems().add(item);
t.setContextMenu(m);
root.getChildren().add(t);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Is this a bug? or am I doing something wrong?
I'm running jdk1.7.0_02, and I think JavaFX 2.0.2 SDK.
BTW, how do I find out, exactly which JavaFX SDK version I have installed?
Thanks in advance for any help.
Your code works for me with JavaFX 2.1 dev build on Windows. Right-click on text area shows menu with one element named "item".
Can you try 2.1 dev version?
You can find out your current version by running next code:
System.out.println(com.sun.javafx.runtime.VersionInfo.getVersion());