I have a GUI that takes the input of an image name, and once the refresh button is pressed, its displayed in a fixed position. I want to be able to input a character 'A-G' which will change the X position of the image, and a character '0-6' that will change the Y position of the image. The name of the images are just "A1", "A2"..."A5". So, if the user inputs "A1B3", it will display the image A1 in X-Position 'B' and Y-Position '3'. So B could be 200, and 3 could be 300, which makes the (X,Y) coordinates (200,300).
This is my code that gets the users input for the image.
private void getImage(){
Image img = new Image("comp1110/ass2/gui/assets/" + textField.getText() + ".png", 100, 100, false, false);
ImageView image = new ImageView();
image.setImage(img);
image.setX(100);
image.setY(100);
pane.getChildren().add(image);
}
I think you should do something along the lines of this yes there is some cosmetic issues that you will need to fix. But its only to give you an idea of what to do. It uses a gridpane so you don't have to worry about getting exact coordinates I choose a vbox so I didn't have to worry about layout you can keep the Pane that you have it shouldn't make a difference.
public class Main extends Application {
private GridPane gridPane;
private TextField imageTextField = new TextField();
private HashMap<String,String> hashMap = new HashMap<>();
#Override
public void start(Stage primaryStage) {
fillHashMapValues();
gridPane = new GridPane();
gridPane.setGridLinesVisible(true);
for (int i = 0; i < 7; i++) {
RowConstraints rowConstraints = new RowConstraints();
rowConstraints.setPercentHeight(14);
gridPane.getRowConstraints().add(rowConstraints);
ColumnConstraints columnConstraints = new ColumnConstraints();
columnConstraints.setPercentWidth(14);
gridPane.getColumnConstraints().add(columnConstraints);
gridPane.addColumn(i);
gridPane.addRow(i);
}
imageTextField.setPromptText("Enter Image Letters?");
TextField textField = new TextField();
textField.setPromptText("Enter Coordinates");
Button button = new Button("Go!");
button.setOnAction(event -> {
addToGridPane(textField.getText());
});
VBox vBox = new VBox();
vBox.setPrefSize(300, 300);
vBox.setAlignment(Pos.TOP_CENTER);
vBox.getChildren().addAll(imageTextField, textField, button, gridPane);
primaryStage.setScene(new Scene(vBox));
primaryStage.show();
button.requestFocus();//This is only so you can see the prompt text its irrelevant
}
private void fillHashMapValues(){
hashMap.put("A", "1");
hashMap.put("B", "2");
hashMap.put("C", "3");
hashMap.put("D", "4");
hashMap.put("E", "5");
hashMap.put("F", "6");
hashMap.put("G", "7");
}
private void addToGridPane(String string){
char[] chars = string.toCharArray();
if(chars.length==2){//Do more data validation here
if(hashMap.containsKey(String.valueOf(chars[0]))) {
int xValue = Integer.parseInt(hashMap.get(String.valueOf(chars[0])));
int yValue = Integer.parseInt(String.valueOf(chars[1]));
ImageView image = getImage();
gridPane.add(image, xValue, yValue);
}
}
}
private ImageView getImage(){
Image image = new Image("comp1110/ass2/gui/assets/" + imageTextField.getText() + ".png", 100, 100, false, false);
ImageView imageView = new ImageView();
imageView.setImage(image);
//imageView.setX(100);
//imageView.setY(100);
//pane.getChildren().add(image);
return imageView;
}
public static void main(String[] args) { launch(args); }
}
Related
This is my main class. I'm trying to get the string that is being selected from the combobox and "get the wall color" from that string. The problem is that when I run the application, after hitting the playbutton I get an error saying that in line 75 - if (stringWallColor.equals("Default - Black")), stringWallColor is null.
Does that I mean that it uses the public static String stringWallColor which is null as default? And how can I fix this?
public static String stringWallColor;
public static void main(String[] args) {
launch(args);
System.out.println("Done!");
}
public void start(Stage primaryStage) throws Exception {
Main.primaryStage = primaryStage;
MenuBar MENU = new MenuBar();
MenuGenerator.menuCreator(MENU);
Button playButton = new Button("Play Game");
ComboBox<String> wallColorCombo = new ComboBox<>();
wallColorCombo.setPromptText("Choose wall color");
wallColorCombo.getItems().addAll(
"Default - Black",
"Dark Green",
"Dark Red",
"Dark Gray",
"Saddle Brown",
"Midnight Blue",
"Dark Magenta",
"Crimson",
"Navy");
stringWallColor = wallColorCombo.getSelectionModel().getSelectedItem();
gameGrid = new GridPane();
GridPane root = new GridPane();
root.add(MENU,0,0);
root.add(gameGrid, 0, 1);
gameScene = new Scene(root,600,625);
GridPane startGrid = new GridPane();
startGrid.setHgap(20);
startGrid.setVgap(20);
playButton.setLineSpacing(10);
startGrid.add(playButton,8,12);
startGrid.add(wallColorCombo,7,12);
GridPane root0= new GridPane();
root0.add(startGrid,0,1);
Scene startScene = new Scene(root0, 400, 400);
primaryStage.setScene(startScene);
primaryStage.setTitle(GameEngine.GAME_NAME);
primaryStage.show();
System.out.println("Default save file not loaded yet");
playButton.setOnAction(e -> {
MenuGenerator.loadDefaultSaveFile(primaryStage);
System.out.println("Default save file loaded");
primaryStage.setScene(gameScene); });
}
public static Color getWallColor() {
Color wallColor = Color.BLACK;
if (stringWallColor.equals("Default - Black"))
wallColor = Color.BLACK;
if (stringWallColor.equals("Dark Green"))
wallColor = Color.DARKGREEN;
if (stringWallColor.equals("Dark Red"))
wallColor = Color.DARKRED;
if (stringWallColor.equals("Dark Gray"))
wallColor = Color.DARKGRAY;
if (stringWallColor.equals("Saddle Brown"))
wallColor = Color.SADDLEBROWN;
if (stringWallColor.equals("Midnight Blue"))
wallColor = Color.MIDNIGHTBLUE;
if (stringWallColor.equals("Dark Magenta"))
wallColor = Color.DARKMAGENTA;
if (stringWallColor.equals("Crimson"))
wallColor = Color.CRIMSON;
if (stringWallColor.equals("Navy"))
wallColor = Color.NAVY;
return wallColor;
}
}
Solved by setting stringWallColor = wallColorCombo.getSelectionModel().getSelectedItem(); as an action for the playbutton.
I'm trying to set every column minimum width to 100px. I prefer to use tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
Explanation
If you set TableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY) all columns will be equally resized until the TableViews maximum width is reached.
Explanation from
At the moment the width of each column is determined by the width of the TableViewdevided by the number of columns.
I tried to set every column the minimum width but that didn't work. I've also saw that people just created their own callback for the setColumnResizePolicy but I couldn't implement my idea of what should happen.
MCVE
public class MCVE extends Application {
private Scene mainScene;
private Stage mainStage;
private Label filename;
private VBox mainBox;
private TableView<String> tableView;
private Button open;
private Button save;
private Button neu;
private Button settings;
private Button table;
private Button row;
private Button column;
private Button date;
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
initButton();
initTable();
mainStage = new Stage();
filename = new Label("Nr. 100 - Test Data (Applikation: TEST)");
mainScene = new Scene(mainVBox(), 1200, 600);
tableView.prefWidthProperty().bind(mainBox.widthProperty());
tableView.prefHeightProperty().bind(mainBox.heightProperty());
mainStage.setScene(mainScene);
mainStage.show();
}
private GridPane mainGrid() {
GridPane gridPane = new GridPane();
gridPane.setVgap(10);
gridPane.setHgap(10);
gridPane.add(filename, 0, 0);
gridPane.add(buttonBox(), 0, 1);
gridPane.add(tableView, 0, 2);
return gridPane;
}
private VBox buttonBox() {
VBox buttonBox = new VBox();
HBox firstRowBox = new HBox();
HBox secRowBox = new HBox();
firstRowBox.getChildren().addAll(open, save, neu, settings);
firstRowBox.setSpacing(5);
secRowBox.getChildren().addAll(table, row, column, date);
secRowBox.setSpacing(5);
buttonBox.getChildren().addAll(firstRowBox, secRowBox);
buttonBox.setSpacing(5);
buttonBox.prefWidthProperty().bind(mainBox.widthProperty());
return buttonBox;
}
private VBox mainVBox() {
mainBox = new VBox();
mainBox.prefWidthProperty().bind(mainStage.widthProperty().multiply(0.8));
mainBox.setPadding(new Insets(10, 10, 10 ,10));
mainBox.getChildren().add(mainGrid());
return mainBox;
}
private void initButton() {
open = new Button("Open");
open.setPrefWidth(100);
save = new Button("Save");
save.setPrefWidth(100);
neu = new Button("New");
neu.setPrefWidth(100);
settings = new Button("Settings");
settings.setPrefWidth(100);
table = new Button("Table");
table.setPrefWidth(100);
row = new Button("Row");
row.setPrefWidth(100);
column = new Button("Column");
column.setPrefWidth(100);
date = new Button("Date");
date.setPrefWidth(100);
}
private TableView initTable() {
tableView = new TableView<>();
// Create column UserName (Data type of String).
TableColumn<String, String> userNameCol //
= new TableColumn<>("User Name");
// Create column Email (Data type of String).
TableColumn<String, String> emailCol//
= new TableColumn<>("Email");
// Create 2 sub column for FullName.
TableColumn<String, String> firstNameCol //
= new TableColumn<>("First Name");
TableColumn<String, String> lastNameCol //
= new TableColumn<>("Last Name");
// Active Column
TableColumn<String, Boolean> activeCol//
= new TableColumn<>("Active");
tableView.getColumns().addAll(userNameCol, emailCol, firstNameCol, lastNameCol, activeCol);
for (int i = 0; tableView.getColumns().size() < i; i++){
tableView.getColumns().get(i).setMinWidth(100);
}
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
return tableView;
}
}
In the end I expect that after I load the file, the width of the column should still be the TableView width devided by the number of columns expect the width would be < 100px. In this case every width should be 100px and a scrollpane appears (ignores the scrollbar here).
Thank you for your help!
Your constraint of min width is never set...
Just replace this:
for (int i = 0; tableView.getColumns().size() < i; i++){
to this:
for (int i = 0; i < tableView.getColumns().size(); i++) {
Or even better use forEach:
tableView.getColumns().forEach(column -> column.setMinWidth(100));
I'm trying to make TreeView with CheckBoxTreeItems. When I collapse/expand a CheckBoxTreeItems the image I set up does not display correctly. I googled but I couldn't find correct answer. On Stack Overflow, I found a similar problem, but I didn't get a valid answer.
E.g
JavaFX CheckBoxTreeItem graphic disappear when siblings collapse
JavaFX CheckBoxTreeItem: Graphic disappears if graph is extended
Any ideas?
public class ClientApplication extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(final Stage stage) {
ImageView folderIcon = new ImageView();
Image folderImage = new Image("image/folder.png");
folderIcon.setImage(folderImage);
folderIcon.setFitWidth(16);
folderIcon.setFitHeight(16);
CheckBoxTreeItem<String> rootItem = new CheckBoxTreeItem<String>("folder", folderIcon);
rootItem.setExpanded(true);
for (int i = 0; i < 4; i++) {
CheckBoxTreeItem<String> checkBoxTreeItem = new CheckBoxTreeItem<String>("Sample" + (i + 1), folderIcon);
rootItem.getChildren().add(checkBoxTreeItem);
}
final TreeView<String> tree = new TreeView<String>(rootItem);
tree.setCellFactory(CheckBoxTreeCell.<String>forTreeView());
tree.setRoot(rootItem);
tree.setShowRoot(true);
StackPane root = new StackPane();
root.getChildren().add(tree);
stage.setScene(new Scene(root, 300, 250));
stage.show();
}
}
enter image description here
I tried to use the ideas provided by #Jai,But when I click the expand/collapse icon, there is still a problem.Attachment is a screenshot.Thanks in advance.
enter image description here
ImageView is a JavaFX control. This means that each instance represents a unique control you see on your screen. You should never use the same instance for multiple locations in your GUI.
On the other hand, Image represents an image (i.e. an array of pixel data), so it is reusable.
This should work:
#Override
public void start(final Stage stage) {
final Image folderImage = new Image("image/folder.png");
CheckBoxTreeItem<String> rootItem = new CheckBoxTreeItem<String>("folder", createImageView(folderImage));
rootItem.setExpanded(true);
for (int i = 0; i < 4; i++) {
CheckBoxTreeItem<String> checkBoxTreeItem = new CheckBoxTreeItem<String>("Sample" + (i + 1), createImageView(folderImage));
rootItem.getChildren().add(checkBoxTreeItem);
}
final TreeView<String> tree = new TreeView<String>(rootItem);
tree.setCellFactory(CheckBoxTreeCell.<String>forTreeView());
tree.setRoot(rootItem);
tree.setShowRoot(true);
StackPane root = new StackPane();
root.getChildren().add(tree);
stage.setScene(new Scene(root, 300, 250));
stage.show();
}
private ImageView createImageView(Image folderImage) {
ImageView folderIcon = new ImageView();
folderIcon.setImage(folderImage);
folderIcon.setFitWidth(16);
folderIcon.setFitHeight(16);
return folderIcon;
}
I have a program in which it displays 3 random hieroglyphic images on the screen. I have added a "Refresh" button in order to refresh the hieroglyphic images. When I click the button, the images refresh and randomize properly. After the button has been clicked for the first time however, it disappears. I am almost certain it has something to do with my pane.getChildren().clear(); line, but I cant seem to figure it out. Any tips or advice?
If I have posted incorrectly or without using proper guidelines, I apologize. This is one of my first posts.
Here is my code:
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.control.Button;
import javafx.geometry.Pos;
import javafx.scene.layout.HBox;
public class Lab6a extends Application {
#Override
public void start(Stage myStage) {
//Create an HBox layout.
HBox hBox1 = new HBox();
//Set alignment.
hBox1.setAlignment(Pos.CENTER);
getRandomHieroglyphic(hBox1);
//Create a Refresh button.
Button refresh = new Button("Refresh");
refresh.setOnAction(e -> getRandomHieroglyphic(hBox1));
hBox1.getChildren().add(refresh);
//Set the title for the second window.
myStage.setTitle("Random Hieroglyphics with Refresh");
//Create a scene for the window.
Scene myScene = new Scene(hBox1, 400, 400);
//Place the scene in the second window.
myStage.setScene(myScene);
//Show the stage.
myStage.show();
}
public void getRandomHieroglyphic(HBox pane) {
pane.getChildren().clear();
//Create random generators to get a random image
int randomInt1 = (int) (Math.random() * 9) + 1;
int randomInt2 = (int) (Math.random() * 9) + 1;
int randomInt3 = (int) (Math.random() * 9) + 1;
//Create paths for the images to be called
String path1 = "Image/Hieroglyphics/h" + randomInt1 + ".png";
String path2 = "Image/Hieroglyphics/h" + randomInt2 + ".png";
String path3 = "Image/Hieroglyphics/h" + randomInt3 + ".png";
//Add the images into the pane
pane.getChildren().add(new ImageView (path1));
pane.getChildren().add(new ImageView (path2));
pane.getChildren().add(new ImageView (path3));
}
public static void main(String[] args) {
launch(args);
}
}
clear() removes all children from the HBox including the Button.
You've got 3 ImageViews and want to keep the number of ImageViews constant. This means you should not replace them, but replace the images they contain instead. Furthermore you should avoid reloading the images and load all 9 images at the start:
public class Lab6a extends Application {
private Image[] images;
private final Random random = new Random();
#Override
public void start(Stage myStage) {
// load all hieroglyphs
images = new Image[9];
for (int i = 0; i < images.length; i++) {
images[i] = new Image("Image/Hieroglyphics/h" + (i+1) + ".png");
}
// store all imageviews in array
final ImageView[] imageViews = Stream.generate(ImageView::new).limit(3).toArray(ImageView[]::new);
// set initial images
getRandomHieroglyphic(imageViews);
...
hBox1.getChildren().add(refresh);
for (ImageView iv : imageViews) {
hBox1.getChildren().add(iv);
}
...
refresh.setOnAction(e -> getRandomHieroglyphic(imageViews));
...
}
public void getRandomHieroglyphic(ImageView[] imageViews) {
for (ImageView iv : imageViews) {
iv.setImage(images[random.nextInt(images.length)]);
}
}
You're right. You Hbox has 4 cildren initially, 3 images and the button. you should add the button too in the getRandomHieroglyphic() method.
But the better way was separate the button from the images. Best is this done by Adding a BorderPane to the Scene, and put the HBox with the images only in the center and the button in the bottom area.
#Override
public void start(Stage myStage) {
HBox hBox1 = new HBox();
hBox1.setAlignment(Pos.CENTER);
getRandomHieroglyphic(hBox1);
Button refresh = new Button("Refresh");
refresh.setOnAction(e -> getRandomHieroglyphic(hBox1));
BorderPane borderPane = new BorderPane();
borderPane.getBottom().add(refresh);
myStage.setTitle("Random Hieroglyphics with Refresh");
Scene myScene = new Scene(borderPane, 400, 400);
Whenever I click refresh in my program here, it will generate 5 random numbers from between 1 to 13 and display it in the form of cards on screen. I'm using JavaFx for that. I cannot figure out the second thing, which is when I click the Sort button then the program should take the current set of random numbers and show the cards from lowest to highest.
public class Cards extends Application {
public static void main(String[] args) {
Application.launch(args);
}
public static int mycard() {
Random rand = new Random();
int n = rand.nextInt(13) + 1;
return n;
}
public void start(Stage primaryStage) {
primaryStage.setTitle("Cards Layout");
GridPane pane = new GridPane();
pane.setAlignment(Pos.CENTER);
pane.setHgap(10);
pane.setVgap(5);
// creates button
Button refresh = new Button("Refresh");
HBox button = new HBox(10);
button.setAlignment(Pos.BOTTOM_LEFT);
button.getChildren().add(refresh);
pane.getChildren().add(refresh);
//Create sort button
Button sort = new Button("Sort");
HBox button1 = new HBox(10);
button1.setAlignment(Pos.BOTTOM_RIGHT);
button1.getChildren().add(sort);
pane.getChildren().add(sort);
// creates random card images and adds them to pane
Image img = new Image("image/card/"+mycard()+".png");
ImageView imgView = new ImageView(img);
pane.add(imgView, 1, 0);
Image img2 = new Image("image/card/"+mycard() +".png");
ImageView imgView2 = new ImageView(img2);
pane.add(imgView2, 2, 0);
Image img3 = new Image("image/card/" +mycard()+ ".png");
ImageView imgView3 = new ImageView(img3);
pane.add(imgView3, 3, 0);
Image img4 = new Image("image/card/" +mycard()+".png");
ImageView imgView4 = new ImageView(img4);
pane.add(imgView4, 4, 0);
Image img5 = new Image("image/card/" +mycard()+".png");
ImageView imgView5 = new ImageView(img5);
pane.add(imgView5, 5, 0);
Scene scene = new Scene(pane, 600, 200);
primaryStage.setScene(scene);
primaryStage.show();
refresh.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
imgView.setImage(new Image("image/card/" +mycard()+".png"));
imgView2.setImage(new Image("image/card/" +mycard()+".png"));
imgView3.setImage(new Image("image/card/" +mycard()+".png"));
imgView4.setImage(new Image("image/card/" +mycard()+".png"));
imgView5.setImage(new Image("image/card/" +mycard()+".png"));
}
});
sort.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
imgView.setImage(new Image("image/card/" + "1.png"));
imgView2.setImage(new Image("image/card/" + "2.png"));
imgView3.setImage(new Image("image/card/" + "3.png"));
imgView4.setImage(new Image("image/card/" + "4.png"));
imgView5.setImage(new Image("image/card/" + "5.png"));
//Cannot figure out what to do here ^
}
});
}
}
When you call myCard() you need to add the randomly generated number to a List. When you click on refresh you need to clear that list (myList.clear()). When you click on sort you need to first sort that list and then access the items in the list by index from 0 to myList.size().
If you add your images to a List, too, you can use the same index to match image with number / imageResource.
Since you have a fixed number of cards you could also use an Array (but if you plan on reusing code for implementations with more cards I'd use a List)