I need some help trying to get two things appearing on this borderpane. Currently I have the center set as a Gridpane. I need to add a mediaview and the text displayed in the class ButtonDemo both to the Gridpane. I also have to set the top of the borderpane to have a moving square. I can't figure out how to animate the square. But currently I am having trouble getting these two things to display. If anyone could help explain why these two objects won't display that would be very helpful. Thanks!
import javafx.application.Application;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.beans.property.DoubleProperty;
import javafx.stage.Stage;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.CheckBox;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.control.Slider;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.util.Duration;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
//Up and Down Button Class
class ButtonDemo extends Application {
protected Text text = new Text(50, 50, "Assignment 7");
public GridPane grid = new GridPane();
protected BorderPane getPane() {
HBox paneForButtons = new HBox(20);
Button btUp = new Button("^ Up ");
Button btDown = new Button("v Down ");
paneForButtons.getChildren().addAll(btUp, btDown);
paneForButtons.setStyle("-fx-border-color: green");
BorderPane border = new BorderPane();
border.setBottom(paneForButtons);
Pane paneForText = new Pane();
paneForText.getChildren().add(text);
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(0, 10, 0, 10));
border.setCenter(grid);
grid.add(paneForText, 1, 10);
btUp.setOnAction(e -> text.setY(text.getY() - 10));
btDown.setOnAction(e -> text.setY(text.getY() + 10));
return border;
}
#Override
public void start(Stage primaryStage) {
Scene scene = new Scene(getPane(), 800, 650);
primaryStage.setTitle("Assignment 7");
primaryStage.setScene(scene);
primaryStage.show();
}
}
//Font Type Class
class CheckBoxDemo extends ButtonDemo {
#Override
protected BorderPane getPane() {
BorderPane border = super.getPane();
Font fontBoldItalic = Font.font("Arial",
FontWeight.BOLD, FontPosture.ITALIC, 20);
Font fontBold = Font.font("Arial",
FontWeight.BOLD, FontPosture.REGULAR, 20);
Font fontItalic = Font.font("Arial",
FontWeight.NORMAL, FontPosture.ITALIC, 20);
Font fontNormal = Font.font("Arial",
FontWeight.NORMAL, FontPosture.REGULAR, 20);
text.setFont(fontNormal);
VBox paneForCheckBoxes = new VBox(20);
paneForCheckBoxes.setPadding(new Insets(5, 5, 5, 5));
paneForCheckBoxes.setStyle("-fx-border-color: green");
CheckBox chkBold = new CheckBox("Bold");
CheckBox chkItalic = new CheckBox("Italic");
paneForCheckBoxes.getChildren().addAll(chkBold, chkItalic);
border.setLeft(paneForCheckBoxes);
EventHandler<ActionEvent> handler = e -> {
if (chkBold.isSelected() && chkItalic.isSelected()) {
text.setFont(fontBoldItalic);
}
else if (chkBold.isSelected()) {
text.setFont(fontBold);
}
else if (chkItalic.isSelected()) {
text.setFont(fontItalic);
}
else {
text.setFont(fontNormal);
}
};
chkBold.setOnAction(handler);
chkItalic.setOnAction(handler);
return border;
}
}
//Color Button Class
class RadioButtonDemo extends CheckBoxDemo {
#Override
protected BorderPane getPane() {
BorderPane border = super.getPane();
VBox paneForRadioButtons = new VBox(20);
paneForRadioButtons.setPadding(new Insets(5, 5, 5, 5));
paneForRadioButtons.setStyle("-fx-border-color: black");
paneForRadioButtons.setStyle("-fx-border-color: green");
RadioButton rbYellow = new RadioButton("Yellow");
RadioButton rbOrange = new RadioButton("Orange");
RadioButton rbPurple = new RadioButton("Purple");
paneForRadioButtons.getChildren().addAll(rbYellow, rbOrange, rbPurple);
border.setRight(paneForRadioButtons);
ToggleGroup group = new ToggleGroup();
rbYellow.setToggleGroup(group);
rbOrange.setToggleGroup(group);
rbPurple.setToggleGroup(group);
rbYellow.setOnAction(e -> {
if (rbYellow.isSelected()) {
text.setFill(Color.YELLOW);
}
});
rbOrange.setOnAction(e -> {
if (rbOrange.isSelected()) {
text.setFill(Color.ORANGE);
}
});
rbPurple.setOnAction(e -> {
if (rbPurple.isSelected()) {
text.setFill(Color.PURPLE);
}
});
return border;
}
}
//Rectangle Bouncing Class
class BouncingRectangle extends RadioButtonDemo {
private Rectangle rectangle = new Rectangle( 0, 0, 10, 10);
private Timeline animation;
#Override
protected BorderPane getPane() {
BorderPane border = super.getPane();
Pane squarePane = new Pane();
rectangle.setFill(Color.BLUE);
squarePane.getChildren().add(rectangle);
border.setTop(squarePane);
return border;
}
}
//MP4 Class
class MediaDemo extends RadioButtonDemo {
private static final String MEDIA_URL =
"http://cs.armstrong.edu/liang/common/sample.mp4";
#Override
protected BorderPane getPane() {
BorderPane border = super.getPane();
Media media = new Media(MEDIA_URL);
MediaPlayer mediaPlayer = new MediaPlayer(media);
MediaView mediaView = new MediaView(mediaPlayer);
Button playButton = new Button(">");
playButton.setOnAction(e -> {
if (playButton.getText().equals(">")) {
mediaPlayer.play();
playButton.setText("||");
} else {
mediaPlayer.pause();
playButton.setText(">");
}
});
Button rewindButton = new Button("<<");
rewindButton.setOnAction(e -> mediaPlayer.seek(Duration.ZERO));
Slider slVolume = new Slider();
slVolume.setPrefWidth(150);
slVolume.setMaxWidth(Region.USE_PREF_SIZE);
slVolume.setMinWidth(30);
slVolume.setValue(50);
mediaPlayer.volumeProperty().bind(
slVolume.valueProperty().divide(100));
HBox hBox = new HBox(10);
hBox.setAlignment(Pos.CENTER);
hBox.getChildren().addAll(playButton, rewindButton,
new Label("Volume"), slVolume);
BorderPane paneForMedia = new BorderPane();
paneForMedia.setCenter(mediaView);
paneForMedia.setBottom(hBox);
grid.add(paneForMedia, 6, 10);
return border;
}
}
public class n00935124 extends RadioButtonDemo {
public static void main(String[] args) {
launch(args);
}
}
Thanks again
First, this is a really non-standard way to organize things. Not wrong in any sense(*), but just so non-standard that it took me a while to figure out what was going on.
The reason you are not seeing the last two additions of content is that your inheritance hierarchy is wrong. You want:
class MediaDemo extends BouncingRectangle
and
public class n00935124 extends MediaDemo
instead of both extending RadioButtonDemo (which I'm guessing is just a copy-and-paste error).
(*) I guess the issue is that you are using inheritance solely to add state here, which is something of an anti-pattern. Inheritance is best used to either add behavior, or to provide alternative implementations of behavior.
Related
I have a Label and a ProgressBar in a GridPane.
I've registered an onMouseClicked-event handler on the GridPane.
If I click on the Label the handler gets triggered.
If I click on the ProgressBar the handler doesn't get triggered.
Why? How can I fix it?
package test;
import javafx.application.Application;
import javafx.scene.Cursor;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.RowConstraints;
import javafx.stage.Stage;
public class ProgressBarTestApplication extends Application {
#Override
public void start(Stage primaryStage) {
GridPane gridPane = new GridPane();
ColumnConstraints columnConstraints0 = new ColumnConstraints();
columnConstraints0.setHgrow(Priority.SOMETIMES);
ColumnConstraints columnConstraints1 = new ColumnConstraints();
columnConstraints1.setHgrow(Priority.NEVER);
gridPane.getColumnConstraints().addAll(columnConstraints0, columnConstraints1);
RowConstraints rowConstraints0 = new RowConstraints();
rowConstraints0.setVgrow(Priority.SOMETIMES);
gridPane.getRowConstraints().add(rowConstraints0);
Label someLabel = new Label("Some Label:");
ProgressBar progressBar = new ProgressBar();
progressBar.setPrefWidth(250.0d);
someLabel.setLabelFor(progressBar);
gridPane.add(someLabel, 0, 0);
gridPane.add(progressBar, 1, 0);
gridPane.setCursor(Cursor.HAND);
gridPane.setHgap(5.0d);
gridPane.setOnMouseClicked(event -> System.out.println("Clicked!"));
Scene scene = new Scene(gridPane, 350, 150);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
It would seem that the MouseEvent is being consumed. I had a quick look through the ProgressBar class and it would seem that the ProgressIndicatorSkin's BehaviourBase may be causing the event to be consumed.
A quick and dirty solution would be to set the mouse clicked EventHandler for the ProgressBar to re-fire the event to the GridPane:
progressBar.setOnMouseClicked(e -> gridPane.fireEvent(e));
or to work with any Parent node:
progressBar.setOnMouseClicked(e -> progressBar.getParent().fireEvent(e));
or subclass ProgressBar to automatically apply this behavior:
public class NoConsumeProgressBar extends ProgressBar {
public NoConsumeProgressBar() {
setOnMouseClicked(e -> {
Parent parent = getParent();
if (parent != null) {
parent.fireEvent(e);
}
});
}
}
I have created a simple app to simulate dynamic node creation with JAVAFX.
This app has the ability to create a new window whenever user want it by clicking the "New" button.
User can add a new node which is TitledPane to the window by clicking "Add Task" button and then clicking "Add" button on the dialog window.
There are an unexpected behavior which I want to fix. This app is only add new node (TitledPane in this case) to the last created window.
And the all of the nodes on the previous window will vanish.
You can see the following video to better understand what I mean.
VIDEO
https://youtu.be/eaWmu3zuuhE
NETBEANS PROJECT
Just in case you want to play with it.
https://drive.google.com/file/d/0B4Sbb8Ym-lcZLUIyWHV5ZXRSZE0/view?usp=sharing
CODES:
TasksList.java
package taskslist;
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.stage.Stage;
public class TasksList extends Application {
DisplayWhich display = new DisplayWhich();
Stage primaryStage;
Parent startWindow;
#Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
initStart();
}
private void initStart(){
display.showDialogWindow();
}
public static void main(String[] args) {
launch(args);
}
}
TheList.java
package taskslist.view;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import taskslist.DisplayWhich;
public class TheList extends BorderPane {
public static VBox listWrapper;
public static ScrollPane listScroller;
public ObservableList<TitledPane> tasks;
private List<String> titles = new ArrayList<>();
public TheList(){
tasks = FXCollections.observableArrayList();
listWrapper = new VBox(5);
listScroller = new ScrollPane(listWrapper);
}
public void setTitles(String... title){
titles = Arrays.asList(title);
}
public List<String> getTitles(){
return titles;
}
public void loadSavedList(){
for(int i=0; i<getTitles().size();i++){
String ttlString = getTitles().get(i);
this.createTask(ttlString);
}
// Display Tasks
listWrapper.getChildren().addAll(this.tasks);
}
// Dialong for adding a new task and also editing a task
private void addTaskDialog(){
GridPane container = new GridPane();
Scene scene = new Scene(container, 150, 50);
Stage addNewTask = new Stage();
addNewTask.initModality(Modality.APPLICATION_MODAL);
addNewTask.setTitle("Add Task");
TextField title = new TextField();
Button confirm = new Button("Add");
// Create Task
confirm.setOnAction((ev) -> {
String ttlString = title.getText();
this.createTask(ttlString);
listWrapper.getChildren().clear();
listWrapper.getChildren().addAll(this.tasks);
addNewTask.close();
});
container.add(title, 0, 1);
container.add(confirm, 0, 5);
addNewTask.setScene(scene);
addNewTask.showAndWait();
}
// Assemble all this.tasks list components
public void render(){
setCenter(listScroller);
loadSavedList();
Button newProject = new Button("New");
Button addTask = new Button("Add Task");
BorderPane listBottom = new BorderPane();
HBox bottomLeft = new HBox();
bottomLeft.getChildren().add(newProject);
listBottom.setLeft(bottomLeft);
HBox bottomRight = new HBox();
bottomRight.getChildren().add(addTask);
listBottom.setRight(bottomRight);
newProject.setOnAction((evt) -> {
DisplayWhich display = new DisplayWhich();
display.showDialogWindow();
});
addTask.setOnAction((e) -> {
addTaskDialog();
});
setBottom(listBottom);
}
// Cteate task from strings
private void createTask(String... strings){
String taskTitle = strings.length > 0 ? strings[0] : "";
TitledPane task = new TitledPane();
task.setPrefWidth(647);
task.setExpanded(false);
task.setText(taskTitle);
this.tasks.add(task);
}
}
NewDialog.java
package taskslist.view;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import taskslist.DisplayWhich;
public class NewDialog {
DisplayWhich display = new DisplayWhich();
Stage stage = new Stage();
Parent startWindow = new AnchorPane();
#FXML
private Button cancelNew;
#FXML
private Button confirmCreation;
/**
* Initializes the controller class.
*/
#FXML
private void initialize() {
}
#FXML
private void cancelNewCreation(ActionEvent event) {
((Stage)cancelNew.getScene().getWindow()).close();
}
#FXML
private void confirmCreateNew(ActionEvent event) {
((Stage)confirmCreation.getScene().getWindow()).close();
TheList wrap = new TheList();
TheWindow window = new TheWindow();
window.makeWindow(wrap);
wrap.setTitles("one", "two", "three", "four");
wrap.render();
}
}
DisplayWhich.java
package taskslist;
import java.io.IOException;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import taskslist.view.TheList;
public class DisplayWhich {
Stage stage = new Stage();
Parent startWindow = new AnchorPane();
public DisplayWhich(){}
public Stage showDialogWindow(){
try {
stage.initModality(Modality.APPLICATION_MODAL);
stage.setTitle("Create New Project");
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/taskslist/view/newDialog.fxml"));
startWindow = loader.load();
Scene scene = new Scene(startWindow);
stage.setScene(scene);
stage.setOnCloseRequest((event) -> {
System.out.println("test");
});
stage.showAndWait();
} catch (IOException ex) {
ex.printStackTrace();
}
return stage;
}
}
TheWindow.java
package taskslist.view;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TheWindow {
public TheWindow(){}
public void makeWindow(BorderPane group) {
Stage mainWindow = new Stage();
Scene scene = new Scene(group, 650, 550);
mainWindow.setScene(scene);
mainWindow.setTitle("Task List");
mainWindow.centerOnScreen();
mainWindow.show();
}
}
Why that weird behavior happening and how to fix it so it only adds new node to the same window where the clicked "Add Task" button is located?
These fields should not be static:
public static VBox listWrapper;
public static ScrollPane listScroller;
Currently the code below produces a BorderPane with a GridPane in the center and a HBox on the bottom to hold two buttons. The left-most pane in the GridPane contains the text "Name Here". Right now I only want the buttons to move the text "Name Here" up and down but they will not move the text.
I think it has something to do with the particular GridPane node, but I'm not sure. Additionally, I don't know why the left-most GridPane takes up more space relative to the right-most GridPane within the center of the BorderPane.
Any advice will be greatly appreciated, thank you!
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.geometry.Pos;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.Priority;
import javafx.scene.text.Text;
public class differentWindows extends Application {
protected Text name = new Text("Name Here");
protected BorderPane getPane() {
// HBox to hold the up and down buttons
HBox paneForButtons = new HBox(20);
Button btUp = new Button("Up");
Button btDown = new Button("Down");
paneForButtons.getChildren().addAll(btUp, btDown);
paneForButtons.setAlignment(Pos.BOTTOM_LEFT);
// Grid pane to go in center of the border pane, for the name and video
GridPane paneForTextNVideo = new GridPane();
paneForTextNVideo.setAlignment(Pos.CENTER);
paneForTextNVideo.setGridLinesVisible(true);
paneForTextNVideo.add(name, 0, 0);
Text temp = new Text("temp");
paneForTextNVideo.add(temp, 1, 0);
paneForTextNVideo.setHalignment(temp, HPos.CENTER);
paneForTextNVideo.setValignment(temp, VPos.CENTER);
paneForTextNVideo.setHgrow(temp, Priority.ALWAYS);
paneForTextNVideo.setVgrow(temp, Priority.ALWAYS);
paneForTextNVideo.setHalignment(name, HPos.CENTER);
paneForTextNVideo.setValignment(name, VPos.CENTER);
paneForTextNVideo.setHgrow(name, Priority.ALWAYS);
paneForTextNVideo.setVgrow(name, Priority.ALWAYS);
// Border pane to hold all windows
BorderPane pane = new BorderPane();
pane.setBottom(paneForButtons);
pane.setCenter(paneForTextNVideo);
btUp.setOnAction(e -> name.setY(name.getY() - 10));
btDown.setOnAction(e -> name.setY(name.getY() + 10));
return pane;
} // end of the getPane method
#Override
public void start(Stage primaryStage) {
Scene scene = new Scene(getPane(), 450, 200);
primaryStage.setTitle("Assignment #7");
primaryStage.setScene(scene);
primaryStage.show();
} // end of start method
public static void main(String[] args) {
Application.launch(args);
}
} // end of class
Try using setLayoutY instead of setY:
btUp.setOnAction(e -> name.setLayoutY(name.getLayoutY() - 10));
btDown.setOnAction(e -> name.setLayoutY(name.getLayoutY() + 10));
As a sidenote, the Node parent class also has a relocate method for easily changing both the X and Y coordinates:
Here is an example from Pro JavaFx 8:
package projavafx.reversi.examples;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.InnerShadow;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Ellipse;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import projavafx.reversi.model.Owner;
import projavafx.reversi.model.ReversiModel;
/**
* #author Stephen Chin <steveonjava#gmail.com>
*/
public class BorderLayoutExample extends Application {
TilePane scoreTiles;
TilePane titleTiles;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
BorderPane borderPane = new BorderPane();
borderPane.setTop(createTitle());
borderPane.setCenter(createBackground());
borderPane.setBottom(createScoreBoxes());
Scene scene = new Scene(borderPane, 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
// scoreTiles.prefTileWidthProperty().bind(Bindings.selectDouble(scoreTiles.parentProperty(), "width").divide(2));
// titleTiles.prefTileWidthProperty().bind(Bindings.selectDouble(titleTiles.parentProperty(), "width").divide(2));
}
private Node createTitle() {
StackPane left = new StackPane();
left.setStyle("-fx-background-color: black");
Text text = new Text("JavaFX");
text.setFont(Font.font(null, FontWeight.BOLD, 18));
text.setFill(Color.WHITE);
StackPane.setAlignment(text, Pos.CENTER_RIGHT);
left.getChildren().add(text);
Text right = new Text("Reversi");
right.setFont(Font.font(null, FontWeight.BOLD, 18));
titleTiles = new TilePane();
titleTiles.setSnapToPixel(false);
TilePane.setAlignment(right, Pos.CENTER_LEFT);
titleTiles.getChildren().addAll(left, right);
titleTiles.setPrefTileHeight(40);
titleTiles.prefTileWidthProperty().bind(Bindings.selectDouble(titleTiles.parentProperty(), "width").divide(2));
return titleTiles;
}
private Node createBackground() {
Region answer = new Region();
RadialGradient rg = new RadialGradient(225, 0, 0, 0, 1, true, CycleMethod.NO_CYCLE,
new Stop(0.0, Color.WHITE),
new Stop(1.0, Color.GRAY)
);
answer.setBackground(new Background(new BackgroundFill(rg, null, null)));
// answer.setStyle("-fx-background-color: radial-gradient(radius 100%, white, gray)");
return answer;
}
private Node createScoreBoxes() {
scoreTiles = new TilePane(createScore(Owner.BLACK), createScore(Owner.WHITE));
scoreTiles.setSnapToPixel(false);
scoreTiles.setPrefColumns(2);
scoreTiles.prefTileWidthProperty().bind(Bindings.selectDouble(scoreTiles.parentProperty(), "width").divide(2));
return scoreTiles;
}
private Node createScore(Owner owner) {
Region background;
Ellipse piece = new Ellipse(32, 20);
piece.setFill(owner.getColor());
DropShadow pieceEffect = new DropShadow();
pieceEffect.setColor(Color.DODGERBLUE);
pieceEffect.setSpread(.2);
piece.setEffect(pieceEffect);
Text score = new Text();
score.setFont(Font.font(null, FontWeight.BOLD, 100));
score.setFill(owner.getColor());
Text remaining = new Text();
remaining.setFont(Font.font(null, FontWeight.BOLD, 12));
remaining.setFill(owner.getColor());
VBox remainingBox = new VBox(10, piece, remaining);
remainingBox.setAlignment(Pos.CENTER);
FlowPane flowPane = new FlowPane(20, 10, score, remainingBox);
flowPane.setAlignment(Pos.CENTER);
background = new Region();
background.setStyle("-fx-background-color: " + owner.opposite().getColorStyle());
ReversiModel model = ReversiModel.getInstance();
StackPane stack = new StackPane(background, flowPane);
InnerShadow innerShadow = new InnerShadow();
innerShadow.setColor(Color.DODGERBLUE);
innerShadow.setChoke(.5);
background.effectProperty().bind(Bindings.when(model.turn.isEqualTo(owner))
.then(innerShadow)
.otherwise((InnerShadow) null));
DropShadow dropShadow = new DropShadow();
dropShadow.setColor(Color.DODGERBLUE);
dropShadow.setSpread(.2);
piece.effectProperty().bind(Bindings.when(model.turn.isEqualTo(owner))
.then(dropShadow)
.otherwise((DropShadow) null));
score.textProperty().bind(model.getScore(owner).asString());
remaining.textProperty().bind(model.getTurnsRemaining(owner).asString().concat(" turns remaining"));
return stack;
}
}
A warning pops up in the console when running this app:
sept. 20, 2015 11:07:03 AM com.sun.javafx.binding.SelectBinding$SelectBindingHelper getObservableValue
WARNING: Exception while evaluating select-binding [width]
sept. 20, 2015 11:07:03 AM com.sun.javafx.binding.SelectBinding$SelectBindingHelper getObservableValue
WARNING: Exception while evaluating select-binding [width]
What went wrong here?
The problem is the following bit of code in the method createTitle():
titleTiles.prefTileWidthProperty().bind(
Bindings.selectDouble(
titleTiles.parentProperty(), "width").divide(2));
At this moment, the titleTiles have not yet been added to the borderPane, so the value of the parentProperty is null, hence the width property can not be found on it.
Same in createScoreBoxes().
Next time, though, it would be nice, if you cut down your sample code a bit, especially remove references to classes from your project (import projavafx.reversi.model.ReversiModel;), do that one can paste it into his IDE and run it right away.
I want to create a refresh button for my webView that will be on top of the view (even if it hides part of the view), when I place the button on the Grid Pane it pushes the webView down or to the side (depends where I place the button)
How can I place my "refresh" button on top of the webView and not move it aside?
import java.util.List;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class webviewbrowser extends Application {
#Override public void start(Stage primaryStage) throws Exception {
Pane root = new WebViewPane();
primaryStage.setScene(new Scene(root, 1024, 768));
primaryStage.setFullScreen(true);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
/**
* Create a resizable WebView pane
*/
public class WebViewPane extends Pane {
public WebViewPane() {
VBox.setVgrow(this, Priority.ALWAYS);
setMaxWidth(Double.MAX_VALUE);
setMaxHeight(Double.MAX_VALUE);
WebView view = new WebView();
view.setMinSize(500, 400);
view.setPrefSize(500, 400);
final WebEngine eng = view.getEngine();
eng.load("http://google.com");
//final TextField locationField = new TextField("http://www.google.com");
//locationField.setMaxHeight(Double.MAX_VALUE);
Button goButton = new Button("Refresh");
goButton.setDefaultButton(true);
EventHandler<ActionEvent> goAction = new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
eng.reload();
}
};
goButton.setOnAction(goAction);
GridPane grid = new GridPane();
grid.setVgap(0);
grid.setHgap(0);
GridPane.setConstraints(goButton,2,0,2,1, HPos.RIGHT, VPos.BOTTOM, Priority.ALWAYS, Priority.ALWAYS);
GridPane.setConstraints(view, 0, 0, 2, 1, HPos.CENTER, VPos.CENTER, Priority.SOMETIMES, Priority.SOMETIMES);
grid.getColumnConstraints().addAll(
new ColumnConstraints(100, 100, Double.MAX_VALUE, Priority.ALWAYS, HPos.CENTER, true),
new ColumnConstraints(40, 40, 40, Priority.NEVER, HPos.CENTER, true)
);
grid.getChildren().addAll(goButton, view);
getChildren().add(grid);
}
#Override protected void layoutChildren() {
List<Node> managed = getManagedChildren();
double width = getWidth();
double height = getHeight();
double top = getInsets().getTop();
double right = getInsets().getRight();
double left = getInsets().getLeft();
double bottom = getInsets().getBottom();
for (int i = 0; i < managed.size(); i++) {
Node child = managed.get(i);
layoutInArea(child, left, top,
width - left - right, height - top - bottom,
0, Insets.EMPTY, true, true, HPos.CENTER, VPos.CENTER);
}
}
}
}
If you want to stack one component on top of another, don't use a GridPane for layout, instead use a parent that allows layout components to be placed on top of one another. For example, a standard Pane, a StackPane, Group or Region. In these stacked style layouts, the components are rendered in order of the child component's position in the parent's child list.
In your sample code you are already extending Pane, so get rid of all of the grid code and just do:
getChildren().addAll(view, goButton);
instead of:
grid.getChildren().addAll(goButton, view);
Modify the layout properties of your goButton to position it within a parent which does not manage the layout position of it's children, e.g. you can call goButton.relocate(xPos, yPos).
You have some custom stuff in the layoutChildren method you override that may mess up the default Pane layout processing logic. Overriding layoutChildren is more of an advanced layout topic and I wouldn't advise it for beginners.
Here is an updated sample you could look at which uses some of the concepts mentioned in this answer.
import javafx.application.Application;
import javafx.event.*;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.scene.web.*;
import javafx.stage.Stage;
public class WebViewBrowser extends Application {
#Override public void start(Stage stage) throws Exception {
stage.setScene(new Scene(new WebViewPane("http://google.com")));
stage.setFullScreen(true);
stage.show();
}
public static void main(String[] args) { launch(args); }
}
class WebViewPane extends Pane {
final WebView view = new WebView();
final Button goButton = createGoButton(view.getEngine());
public WebViewPane(String initURL) {
view.getEngine().load(initURL);
getChildren().addAll(
view,
goButton
);
initLayout();
}
private Button createGoButton(final WebEngine eng) {
Button go = new Button("Refresh");
go.setDefaultButton(true);
go.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
eng.reload();
}
});
return go;
}
private void initLayout() {
setMinSize(500, 400);
setPrefSize(1024, 768);
view.prefWidthProperty().bind(widthProperty());
view.prefHeightProperty().bind(heightProperty());
goButton.setLayoutX(10);
goButton.layoutYProperty().bind(
heightProperty().subtract(20).subtract(goButton.heightProperty())
);
}
}