I am trying to create a textfield that has an image part within itself, similar to this.
imageView.fitHeightProperty().bind(Bindings.createDoubleBinding(
() -> textField.getHeight() -
textField.getPadding().getTop() -
textField.getPadding().getBottom(),
textField.heightProperty(), textField.paddingProperty()));
imageView.fitWidthProperty().bind(imageView.fitHeightProperty());
textField.paddingProperty().bind(Bindings.createObjectBinding(
() -> new Insets(textField.getPadding().getTop(),
textField.getPadding().getRight(),
textField.getPadding().getBottom(),
textField.getPadding().getRight() * 2 + imageView.getFitWidth()),
imageView.fitWidthProperty(), textField.paddingProperty()));
My current approach is to use a StackPane to hold the TextField, then also add an ImageView as the StackPane's child. The ImageView needs to know how resize itself, so I have bound its fitHeight to the TextField's height, with consideration of the TextField's padding.
The ImageView's fitWidth is then bound to its own fitHeight.
Lastly, I need to make my TextField's text offset to the right (because the image is blocking it), so I once again did another binding that is dependent on the ImageView's fitWidth.
This ends up with circular dependency, which causes the stack to overflow. Is there any other way to do it without hard coding the TextField's left padding?
Here is a little exemple, i've used (StackPane/TextField/ImageView) but instead of the Image i advise you to draw your own shape with SVG to have the full control on it (MouseHover/Focused...), i've also used a CSS to achieve this :
Java :
private StackPane sp = new StackPane();
private TextField tf = new TextField();
private ImageView iv;
//Init StackPane
sp.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
sp.getStyleClass().add("identifiant");
sp.setPrefSize(200, 40);
sp.setLayoutX(100);
sp.setLayoutY(100);
//Init ImageView
iv = new ImageView(getClass().getResource("Img.png").toString());
StackPane.setAlignment(iv, Pos.CENTER_LEFT);
StackPane.setMargin(iv, new Insets(0, 0, 0, 10));
//Init TextField
StackPane.setAlignment(tf, Pos.CENTER_LEFT);
StackPane.setMargin(tf, new Insets(2, 5, 0, 30));
//Add all content
sp.getChildren().addAll(iv,tf);
Css :
.identifiant{
-fx-background-color:#45444a;
-fx-effect:innershadow(three-pass-box , rgba(0,0,0) , 6, 0.0 , 0 , 0);
-fx-background-radius:8px;
}
.text-field{
-fx-background-insets:0;
-fx-background-color:#45444a;
-fx-text-fill:white;
}
Hope this will help you !
Related
I am currently developing a messenger in javafx. my general layout is a gridpane with a customized Vbox containing a ListView and a Textfield. The problem is that as you can see below there is a big emty area beneath the textfield. I already tried setting the rowspan to 2, which didn't work.
The important Code:
Main:
chatBox = new ChatBox();
gridPane.add(chatBox, 1, 0, 1, 2);
ChatBox(extends Vbox):
private static ListView<Message> messages;
private TextField inputField;
public ChatBox() {
inputField = new TextField();
messages = new ListView<>();
init();
getChildren().addAll(messages, inputField);
}
Try adding this in the ChatBox class:
VBox.setVgrow(messages, Priority.ALWAYS);
And add this in the main class:
GridPane.setVgrow(chatBox, Priority.ALWAYS);
You need to set the vgrow using RowConstraints. Assuming your first row contains the ListView that is supposed to take all the available space:
RowConstraints constraints = new RowConstraints();
constraints.setVgrow(Priority.ALWAYS);
gridPane.getRowConstraints().addAll(constraints, new RowConstraints());
In order to force the list view to take all the height available in its parent, you can use the following method:
messages.setMaxHeight(Double.MAX_VALUE);
If the problem comes from the VBox, its maxHeight can also be modified with the same method.
I have a school project or something like that and I am trying to make a sign up panel for users. This panel opens when user clicks on sign up. It looks like this.
What I am trying to do is I want to disable that Create Button and It will be enabled only if there are 3 checks on the dialog.
I am using a GridPane on Dialog and I was thinking about returning those certain nodes (Checks which are ImageViews) at those cells and check whether the condition is true. However, I could not figure out how to return a node from GridPane. If you have any other approach for this problem it is fine too.
This is the code's relevant part.
public void SignUp(){
//Create the custom dialog.
Dialog signUpDialog = new Dialog();
//Dialog Title
signUpDialog.setTitle("Sign Up");
//Setting "OK" button type.
ButtonType buttonTypeCreate = new ButtonType("Create", ButtonBar.ButtonData.OK_DONE);
//Adding Button types.
signUpDialog.getDialogPane().getButtonTypes().addAll(buttonTypeCreate, ButtonType.CANCEL);
//Creating the GridPane.
GridPane gridPane = new GridPane();
gridPane.setHgap(10);
gridPane.setVgap(10);
gridPane.setPadding(new Insets(20, 150, 10, 10));
//Setting the Check Icon.
Image imageCheck = new Image("resources/check_icon.png");
//Setting 3 different ImageViews for Check Icon because can't add duplicates to GridPane.
ImageView imageViewCheck1 = new ImageView(imageCheck);
ImageView imageViewCheck2 = new ImageView(imageCheck);
ImageView imageViewCheck3 = new ImageView(imageCheck);
//Setting the X Icon.
Image imageX = new Image("resources/x_icon.png");
//Setting 3 different ImageViews for X Icon because can't add duplicates to GridPane.
ImageView imageViewX1 = new ImageView(imageX);
ImageView imageViewX2 = new ImageView(imageX);
ImageView imageViewX3 = new ImageView(imageX);
//TextField for User ID.
TextField textFieldDialogUserID = new TextField();
textFieldDialogUserID.setPromptText("User ID");
textFieldDialogUserID.setAlignment(Pos.CENTER_RIGHT);
//PasswordField for Password.
PasswordField passwordFieldDialogPassword = new PasswordField();
passwordFieldDialogPassword.setPromptText("Password");
passwordFieldDialogPassword.setAlignment(Pos.CENTER_RIGHT);
//PasswordField for Confirm Password.
PasswordField passwordFieldDialogConfirmPassword = new PasswordField();
passwordFieldDialogConfirmPassword.setPromptText("Confirm Password");
passwordFieldDialogConfirmPassword.setAlignment(Pos.CENTER_RIGHT);
gridPane.add(new Label("User ID"), 0, 0);
gridPane.add(textFieldDialogUserID, 1, 0);
gridPane.add(new Label("Password"), 0, 1);
gridPane.add(passwordFieldDialogPassword, 1, 1);
gridPane.add(new Label("Confirm Password"), 0, 2);
gridPane.add(passwordFieldDialogConfirmPassword, 1, 2);
gridPane.add(imageViewX1,2,0);
gridPane.add(imageViewX2,2,1);
gridPane.add(imageViewX3,2,2);
signUpDialog.getDialogPane().setContent(gridPane);
Stage signUpStage = (Stage) signUpDialog.getDialogPane().getScene().getWindow();
signUpStage.getIcons().add(new Image("resources/application_icon.png"));
Optional<Pair<String, String>> result = signUpDialog.showAndWait();
}
Create an appropriate BooleanBinding which expresses when the button should be disabled. You can use the Bindings utility class to create the expression, including comparison, ands and ors. To make the code more readable do a static import of the functions.
Get the create button from your panel and bind the boolean expression to the disable property of your button.
If any of the values change the JavaFX framework will automatically reevaluate the bindings and update the button's state accordingly.
import static javafx.beans.binding.Bindings.*;
BooleanBinding notComplete = or(
equal(textFieldDialogUserID.textProperty(), null),
equal(passwordFieldDialogPassword.textProperty(), null));
Node createButton = signUpDialog.getDialogPane().lookupButton(buttonTypeCreate);
createButton.disableProperty().bind(notComplete);
You can use the same mechanism to control the visibility of each checkmark. Create a 'incomplete' BooleanBinding for each textfield and bind it with a not binding to the visible property of the checkmark. Use all these BooleanBindings in a compound or to determine the button state. This way the button state and checkmarks will always be in sync.
I could not figure out how to return a node from GridPane.
gridPane.getChildren()
provides the list of nodes, but you already have your components textFieldDialogUserID, passwordFieldDialogPassword, passwordFieldDialogConfirmPassword.
=> Add an action listener for each of them, that checks the values when its value is changed. depending on the result, enable/disable the Create button (per default, it should be disabled).
you can have an example : http://docs.oracle.com/javafx/2/ui_controls/text-field.htm
I want to add multiple images in a ScrollPane when clicking a button. Now when I click the button a new rectangle is created and fitted with a new image.
The problem is the scrollbar is not displaying when a new image is added.
Here is the code:
#FXML
public void handleButtonPause(){
Rectangle r = new Rectangle();
if(counterIm==0){
//Ap1.setMinSize(Sp1.getWidth(), Sp1.getHeight() - 10);
r.setY(Sp1.getHeight() *((double)1/36));
r.setWidth(Sp1.getWidth()*0.75);
rectWidth=r.getWidth();
r.setHeight(Sp1.getHeight()/6);
rectHeight=r.getHeight();
}
else {
r.setY(Sp1.getHeight()*((7*counterIm+1)/36));
r.setWidth(rectWidth);
r.setHeight(rectHeight);
}
r.setX(Sp1.getWidth() / 10);
r.setArcWidth(20);
r.setArcHeight(20);
Ap1.getChildren().add(r);
Image image = new Image(new File("C:\\Users\\Manuel\\Desktop\\error.png").toURI().toString());
r.setFill(new ImagePattern(image));
Sp1.setVvalue(1);
counterIm=counterIm+1;
I don't know how your composition looks like.
A good approach could be to put the images into a VBox and put the VBox into the ScrollPane.
And check if you have set the VBar Policy of your SrollPane:
srollbar.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
You can also set the maximal height of the VBox to double maximum to make it sure it will always grow vertically:
vbox.setMaxHeight(Double.MAX_VALUE);
I have been playing around with JavaFX and I really like it. But I can't seem to get my content where I want it. Even if I place a vbox on the CENTER and a label on the TOP, they're still in the center and almost touching each other.
I want to have (Centered in the screen of course):
My Title
SubLabel
Button1
Button2
Button3
BottomLabel
But it shows up as:
My Title
SubLabel
Button1
Button2
Button3
BottomLabel
If I settranslateX my vbox or top label, it moves the label, but also moves everything else with it.
How can I get it to align correctly?
Here is my pseudo-code:
private Node PreMenu()
{
Group group2 = new Group();
BorderPane pane = new BorderPane();
Text label = new Text("Please Choose a Option");
label.setFont(Font.font("Kozuka Gothic Pro", 30));
label.setEffect(addEffect(Color.web("#FF6600"), .85, 20));
label.setTextAlignment(TextAlignment.CENTER);
label.setTranslateY(-300); //This moves my label, but it also moves the vbox under it DOWN.
VBox vbox = new VBox();
Button option1= new Button("Firstbutton");
Button option2= new Button("Secondbutton");
Button option3= new Button("HelpButton");
option1.setEffect(addEffect(Color.web("#FF6600"), .8, 10));
option2.setEffect(addEffect(Color.web("#FF6600"), .8, 10));
option3.setEffect(addEffect(Color.web("#FF6600"), .8, 10));
option1.setTextAlignment(TextAlignment.CENTER);
option1.setMinWidth(400);
option2.setTextAlignment(TextAlignment.CENTER);
option2.setMinWidth(400);
option3.setTextAlignment(TextAlignment.CENTER);
option3.setMinWidth(400);
vbox.setSpacing(20);
vbox.getChildren().add(option1);
vbox.getChildren().add(option2);
vbox.getChildren().add(option3);
pane.setTop(label);
pane.setCenter(vbox);
group2.getChildren().add(pane);
return group2;
}
Another Node I have in my program with the same issue:
Easiest way with your code would be to set top and bottom padding for your Vbox with buttons:
vbox.setPadding(new Insets(50,0,50,0));
This line adds spacing of 50 pixels above and below vbox.
Don't put it in a Group. Just return the BorderPane directly. If you can post a fully working example (with a main()) I'll take a look at it, but I suspect the problem is the Group you are unnecessarily wrapping around the BorderPane.
Groups have a special function in JavaFX, read the documentation on the difference between Groups and Regions.
I need to create widget, similar to google maps one.
In it's simplest form, the map of all planet is divided into image tiles. While user scrolls the widget into different directions, new empty cells appeared and widget requests these tiles from the server and put it into the widget.
How it can be implemented in GWT?
I found no way to set absolute position dynamically in ScrollPanel. I found no way to draw something lefter than left or upper then top in AbsolutePanel. How to combine panels correctly?
Thanks.
UPDATE 1
Here is one of the examples. In this example labels do not show, because the size of containing absolute panel is zero by height (looked in firebug). I can't just set it's size because this won't help for label at -100,-100.
public void onModuleLoad() {
Label label_minus100_minus100 = new Label("(-100,-100)");
Label label_0_0 = new Label("(0,0)");
Label label_100_100 = new Label("(100,100)");
AbsolutePanel absolutePanel = new AbsolutePanel();
absolutePanel.setStyleName("absolutePanel");
absolutePanel.add(label_0_0, 0, 0);
absolutePanel.add(label_minus100_minus100, -100, -100);
absolutePanel.add(label_100_100, 100, 100);
DOM.setStyleAttribute(absolutePanel.getElement(), "overflow", "visible");
ScrollPanel scrollPanel = new ScrollPanel();
scrollPanel.add(absolutePanel);
scrollPanel.setStyleName("scrollPanel");
RootPanel rootPanel = RootPanel.get();
rootPanel.add(scrollPanel);
}