Good evening everyone,
I have a test application consists of two windows: Main, Window1.
to display the "Window1" window from the main window I click on a button. My problem is that closing the "window1" window automatically close the application. I would like when I click on (X) of the window "window1" I have to return to the main window (not exit the application).
here is the code:
MainScreen.fxml
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="166.0" prefWidth="307.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="testexample.MainScreenController">
<children>
<Button layoutX="128.0" layoutY="127.0" mnemonicParsing="false" onAction="#showScreen1" prefHeight="25.0" prefWidth="57.0" text="show..." />
<Label layoutX="114.0" layoutY="31.0" text="Main Screen">
<font>
<Font size="25.0" />
</font>
</Label>
</children>
</AnchorPane>
MainScreenController
public class MainScreenController implements Initializable {
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
#FXML
private void showScreen1(ActionEvent event) throws IOException {
Parent root = (Parent) FXMLLoader.load(getClass().getResource("Screen1.fxml"));
Scene scene = new Scene(root);
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
stage.setScene(scene);
stage.show();
}}
Screen1.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="202.0" prefWidth="463.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="testexample.Screen1Controller">
<children>
<Label layoutX="58.0" layoutY="40.0" prefHeight="53.0" prefWidth="342.0" text="Welcome to screen 1">
<font>
<Font size="36.0" />
</font>
</Label>
</children>
</AnchorPane>
class that contains method start() and method main():
public class TestExample extends Application {
#Override
public void start(Stage stage) throws IOException {
AnchorPane root = (AnchorPane)FXMLLoader.load(getClass().getResource("MainScreen.fxml"));
Scene sc = new Scene(root);
stage.setScene(sc);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
By default, a JavaFX application will exit when all windows are closed. You can prevent this behavior by calling
Platform.setImplicitExit(false);
in your Application's start(...) method.
I'm not sure this is your problem, however, because nowhere in your code do you create a second window: you just load up a new FXML file, put its contents in a new Scene, and display it in the existing window:
#FXML
private void showScreen1(ActionEvent event) throws IOException {
// Load new FXML file and save root Node as "root":
Parent root = (Parent) FXMLLoader.load(getClass().getResource("Screen1.fxml"));
// Create a new Scene to display the root node just loaded:
Scene scene = new Scene(root);
// Get a reference to the existing stage (the window containing the source of the event; the "show..." Button)
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
// Set the new scene in the existing stage:
stage.setScene(scene);
// Show the existing stage (though it is already showing, I think):
stage.show();
}
From your description, it sounds like you want to create a second window, which the user has to dismiss before returning to the original window. You can do this by creating a new stage, making its owner the existing stage, and making it modal:
#FXML
private void showScreen1(ActionEvent event) throws IOException {
Parent root = (Parent) FXMLLoader.load(getClass().getResource("Screen1.fxml"));
Scene scene = new Scene(root);
Window existingWindow = ((Node) event.getSource()).getScene().getWindow();
// create a new stage:
Stage stage = new Stage();
// make it modal:
stage.initModality(Modality.APPLICATION_MODAL);
// make its owner the existing window:
stage.initOwner(existingWindow);
stage.setScene(scene);
stage.show();
}
Related
i'm try a write a simple javafx program using the GmapsFX. this is the code that i copied from internet for learn the main rudiments of this library.
this is the file .fxml
<?import com.lynden.gmapsfx.GoogleMapView?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
<children>
<GoogleMapView fx:id="mapView" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
<Label alignment="CENTER" contentDisplay="CENTER" text="Map" AnchorPane.bottomAnchor="376.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
this is the controller:
package application;
import com.lynden.gmapsfx.GoogleMapView;
import com.lynden.gmapsfx.MapComponentInitializedListener;
import com.lynden.gmapsfx.javascript.object.GoogleMap;
import com.lynden.gmapsfx.javascript.object.InfoWindow;
import com.lynden.gmapsfx.javascript.object.InfoWindowOptions;
import com.lynden.gmapsfx.javascript.object.LatLong;
import com.lynden.gmapsfx.javascript.object.MapOptions;
import com.lynden.gmapsfx.javascript.object.MapTypeIdEnum;
import com.lynden.gmapsfx.javascript.object.Marker;
import com.lynden.gmapsfx.javascript.object.MarkerOptions;
import javafx.fxml.FXML;
public class SampleController implements MapComponentInitializedListener {
#FXML
private GoogleMapView mapView;
private GoogleMap map = null;
#Override
public void mapInitialized() {
MapOptions mapOptions = new MapOptions();
LatLong latLong = new LatLong(47.6097, -122.3331);
mapOptions.center(latLong)
.mapType(MapTypeIdEnum.ROADMAP)
.overviewMapControl(false)
.panControl(false)
.rotateControl(false)
.scaleControl(false)
.streetViewControl(false)
.zoomControl(false)
.zoom(12);
map = mapView.createMap(mapOptions);
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLong);
Marker marker = new Marker(markerOptions);
map.addMarker(marker);
InfoWindowOptions infoWindowOptions = new InfoWindowOptions();
infoWindowOptions.content("<h2>ROMA</h2>Location di Roma<br>");
InfoWindow infoWindow = new InfoWindow(infoWindowOptions);
infoWindow.open(map, marker);
}
#FXML
public void initialize() {
assert mapView != null : "fx:id=\"mapView\" was not injected: check your FXML file 'Sample.fxml'.";
mapView.addMapInializedListener(this);
}
}
and the answer from eclipse is:
1866 [JavaFX Application Thread] INFO com.lynden.gmapsfx.GoogleMapView - Alert: Hide directions called
is there anyone that can help me, please
So, I am new to JavaFX and as part of a project I am attempting to use ImageView to display some images. Before adding to my actual project, I set up the following to be sure I understood how to use ImageViews.
My Controller:
import javafx.fxml.FXML;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
public class TestController {
#FXML
ImageView imageView;
Image image;
public void start(Stage stage){
/*
* THIS WORKS!
*
* image = new Image("file:/C://Users//Owner//Pictures//MyProjectPhotos/picture.jpg");
*/
//BUT THIS DOESN'T :(
image = new Image("file:/JavaFXPractice/photos/picture.jpg");
imageView.setImage(image);
imageView.setOnMouseClicked(me -> System.out.println("hello"));
}
}
The fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0"
xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="application.TestController">
<children>
<VBox layoutX="156.0" layoutY="88.0" prefHeight="272.0" prefWidth="378.0">
<children>
<ImageView fx:id="imageView" fitHeight="276.0" fitWidth="378.0"
pickOnBounds="true" preserveRatio="true" />
</children>
</VBox>
</children>
</AnchorPane>
And finally this:
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/TestPage.fxml"));
AnchorPane root = (AnchorPane) loader.load();
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.show();
TestController control = loader.getController();
control.start(primaryStage);
}
public static void main(String[] args) {
launch(args);
}
}
My problem is in the TestController class. As you can see in the multi-line comment (and also the comment/line of code below it), the image displays properly when I get it from my local machine, but not when I get it from my project space. I have tried for hours now to figure this out, but every single time I try to retrieve any photo from my project space, nothing appears on the ImageView. It is not null (neither is the Image), and there are no reported errors. I have also tried searching for an answer, but no luck so far.
You can load your images like this:
image = new Image(getClass().getResource("/photos/picture.jpg").toExternalForm());
under the assumption, that "photos" is a folder at the root of your project. This folder must be on the classpath. Depending on your IDE this can be achieved in different ways. In Eclipse this can be achieved by putting this folder into a "source folder". A typical structure is
project
src
...
res
photos
picture.jpg
where both "src" and "res" are source folders.
So here is my situation:
I have built a GUI using the scene Builder and it works just fine: A search box and a list. When the user search a value the results are correctly displayed on the list.
What I've tried to do is to add a progress bar to be showed when the user makes a search. For that I have added a pane to be used as a wrapper and inside the pane there is the progress bar.
On the controller initialization I do a:
progressBarWrapper.setVisible(false)
which works. When I try to activate it inside the search it doesn't:
private void search() {
progressBarWrapper.setVisible(true);
String val = searchField.getText();
if (val!= null && !"".equals(val)) {
ObjectList list = service.getObjects(val);
objects.clear();
objects.addAll(list);
}
progressBarWrapper.setVisible(false);
}
what I've realized is that if I remove the bottom line where the wrapper is set to invisible again I do get my progress bar to show up, however only when I already have the results.
I guess this is some kind of blocking issue or the redraw process of the screen beeing held back while computations are beeing made, however I don't understand what is going on... can somebody shed a light on it so I can develop it further? Just explain why this behaviour happens so I can have an idea on how to solve it.
Thanks
EDIT: Here I am adding a SSCCE to exemplify
Main.java
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("Main.fxml"));
Parent root = loader.load();
Scene primaryScene = new Scene(root);
primaryStage.setScene(primaryScene);
primaryStage.setTitle("Test");
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
In the controller I have simulated the getting of data through a simple loop with a thread sleep inside.
MainController.java
package application;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.Pane;
public class MainController {
#FXML
private Button startLoop;
#FXML
private ProgressBar progressBar;
#FXML
private Pane progressBarWrapper;
#FXML
private Label loopCounter;
#FXML
public void initialize() {
System.out.println("Application Started");
progressBarWrapper.setVisible(false);
}
#FXML
private void doLoop() {
progressBarWrapper.setVisible(true);
for (int i = 1; i <= 5; i++) {
progressBar.setProgress(i * 0.2);
loopCounter.setText(String.format("%s loop(s)", i));
try {
Thread.sleep(1000); // 1000 milliseconds is one second.
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
progressBarWrapper.setVisible(false);
}
}
And the View:
Main.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.*?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainController">
<children>
<Button fx:id="startLoop" layoutX="258.0" layoutY="14.0" mnemonicParsing="false" onAction="#doLoop" prefHeight="80.0" prefWidth="84.0" text="START LOOP" />
<Label fx:id="loopCounter" layoutX="286.0" layoutY="165.0" text="0">
<font>
<Font name="System Bold" size="48.0" />
</font>
</Label>
<Pane fx:id="progressBarWrapper" layoutX="461.0" layoutY="297.0" prefHeight="400.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<ProgressBar fx:id="progressBar" layoutX="200.0" layoutY="191.0" prefWidth="200.0" progress="0.0">
<cursor>
<Cursor fx:constant="WAIT" />
</cursor>
</ProgressBar>
</children>
</Pane>
</children>
</AnchorPane>
All is simply under a package called "application"
During some help by the user kleopatra in the comments I came accross the following link from oracle:
https://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm
Basically my problem sums up to the following:
The JavaFX scene graph, which represents the graphical user interface
of a JavaFX application, is not thread-safe and can only be accessed
and modified from the UI thread also known as the JavaFX Application
thread. Implementing long-running tasks on the JavaFX Application
thread inevitably makes an application UI unresponsive. A best
practice is to do these tasks on one or more background threads and
let the JavaFX Application thread process user events.
Hope it helps someone!
I'm developing a software for the comparison of different amounts of data and I want to use charts to display them in a horizontal way.
Important for me is to display just 3 charts on one side. If there are more than 3 the user shall scroll to the other charts.
It won't look exactly like that pic, I'm too lazy for css. The idea is to put all the charts in a GridPane inside a ScrollPane. Bind the charts so the width is exactly 1/3 of the TabPane width.
I used FXML since it's easier to make a scene.
FXMLDocument.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<TabPane fx:id="tabPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" tabClosingPolicy="UNAVAILABLE" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="horizcharts.FXMLDocumentController">
<tabs>
<Tab text="Main View">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<Button layoutX="181.0" layoutY="112.0" mnemonicParsing="false" onAction="#addChart" text="Add Chart" />
</children></AnchorPane>
</content>
</Tab>
<Tab text="Compare">
<content>
<ScrollPane maxWidth="1.7976931348623157E308">
<content>
<GridPane fx:id="grid" gridLinesVisible="true">
</GridPane>
</content>
</ScrollPane>
</content>
</Tab>
</tabs>
</TabPane>
FXMLDocumentController.java
package horizcharts;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.control.Label;
import javafx.scene.control.TabPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
public class FXMLDocumentController implements Initializable {
#FXML GridPane grid;
#FXML TabPane tabPane;
private int numCharts = 0;
#FXML private void addChart(ActionEvent event) {
VBox vb = randChart(numCharts);
GridPane.setConstraints(vb, numCharts++,0);
grid.getChildren().add(vb);
}
private VBox randChart(int num){
CategoryAxis xAxis = new CategoryAxis();
NumberAxis yAxis = new NumberAxis();
BarChart<String, Number> bc = new BarChart(xAxis, yAxis);
BarChart.Series<String, Number> series = new BarChart.Series<>();
series.setName("Bar Chart "+num);
bc.getData().add(series);
for (int i = 0; i<5; i++){
series.getData().add(new BarChart.Data("cat "+i, Math.random()*10*i));
}
bc.prefWidthProperty().bind(tabPane.widthProperty().subtract(6).divide(3));
bc.prefHeightProperty().bind(tabPane.heightProperty().subtract(180));//guess heights
VBox vb = new VBox(5,new Label("Version "+num), bc, new Label("precision"), new Label("recall"));
return vb;
}
#Override
public void initialize(URL url, ResourceBundle rb) {
}
}
Regular main class HorizCharts.java.
package horizcharts;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class HorizCharts 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();
}
public static void main(String[] args) { launch(args); }
}
I have 2 layouts,in first layout I have EditText,Button and in second layout I have TextView. What I want is when i write something in EditText to copy that in second layout when you press button,but i get crash every time. Is there any way to use components from two layouts or i am missing something. If this is imposible another way would be good. Thx
main activity
public void onCreate(Bundle ivansad) {
super.onCreate(ivansad);
setContentView(R.layout.activity_main);
Button Start = (Button) findViewById(R.id.bStart);
Start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
setContentView(R.layout.numbers);
Intent Changeto2 = new Intent (MainAct.this, Numgen.class);
startActivity(Changeto2);
}
});
}
second activity
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.numbers);
Button Next = (Button)findViewById(R.id.bNext);
final EditText text = (EditText)findViewById(R.id.broj1);
final TextView edit = (TextView)findViewById(R.id.lb1);
Next.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
edit.setText(text.getText());
}
});
}
First layout
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="Deprecated"
android:background="#drawable/grey_bg" >
<Button
android:id="#+id/bNext"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:layout_x="-1dp"
android:layout_y="405dp"
android:background="#000000"
android:text="Dalje"
android:textColor="#ffffff"
tools:ignore="HardcodedText" />
<EditText
android:textColor="#ffffff"
android:id="#+id/broj1"
android:layout_width="154dp"
android:layout_height="50dp"
android:layout_x="164dp"
android:layout_y="6dp"
android:background="#drawable/text_bg"
android:ems="10"
android:gravity="center"
android:hint="1-49"
android:inputType="number"
tools:ignore="HardcodedText" >
</AbsoluteLayout>
Second Layout
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/grey_bg"
android:orientation="vertical">
<TextView
android:id="#+id/lb1"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_x="80dp"
android:layout_y="107dp"
android:gravity="center"
android:text=" "
android:textSize="18sp"
tools:ignore="HardcodedText" />
</AbsoluteLayout>
What you want to do is have two separate activities, one to edit the text, and one to display it.
The first one you want to set the layout to layout_main, and set a callback for the button. Inside the callback you want:
final EditText text = (EditText)findViewById(R.id.broj1);
Intent intent = new Intent(MainAct.this, NumGen.class);
Bundle bundle = new Bundle();
bundle.putString("mString",text.getText().toString());
intent.putExtras(bundle);
startActivity(intent);
Then inside your second activity (NumGen?) you can get that string you saved by doing this:
Bundle data = getIntent().getExtras();
String mString="";
if(data.containsKey("mString")){ mString=data.getString("mString"); }
One of the main issues it looks like you might be having is the ids defined in your XML files aren't the same as the ids in your code. After that, read up on how Activities work and pass information.