JavaFX Graphical Glitch - java

I'm experiencing a weird graphical glitch on my application. The situation is that I am creating some GridPanes and adding them to a parent GridPane which is inside a ScrollPane. However, upon scrolling, some weird glitches begin occurring. Here is a picture:
(Sorry for having to use links, I don't have enough reputation to post images).
http://s11.postimg.org/x9eg8bz4z/Glitch.png
Here is a picture of what it should look like:
http://s11.postimg.org/cqjk39l7n/Normal.png
Here is my code:
private static class Controller implements Initializable {
#FXML private GridPane projectsPane;
#Override
public void initialize(URL location, ResourceBundle resources) {
//I first create some objects to be used when
//creating the GridPanes in the following loop,
//but I have removed the code for simplicity
for(AvailableProject availableProject : availableProjects) {
GridPane projectPane = new GridPane();
projectPane.setBackground(new Background(new BackgroundFill(Color.DARKGREY, CornerRadii.EMPTY, Insets.EMPTY)));
ColumnConstraints column1 = new ColumnConstraints();
column1.setPercentWidth(50);
ColumnConstraints column2 = new ColumnConstraints();
column2.setPercentWidth(50);
projectPane.getColumnConstraints().addAll(column1, column2);
projectPane.setPadding(new Insets(5));
Label projectName = new Label(availableProject.projectName);
GridPane.setValignment(projectName, VPos.CENTER);
projectPane.add(projectName, 0, 0);
TextFlow description = new TextFlow(new Text(availableProject.description));
description.setMaxSize(200, 100);
GridPane.setValignment(description, VPos.CENTER);
projectPane.add(description, 0, 1);
Label category = new Label(availableProject.category);
GridPane.setValignment(category, VPos.CENTER);
GridPane.setHalignment(category, HPos.RIGHT);
projectPane.add(category, 1, 0, 1, 2);
projectsPane.add(projectPane, 0, yRow);
yRow++;
Pane pane = new Pane();
pane.setMinHeight(15);
projectsPane.addRow(yRow, pane);
yRow++;
}
}
}
I have tried simplifying the code to make it cleaner, but I will post the rest if needed.
Thank you!

I seem to have found the solution. By the looks of it, this really is a bug. I will report it to Oracle later. It seems the problem was that I had padding in my ScrollPane. By my testing, if padding was greater than 5, the glitches would occur. A workaround is to assign the padding to the parent GridPane rather than the ScrollPane.

Related

Javafx GridPane, how to center Node? (Text/Label)

I am trying to learn Javafx for a class I am taking. I am having a lot of difficulty transitioning from HTML + ERB templates to the Javafx framework (I am a Rails dev).
For some reason I am unable to center a Label node in a gridpane. Here is my start method:
#Override
public void start(Stage stage) throws Exception {
GridPane root = new GridPane();
FlowPane leftbanner = new FlowPane();
leftbanner.setPrefWidth(200);
String bgStyle = "-fx-background-color: lightblue;"
+ "-fx-background-radius: 0%;"
+ "-fx-background-inset: 5px;";
leftbanner.setStyle(bgStyle);
root.add(leftbanner, 0, 0, 1, 1);
root.add(createGridPane(), 1, 0, 1, 1);
Scene scene = new Scene(root, 700, 500);
stage.setTitle("Recommendify");
stage.setScene(scene);
stage.show();
}
I am using the createGridPane method to build my app. Here are the contents of that method which includes my attempts to center the label:
public GridPane createGridPane() {
GridPane grid = new GridPane();
grid.setPadding(new Insets(10));
grid.setHgap(10);
grid.setVgap(10);
Text txt = new Text("Recommendify");
txt.setFont(Font.font("Dialog", FontWeight.BOLD, 12));
GridPane.setHalignment(txt, HPos.CENTER);
grid.add(txt, 0, 0, 1, 1);
grid.add(new Separator(), 0, 1, 3, 1);
return grid;
}
I have also tried these solutions posted here: JavaFX alignment of Label in GridPane
Do I need to throw this Label node into a container in order to center it in the GridPane? Like an HBox or VBox?
There is actually nothing wrong with your code. The "Recommendify" text is centered in its cell. However, the cell is no wider than the text itself.
You can see this by turning on the grid lines within your createGridPane() method:
grid.setGridLinesVisible(true);
To test the alignment, you can add ColumnConstraints to the GridPane:
grid.getColumnConstraints().add(new ColumnConstraints(150));
The above statement sets the preferred width of the first column to 150. Here is the new result:
As you can see, the Text node is centered properly.
EDIT: Keep in mind that if you want your Text to be centered over the Separator you've added to the second row, you need to have
it span 3 columns as well.

Structure of a questionnare panel in javafx

I am trying to create a questionnaire panel in javafx. I have a label with the question and three buttons for the answer. I have manage to put all of them together, however I am not sure how can I structure the whole thing. Furthermore in the sam BorderPane I want to add more questions. How can I do so?
BorderPane questionaires = new BorderPane();
questionaires.setTop(questionnairesPane);
questionaires.setCenter(questionsPane);
//QUESTIONS Panel
questionnairesPane = new GridPane();
questionnairesPane.setHgap(0);
questionnairesPane.setVgap(0);
questionnairesPane.setPadding(new Insets(0, 0, 0, 200));
results = new MyTitles("Questionnaires");
questionnairesPane.setStyle("-fx-font: 150 hamster; -fx-text-fill: white;");
questionnairesPane.add(results,1,1);
questionsPane = new GridPane();
questionsPane.setHgap(15);
questionsPane.setVgap(30);
questionsPane.setPadding(new Insets(0, 50, 0, 80));
SsubjectLabel = new Label("What was your affective response during the game?");
SsubjectLabel.setPrefWidth(1000.0);
SsubjectLabel.setPrefHeight(70.0);
SsubjectLabel.setStyle("-fx-font: 30 cornerstone; -fx-text-fill: black;");
boredom = new Button("Boredom");
boredom.setStyle("-fx-font: 30 cornerstone; -fx-text-fill: black;");
boredom.addEventHandler(ActionEvent.ACTION, (e)-> {
});
engagement = new Button("Boredom");
engagement.setStyle("-fx-font: 30 cornerstone; -fx-text-fill: black;");
engagement.addEventHandler(ActionEvent.ACTION, (e)-> {
});
frustration = new Button("Boredom");
frustration.setStyle("-fx-font: 30 cornerstone; -fx-text-fill: black;");
frustration.addEventHandler(ActionEvent.ACTION, (e)-> {
});
questions.add(SsubjectLabel,1,1);
questions.add(boredom,1,2);
questions.add(engagement,1,3);
questions.add(frustration,1,4);
questions.add(next,2,4);
The functinoality is corrent but how can I structure corrent all buttons, this is what I am struggle to do. My panel right now looks like the following pic:
In the class where you made the layout you can have one method that accept as parameter a Question class.
Question class should have the actuall question,possible answers and the correct one.
When you want to change or go to previous or next you just call the method above(changeQuestion(Question newOne);)
This method will change the values of javaFX elements you use.So you will not create new FX elements everytime.
If you want to hold a lot of questions use an array and in the Class Question have a value answered if has been answered or not.
All the above as a simple idea.
Edit
Read here about build-in Layouts and Alignment in javaFX
What you can do is:
HBox box = new HBox();
Button confirm = new Button();
box.getChildren().add(confirm);
borderPane.setBottom(box);
the confirm will go on left of the window.That is called alignment.
You can use method setAlignment(); to change the positioning of Hbox and Button.
There are better approaches though.Go on a full tutorial about fxml and javaFX here.

How can I change my JavaFx's buttons to look exactly like this?

[2]: Below is a piece of what I've done so far. Can't seem to get it to look like the pic that I've attached.
gp.getColumnConstraints().addAll(rc, rc1, rc2);
gp.setAlignment(Pos.TOP_CENTER);
gp.add(prev, 0, 0);
gp.add(search, 1, 0);
gp.add(next, 2, 0);
Button add = new Button("Add + ");
add.setPrefSize(75, 10);
add.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
if (!fNameFld.getText().toString().equals("")) {
Contact c = new Contact(fNameFld.getText().toString(), numF.getText().toString(),
emailf.getText().toString());
contact.add(c);
i = contact.indexOf(c);
System.out.println(i);
}
}
});
Button edit = new Button("Edit * ");
edit.setPrefSize(75, 10);
edit.setOnAction(new EventHandler<ActionEvent>() {
I wouldn't use a GridPane for this. In fact, I’m pretty sure a GridPane alone can’t do what you want.
You can make a center-aligned HBox for each row, and put those rows into a single VBox:
Collection<HBox> buttonRows = Arrays.asList(
new HBox(6, previous, search, next),
new HBox(6, add, edit, remove),
new HBox(6, clear, quit));
buttonRows.forEach(hbox -> hbox.setAlignment(Pos.CENTER));
VBox buttonPane = new VBox(12);
buttonPane.getChildren().addAll(buttonRows);
You should get rid of all calls to setPrefSize. Your buttons are perfectly capable of defining their own sizes. If you want to give them larger internal margins, set their -fx-label-padding CSS properties.

ImageView always scaling beyond scene size, can't seem to force it to fit

I am new to JavaFX (been working with swing for a long time) and am trying to work with BorderPane. One would assume BorderPane is similar to BorderLayout but the big difference is the center of BorderPane will expand to fit its contents while BorderLayout will shrink to fit the window.
I am using JFXPanel in a JFrame and have a 3 part interface: A panel on the left (some text), some buttons on the bottom (flow control), and in the center want to have a dynamic panel/pane, that for the most part will be just an imageview. I set it all up and it works fine, but I'm working with camera images here which are way bigger than my monitor. I've tried scaling the images down by binding the imageview width to different things (such as anchor pane, scene size (works, but not properly), etc. The issue I am having is that since borderpane's center panel expands to fit its content, it will expand and never have a proper value I can bind to. I need the image to be fully visible in the window at any size.
Here's the code I've been working with.
protected void setupFXWindow(JFXPanel mainPanel) {
butNext = new Button("Next Step");
butBack = new Button("PreviousStep Step");
butQuit = new Button("Cancel Signature Generation");
butNext.setTooltip(new Tooltip("Next step..."));
butBack.setTooltip(new Tooltip("Previous Step..."));
butQuit.setTooltip(new Tooltip("Quit generating a signature"));
Group root = new Group();
Scene scene = new Scene(root, javafx.scene.paint.Color.ALICEBLUE);
javafx.scene.image.Image fximage = new javafx.scene.image.Image(new File(image.getSourceFilePath()).toURI().toString());
ImageView iv1 = new ImageView();
iv1.setImage(fximage);
iv1.setPreserveRatio(true);
VBox directionsPanel = new VBox();
HBox authorflowPanel = new HBox(); //bottom buttons for next, back, etc.
mainPanel.setScene(scene);
//INSTRUCTIONS
directionsStepLabel = new Text();
directionsLabel = new Text();
setDirectionsText("Directions will be placed here.");
exampleLabel = new Text("Example");
exampleIconLabel = new Text("An example image will be shown here.");
directionsPanel.setPadding(new javafx.geometry.Insets(5, 5, 5, 5));
directionsPanel.getChildren().addAll(directionsStepLabel, directionsLabel, exampleLabel);
authorflowPanel.getChildren().addAll(butBack, butQuit, butNext);
BorderPane bp = new BorderPane();
bp.prefHeightProperty().bind(scene.heightProperty());
bp.prefWidthProperty().bind(scene.widthProperty());
bp.setLeft(directionsPanel);
bp.setBottom(authorflowPanel);
bp.setCenter(iv1);
root.getChildren().add(bp);
}
This code sample doesn't have iv1 (imageview) binded to anything, cause at this point I have no idea what I can bind to that will give me the remaining space in the scene. Since I cannot use the full width or height of the scene, I'm at a loss of what I am supposed to do here.
The code above makes it look like this:
Wrap the ImageView in some kind of Pane (e.g. a StackPane). Then the pane will fill the center region of the border pane and you can bind to its width and height:
ImageView iv1 = new ImageView();
iv1.setImage(fximage);
iv1.setPreserveRatio(true);
StackPane imageContainer = new StackPane(iv1);
iv1.fitWidthProperty().bind(imageContainer.widthProperty());
iv1.fitHeightProperty().bind(imageContainer.heightProperty());
// ...
bp.setCenter(imageContainer);

libgdx ScrollPane - Doesn't scroll?

I'm making a lobby in a multi-player game, which may have any number of players displayed in a table. I have the following code:
camera = new OrthographicCamera(WIDTH,HEIGHT);
camera.position.set(WIDTH/2,HEIGHT/2, 0);
camera.update();
stage = new Stage();
Gdx.input.setInputProcessor(stage);
stage.setCamera(camera);
stage.setViewport(WIDTH,HEIGHT,false);
ScrollPaneStyle paneStyle = new ScrollPaneStyle();
paneStyle.background = new TextureRegionDrawable(WizardsDuel.atlas.findRegion("cavebg"));
paneStyle.vScrollKnob = new TextureRegionDrawable(WizardsDuel.atlas.findRegion("GUI/slidernob"));
paneStyle.hScroll = paneStyle.hScrollKnob = paneStyle.vScroll = paneStyle.vScrollKnob;
Table container = new Table();
table = new Table();
ScrollPane pane = new ScrollPane(table,paneStyle);
container.add(pane).width(WIDTH).height(HEIGHT);
container.row();
container.setBounds(0,0,WIDTH,HEIGHT);
stage.addActor(container);
font = new BitmapFont();
color = new Color(0,0,0,1);
style = new TextButtonStyle();
style.font = font;
style.up = new TextureRegionDrawable(WizardsDuel.atlas.findRegion("GUI/guibg"));
style.fontColor = color;
handler = new ChangeHandler();
ArrayList<User> users = FirebaseManager.lobbyUsers;
for(int i = 0; i < users.size() || i < 100; i++){
TextButton tmp = new TextButton("",style);
tmp.scale(2);
//tmp.setText(users.get(i).name);
tmp.setText(i+ " asdf");
tmp.addListener(handler);
table.add(tmp).width(WIDTH/4f);
if(i%2 == 1 && i > 0)
table.row();
}
Despite the manner in which the table clearly extends below the bottom of the screen(which should be the bottom of the scroll pane), there is no scroll bar, and clicking and dragging does nothing.
Screenshot:
maybe you forget to make stage act in render(), add something like:
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));
stage.draw();
}
You do actually need two things. An outer Container and an inner Container. You do regularly use two Tables for this. So here is a small example how I use the scrollPane. Actually with no style but it should make it clear.
this.table = new Table();
this.container = new Table();
scroll = new ScrollPane(table);
container.add(scroll).width(500f).height(500f);
container.row();
The table is the table one where you do add the stuff that should be scrollable. The container is the outer box. So you can add for example a headline above your scrollbox. The outer box (container) does need a size. Else you will not have any scrollbars or such. And you do need the inner table.
Simple example for adding:
style = new LabelStyle(font, Color.WHITE);
label = new Label(null, style);
table.add(label);
table.row();
label.setAlignment(1); // align center
give it more lines that it can show and you'll have a scroll pane. Else there is no scrollbar or such.
All in one. You just missed the outer container i think. Add it and it should work. Don't forget to sett the sizes.
My problem was that is wasn't receiving input. My I shouldn't have set the input processor in the constructor, because, the previous screen was setting the processor to null when it was "hidden", so when I moved the line to LobbyScreen's show method it happened after the previous screen was hidden, and the input is set correctly.
after you init the scrollpane you should call this first
mScrollPane.layout();
2023 | KOTLIN
The element to be scrolled must be added to the stage or group before passing it to the ScrollPane
Create the necessary actor and add it to the stage or group
val actor = Actor()
[Stage/Group].addActor(actor)
Create a ScrollPane and place an actor in it
val scrollPane = ScrollPane(actor)
Set the position and dimensions for the actor and the ScrollPane
actor.setBounds(x,y,w,h) | scrollPane.setBounds(x,y,w,h)
PS. Vel_daN: Love what You DO 💚.

Categories