So my teacher has just started teaching us how to use JavaFx and up until now, I had thought I had a pretty good grasp of the material. But, I am stuck and I don't quite know how to fix the issue or even what's causing the issue. I am trying to create a green rectangle that is three nodes high on a grid that is 64x64. The grid shows up just fine but for the life of me, I cannot understand why the rectangle is not showing up as well. Can someone please help me figure out why the rectangle won't show up? I am sure it's a small stupid issue but again I can't see it. Here is my code:
public class test2 extends Application {
private Cell[][] cell = new Cell[64][64];
public void start(Stage primaryStage) {
GridPane pane = new GridPane();
pane.setStyle("-fx-background-color: black");
for (int col = 1; col < 64; col++)
for (int row = 1; row < 64; row++)
pane.add(cell[col][row] = new Cell(), row, col);
Rectangle rectangle = new Rectangle(1,3);
rectangle.setFill(Color.GREEN);
VBox box2 = new VBox(rectangle);
box2.setAlignment(Pos.CENTER);
BorderPane bp = new BorderPane();
bp.setCenter(pane);
Scene scene = new Scene(bp, 1000, 700);
primaryStage.setScene(scene);
primaryStage.show();
}
public class Cell extends Pane{
public Cell(){
setStyle("-fx-border-color: white");
setPrefSize(1000, 1000);
return;
}
}
public static void main(String[] args) {
launch(args);
}
Related
I'm trying to achieve this effect here but on a static background (without the scrolling). I'm getting this weird clip on my results though (without the frost effect). I think I know where the problem is in my code but I'm not sure how to solve it.
public class App extends Application {
private static final double BLUR_AMOUNT = 80;
private static final Effect frostEffect = new BoxBlur(BLUR_AMOUNT, BLUR_AMOUNT, 3);
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
ImageView background = new ImageView(bgImage);
StackPane centerBlurredPane = (StackPane) frozenCenterUI();
BorderPane centerContent = new BorderPane();
centerContent.setCenter(new Text("Center"));
centerContent.setTop(new Text("Top"));
centerContent.setLeft(new Text("Left"));
centerContent.setRight(new Text("Right"));
centerBlurredPane.getChildren.add(centerContent);
Scene scene = new Scene(new StackPane(background,centerBlurredPane),414, 849);
primaryStage.setScene(scene);
primaryStage.show();
}
private Node frozenCenterUI() {
Image frostImage = background.snapshot(new SnapshotParameters(), null);
ImageView frost = new ImageView(frostImage);
Rectangle filler = new Rectangle(24, 762, 366, 696);
filler.setArcHeight(50);
filler.setArcWidth(50);
filler.setFill(Color.AZURE);
Pane frostPane = new Pane(frost);
frostPane.setEffect(frostEffect);
StackPane frostView = new StackPane(filler, frostPane);
Rectangle clipShape = new Rectangle(24, 762, 366, 696);
frostView.setClip(clipShape);
return frostView;
}
}
This is what i'm getting, however. I want to apply frost on the white area here.
What should my clip shape be?
Here's my background image, backgroundImage
Edit: I found that if I change my clipShape to have the same dimensions as the scene, then I get the desired effect. However, the BorderPane I added to the frozen pane is not constrained to it, but actually stretches and fills the entire window.
I am having problems producing the correct number of columns in a TilePane row.
I'm trying just to have ten columns per row. I know I'm missing the obvious. So, I need another pair of eyes.
The setPrefColumns method does not appear to work the way I have it coded.
#SuppressWarnings("unused")
public class Main extends Application {
TilePane tp = new TilePane();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
try {
primaryStage.setResizable(false);
tp.setPrefColumns(10);
setTP();
Scene scene = new Scene(tp,800,600);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public void setTP() {
tp.setVisible(true);
int[] numbers = {1,2,3,4,5,6,7,8,9,10};
for(int row=0; row<11; row++) {
for (int i: numbers ) {
Text t = new Text(String.valueOf(i));
HBox hbox = new HBox();
hbox.getChildren().add(t);
hbox.setStyle("-fx-border-color: red;");
tp.getChildren().add(hbox);
}
}
}
}
Your example TilePane behaves as specified:
Note that prefColumns/prefRows is used only for calculating the preferred size and may not reflect the actual number of rows or columns, which may change as the tilepane is resized and the tiles are wrapped at its actual boundaries.
As root of the scene it is sized to fill the complete width (800 in your context):
Scene scene = new Scene(tp,800,600);
To make it wrap on its prefColumns, you need to add it to a layout that respects its content's prefWidth, f.i. a HBox:
Scene scene = new Scene(new HBox(tp),800,600);
I'm trying to make a program that will display a random set of 4 cards, then when I click the button again it will clear the old set and display a new random set.
Right now my program will display 4 random images of cards when I click the button; however, when I try to click it again nothing happens. I'm assuming it has something to do with the EventHandler no longer being registered to the button after I clear the root children. However, I don't know how to go about fixing this. Any help is greatly appreciated! I haven't been able to find an answer to this yet, and have only been learning JavaFX for about a week. Thank you.
The code I have so far:
public class CardShuffle extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
StackPane root = new StackPane();
Scanner input = new Scanner(System.in);
File cardsFolder = new File("C:\\Users\\timsp\\Pictures\\JPEG");
ArrayList<File> cardsFilePaths = new ArrayList<File> (Arrays.asList(cardsFolder.listFiles()));
Button deal = new Button("DEAL");
Pane hb = new HBox(10);
hb.setPadding(new Insets(5, 5, 5, 5));
root.getChildren().add(deal);
deal.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
root.getChildren().clear();
ArrayList<ImageView> cards = getRandomCards(cardsFilePaths);
for (int i = 0; i < 4; i++) {
cards.get(i).setFitWidth(150);
cards.get(i).setFitHeight(100);
hb.getChildren().add(cards.get(i));
}
root.getChildren().addAll(deal, hb);
}
});
Scene scene = new Scene(root, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
public ArrayList<ImageView> getRandomCards(ArrayList<File> cardsFilePaths) {
ArrayList<ImageView> cards = new ArrayList<ImageView>();
try {
for (int i = 0; i < 4; i++) {
Image card = new Image((new FileInputStream(cardsFilePaths.get((int) (Math.random() * 52)).getPath())));
ImageView temp = new ImageView();
temp.setImage(card);
cards.add(temp);
}
} catch (FileNotFoundException e) {
e.getMessage();
}
return cards;
}
}
Many problems here :
the first one, and the most important (because it hides your further error) is the root layout : you use a StackPane, the first thing you should do is to replace it by a VBox for example and rerun your program, it will be easier to see what really happens. (you will not have 4 cards, but 8, 12, 16 and so on).
the first one generates the second one. By doing this root.getChildren().addAll(deal, hb); you put the HBox layout above the button, and the click is first consumed by the HBox. Here is an example to see it more easily :
// Add the HBox as soon as the initialization
root.getChildren().add(deal);
hb.setOnMouseClicked(e -> System.out.println("HBox clicked"));
deal.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
root.getChildren().clear();
ArrayList<ImageView> cards = getRandomCards(cardsFilePaths);
for(int i = 0; i < 4; i++) {
cards.get(i).setFitWidth(150);
cards.get(i).setFitHeight(100);
hb.getChildren().add(cards.get(i));
}
hb.setStyle("-fx-background-color:CORNFLOWERBLUE;-fx-opacity:0.8;");
root.getChildren().addAll(deal, hb);
}
});
And the last one, you don't really want to remove all root's children, what you want is to replace your cards by another 4 ones. Thus it is not necessary to remove the button, only the HBox can be manipulated as shown by the following example :
// Add the HBox as soon as the initialization
root.getChildren().addAll(hb, deal);
deal.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
// root.getChildren().clear();
// Replace the previous line by the following :
hb.getChildren().clear();
ArrayList<ImageView> cards = getRandomCards(cardsFilePaths);
for(int i = 0; i < 4; i++) {
cards.get(i).setFitWidth(150);
cards.get(i).setFitHeight(100);
hb.getChildren().add(cards.get(i));
}
// The following is useless now.
// root.getChildren().addAll(hb, deal);
}
});
Unpleasantly surprised by TextArea CSS font sizes having wacky effects on the sizes of the scroll bars, I'm trying to get control of the sizes myself. Please refer to the following SSCCE. I can easily control the vertical scroll bar, but the horizontal bar is simply ignoring the sizes I'm setting. Am I expecting something unreasonable here, or is this (yet another) bug in JavaFX? Thanks!
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
TextArea textArea = new TextArea();
int lineCount = 100;
int wordCount = 70;
StringBuilder sb = new StringBuilder();
for (int lineNbr = 0; lineNbr < lineCount; lineNbr++) {
for (int wordNbr = 0; wordNbr < wordCount; wordNbr++) {
sb.append("Sample");
}
sb.append(System.getProperty("line.separator"));
}
textArea.setText(sb.toString());
StackPane root = new StackPane();
root.getChildren().add(textArea);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
double prefSize = 50;
ScrollBar vertScrollBar = (ScrollBar)textArea.lookup(".scroll-bar:vertical");
ScrollBar horizScrollBar = (ScrollBar)textArea.lookup(".scroll-bar:horizontal");
vertScrollBar.setPrefWidth(prefSize); // This works great!
horizScrollBar.setPrefHeight(prefSize); // This doesn't do anything!
horizScrollBar.setMinHeight(prefSize); // Nor does this
horizScrollBar.setPrefWidth(prefSize); // Nor this
horizScrollBar.setMinWidth(prefSize); // Nor this
}
}
ScrollBar vertScrollBar = (ScrollBar) textArea.lookup(".scroll-bar:vertical");
ScrollBar horizScrollBar = (ScrollBar) textArea.lookup(".scroll-bar:horizontal");
System.out.println(vertScrollBar + " " + horizScrollBar);
ScrollBar#35ef2d94[styleClass=scroll-bar]
ScrollBar#35ef2d94[styleClass=scroll-bar]
Same object (vertical ScrollBar).
ScrollPane sPane = (ScrollPane)textArea.getChildrenUnmodifiable().get(0);
ScrollBar horizScrollBar = (ScrollBar)sPane.getChildrenUnmodifiable().get(2);
horizScrollBar.setPrefHeight(prefSize); // This does something!
Update: Better way to receive the two ScrollBars.
ScrollBar[] bars = new ScrollBar[2];
textArea.lookupAll(".scroll-bar").toArray(bars);
bars[0].setPrefWidth(prefSize);
bars[1].setPrefHeight(prefSize);
Edit: Explanation for similar problem with lookupAll(...) and pseudo classes here and here.
Lookups are generally pretty fragile (and I don't think they're really intended to be robust); as noted in the links from the other answer they don't appear to support pseudoclasses.
You can of course just use CSS for this:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
TextArea textArea = new TextArea();
int lineCount = 100;
int wordCount = 70;
StringBuilder sb = new StringBuilder();
for (int lineNbr = 0; lineNbr < lineCount; lineNbr++) {
for (int wordNbr = 0; wordNbr < wordCount; wordNbr++) {
sb.append("Sample");
}
sb.append(System.getProperty("line.separator"));
}
textArea.setText(sb.toString());
StackPane root = new StackPane();
root.getChildren().add(textArea);
Scene scene = new Scene(root, 300, 250) ;
scene.getStylesheets().add("style.css");
primaryStage.setScene(scene);
primaryStage.show();
}
}
with the following in style.css:
.scroll-pane .scroll-bar:horizontal {
-fx-pref-height: 50 ;
}
.scroll-pane .scroll-bar:vertical {
-fx-pref-width: 50 ;
}
This approach, of course, is far more convenient if you have multiple scroll panes in your application and want them all to have the same style of scroll bars.
I have three problems:
I want to create resizable shapes with box bounding...
I also want to know how to get child seleted in a Pane.
I'm creating multiple shapes on a pane. I want to change some property of that shape say Fill.. How do i do it??
Thanx
Next example will answer your questions:
for (1) it uses binding, connecting pane size with rectangle size
for (2) it adds setOnMouseClick for each rectangle which stores clicked one in the lastOne field.
for (3) see code of setOnMouseClick() handler
public class RectangleGrid extends Application {
private Rectangle lastOne;
public void start(Stage stage) throws Exception {
Pane root = new Pane();
int grid_x = 7; //number of rows
int grid_y = 7; //number of columns
// this binding will find out which parameter is smaller: height or width
NumberBinding rectsAreaSize = Bindings.min(root.heightProperty(), root.widthProperty());
for (int x = 0; x < grid_x; x++) {
for (int y = 0; y < grid_y; y++) {
Rectangle rectangle = new Rectangle();
rectangle.setStroke(Color.WHITE);
rectangle.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
if (lastOne != null) {
lastOne.setFill(Color.BLACK);
}
// remembering clicks
lastOne = (Rectangle) t.getSource();
// updating fill
lastOne.setFill(Color.RED);
}
});
// here we position rects (this depends on pane size as well)
rectangle.xProperty().bind(rectsAreaSize.multiply(x).divide(grid_x));
rectangle.yProperty().bind(rectsAreaSize.multiply(y).divide(grid_y));
// here we bind rectangle size to pane size
rectangle.heightProperty().bind(rectsAreaSize.divide(grid_x));
rectangle.widthProperty().bind(rectangle.heightProperty());
root.getChildren().add(rectangle);
}
}
stage.setScene(new Scene(root, 500, 500));
stage.show();
}
public static void main(String[] args) { launch(); }
}