I'm trying to make a chatBox with javafx, and I want the messages from the client to be aligned to right and the rest to left.
I'm using a Vbox, wrapped in a Scrollpane and in that Vbox, each message is wrapped in another Vbox.
But aligning the inner Vbox doesn't work.
Here is my code:
private VBox addMsg(String senderName, String text, String time) {
Label snderName = new Label(senderName + ":");
snderName.setId("senderName");
snderName.setMaxWidth(400);
snderName.setAlignment(Pos.BASELINE_LEFT);
Label msgText = new Label(text);
msgText.setId("msgText");
msgText.setWrapText(true);
msgText.setMaxWidth(400);
Label msgTime = new Label(time);
msgTime.setId("msgTime");
msgTime.setMaxWidth(400);
msgTime.setAlignment(Pos.BASELINE_RIGHT);
VBox msg = new VBox(snderName, msgText, msgTime);
msg.setBackground(new Background(new BackgroundFill(Color.AQUA, new CornerRadii(3d), Insets.EMPTY)));
msg.setPadding(new Insets(5));
msg.setMaxWidth(400);
msg.setEffect(new DropShadow(2, Color.DARKBLUE));
return msg;
}
public void buildChatBox() {
Button backToPublicChat = new Button("<");
backToPublicChat.setId("backToPublicChat");
backToPublicChat.setVisible(false);
Text chatWindowInfo = new Text("public chat room");
chatWindowInfo.setId("chatWindowInfo");
VBox chatHistory = new VBox();
chatHistory.setId("chatHistory");
chatHistory.setPrefWidth(CHAT_BOX_WIDTH);
chatHistory.setPrefHeight(GAME_HEIGHT - 50);//badsmell
TextField messageField = new TextField("type your message...");
messageField.setId("messageField");
messageField.setPrefHeight(30);
messageField.setPrefWidth(CHAT_BOX_WIDTH - 40);
Button sendButton = new Button("send");
sendButton.setId("sendButton");
sendButton.setPrefHeight(30);
sendButton.setOnMouseClicked(event -> {
VBox vBox = addMsg(
"Aran",
"hi, i'm aran",
"5:19");
vBox.setAlignment(Pos.TOP_LEFT);
chatHistory.getChildren().add(vBox);
VBox vBox2 = addMsg(
"Farnam",
"oh, I love you!",
"5:19");
vBox2.setAlignment(Pos.TOP_RIGHT);
chatHistory.getChildren().add(vBox2);
});
ScrollPane scrlPane = new ScrollPane(chatHistory);
scrlPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scrlPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
scrlPane.setId("scrolPane");
chatBox = new VBox(new HBox(backToPublicChat, chatWindowInfo), scrlPane, new HBox(messageField, sendButton));
chatBox.setId("chatBox");
chatBox.getStylesheets().add("TowDef/GUI//chatBoxCSS.css");
}
Also I just need to set the HPos but i don't know how to, so I used the Pos.TOP_RIGHT.
does anyone know how to achieve this?
any advice on how to make the chatbox in a better way will be well appreciated:)
You can achieve that using HBox,
For Right Aligning.
Label label=new Label("guru ");
label.getStylesheets().add("sample/styles/send.css");
label.setId("receive");
HBox hBox=new HBox();
hBox.getChildren().add(label);
hBox.setAlignment(Pos.BASELINE_RIGHT);
vBox.getChildren().add(hBox);
vBox.setSpacing(10);
For Left Aligning
Label label=new Label(msg);
label.getStylesheets().add("sample/styles/send.css");
label.setId("send");
HBox hBox=new HBox();
hBox.getChildren().add(label);
hBox.setAlignment(Pos.BASELINE_LEFT);
vBox.getChildren().add(hBox);
vBox.setSpacing(10);
Related
I'm trying to get two tabs, each with their own little form that contain labels and textfields/textareas. I thought my making a "Master" VBox that should display everything but nothing other than the tabs are showing and neither am i getting any errors.
How do I add them to the scene?
// Label and Button variables
private Label fname,lname, appt, AppointmentInfo;
protected String input;
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Person Appointments");
primaryStage.setWidth(500);
primaryStage.setHeight(500);
//Create and set Tab Names
Tab InfoTab = new Tab();
Tab ApptTab = new Tab();
InfoTab.setText("PersonInfo");
ApptTab.setText("Appointments");
// VBoxes
VBox personInfoBox = new VBox();
VBox FirstBox = new VBox();
VBox appointmentBox = new VBox();
// Setup labels and fields
fname = new Label();
lname = new Label();
appt = new Label();
AppointmentInfo = new Label();
fname.setText("First Name");
lname.setText("Last Name");
appt.setText("Appt Count");
AppointmentInfo.setText("Appt Info");
// Text Fields
TextField firstNameText = new TextField();
TextField lastNameText = new TextField();
TextField appointmentText = new TextField();
TextArea apptInfo = new TextArea();
firstNameText.setText("First Name Here");
lastNameText.setText("Last Name Here");
appointmentText.setText("Appointment Here");
personInfoBox.getChildren().add(fname);
personInfoBox.getChildren().addAll(firstNameText);
personInfoBox.getChildren().add(lname);
personInfoBox.getChildren().addAll(lastNameText);
appointmentBox.getChildren().add(AppointmentInfo);
appointmentBox.getChildren().addAll(apptInfo);
// Grid for Tabs
GridPane grid = new GridPane();
GridPane grid2 = new GridPane();
grid.add(fname, 0, 0);
grid.add(firstNameText, 0, 1);
grid.add(lname, 1, 0);
grid.add(lastNameText, 1, 1);
grid.add(appt, 2, 0);
grid.add(appointmentText, 2, 1);
grid2.add(AppointmentInfo, 0, 0);
grid2.add(apptInfo, 0, 1);
InfoTab.setContent(grid);
ApptTab.setContent(grid2);
// TabPane
TabPane tabPane = new TabPane();
tabPane.getTabs().add(InfoTab);
tabPane.getTabs().add(ApptTab);
InfoTab.setClosable(false);
ApptTab.setClosable(false);
InfoTab.setContent(personInfoBox);
ApptTab.setContent(appointmentBox);
VBox one = new VBox(tabPane, personInfoBox);
Scene scene = new Scene(one, 500, 500);
primaryStage.setScene(scene);
primaryStage.show();`
You can't assign a Node more than once to the SceneGraph:
A node may occur at most once anywhere in the scene graph. Specifically, a node must appear no more than once in all of the following: as the root node of a Scene, the children ObservableList of a Parent, or as the clip of a Node.
http://docs.oracle.com/javase/8/javafx/api/javafx/scene/Node.html
You assigned e.g. lname to personInfoBox AND grid. So finally lname will be assigned to grid only. Then you set grid as content for a Tab and after that you set personInfoBox as content, which is now empty
I have a GridPane that i fill dynamically, then I display it, the problem is: if the rows are so many, then the rows in the bottom don't get displayed, what i want is to add a scrollbar so that I can display all of the rows, here is the code but it's not working:
BudgetManager bManager = new BudgetManager();
List<Debt> debts = bManager.getDebts();
GridPane topLevel = new GridPane();
topLevel.setAlignment(Pos.TOP_CENTER);
int row = 0;
double totatB = 0, totalS = 0;
for (Debt d : debts) {
//fill GridPane
}
ScrollBar sc = new ScrollBar();
sc.setMin(0);
sc.setMax(350);
sc.setVisibleAmount(20);
sc.setOrientation(Orientation.VERTICAL);
sc.setUnitIncrement(10);
sc.setBlockIncrement(50);
sc.setPrefWidth(20);
sc.valueProperty().addListener((ObservableValue<? extends Number> ov, Number old_val, Number new_val) -> {
topLevel.setLayoutY(-new_val.doubleValue());
}
});
HBox box = new HBox();
box.getChildren().addAll(topLevel, sc);
HBox.setHgrow(topLevel, Priority.ALWAYS);
Scene scene = new Scene(box, 1200, 600);
stage.setScene(scene);
stage.show();
SOLVED
here is the solution, thanks to keuleJ, using ScrollPane instead of ScrollBar:
ScrollPane scroll = new ScrollPane();
GridPane topLevel = new GridPane();
scroll.setContent(topLevel);
scroll.setHbarPolicy(ScrollBarPolicy.ALWAYS);
scroll.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
scroll.setFitToWidth(true);
scroll.setFitToHeight(true);
Scene scene = new Scene(scroll, 1200, 600); // Manage scene size
Use fitToWidth or fitToHeight properties.
See the docs:
https://docs.oracle.com/javafx/2/api/javafx/scene/control/ScrollPane.html
I'm trying to add a ScrollBar to a HBox. The ScrollBar gets added, but I get no scrolling. How can I make it work?
public class ScrollableItems {
public void scrollableItems(HBox content) {
double height = 180;
ScrollBar sc = new ScrollBar();
content.getChildren().add(sc);
sc.setLayoutX(content.getWidth() - sc.getWidth());
sc.setMin(0);
sc.setOrientation(Orientation.VERTICAL);
sc.setPrefHeight(height);
sc.setMax(height * 2);
sc.valueProperty().addListener(new ChangeListener<Number>() {
public void changed(ObservableValue<? extends Number> ov,
Number old_val, Number new_val) {
content.setLayoutY(-new_val.doubleValue());
}
});
}
}
Add children to a HBox then pass it to scrollableItems(HBox content) above to add a SCrollBar
public HBox mainItemsWrapper() {
HBox scrollabelWrapper = new HBox();
scrollabelWrapper.setMaxHeight(180);
HBox entityDetailViewWrapper = new HBox();
entityDetailViewWrapper.getChildren().addAll(.....);
scrollabelWrapper.getChildren().add(entityDetailViewWrapper);
new ScrollableItems().scrollableItems(scrollabelWrapper);
return scrollabelWrapper;
}
Thank you all.....
I do not really get why you are trying to reinvent the wheel.. you should probably use the ScrollPane instead.
This little example shows how to create a horizontally scrollable HBox with the ScrollPane class:
#Override
public void start(Stage primaryStage) {
HBox hbox = new HBox();
Button b = new Button("add");
b.setOnAction(ev -> hbox.getChildren().add(new Label("Test")));
ScrollPane scrollPane = new ScrollPane(hbox);
scrollPane.setFitToHeight(true);
BorderPane root = new BorderPane(scrollPane);
root.setPadding(new Insets(15));
root.setTop(b);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
As eckig said, you can wrap you HBox into a ScrollPane.
Additionnaly, you can customize the visual part of the scrollbar in CSS. I found this link useful for the comprehension of the differents parts of a scrollbar: Customize ScrollBar via CSS
I am having a resize issue when content is added and removed from a JavaFX BorderPane. The BorderPane content is not being resized until the window is manually resized. I have written a small test app to model this behavior. The application builds a BorderPane that contains a rectangle embedded within a StackPane at the center of the BorderPane. Along the bottom of the BorderPane there is a VBox and HBox that contain text and a separator. There is a menu item that removes the content from the bottom of the BorderPane (MoveText -> Right) and adds similar content to the right position of the BorderPane.
When the text is added to the right position of the BorderPane, the rectangle overlaps the text. In otherwords the content of the BorderPane center is overlapping the content in the BorderPane right.
I saw the following link -
https://stackoverflow.com/questions/5302197/javafx-bug-is-there-a-way-to-force-repaint-this-is-not-a-single-threading-pr
Calling requestLayout does not seem to help. I have also tried calling impl_updatePG and impl_transformsChanged on various nodes in the graph. I got this idea from this thread - https://forums.oracle.com/forums/thread.jspa?threadID=2242083
public class BorderPaneExample extends Application
{
private BorderPane root;
private StackPane centerPane;
#Override
public void start(Stage primaryStage) throws Exception
{
root = new BorderPane();
root.setTop(getMenu());
root.setBottom(getBottomVBox());
centerPane = getCenterPane();
root.setCenter(centerPane);
Scene scene = new Scene(root, 900, 500);
primaryStage.setTitle("BorderPane Example");
primaryStage.setScene(scene);
primaryStage.show();
}
private MenuBar getMenu()
{
MenuBar menuBar = new MenuBar();
MenuItem rightMenuItem = new MenuItem("Right");
rightMenuItem.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
root.setRight(getRightHBox());
root.setBottom(null);
root.requestLayout();
}
});
MenuItem bottomMenuItem = new MenuItem("Bottom");
bottomMenuItem.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
root.setRight(null);
root.setBottom(getBottomVBox());
}
});
Menu menu = new Menu("Move text");
menu.getItems().add(rightMenuItem);
menu.getItems().add(bottomMenuItem);
menuBar.getMenus().addAll(menu);
return menuBar;
}
private HBox getRightHBox()
{
HBox hbox = new HBox();
VBox vbox = new VBox(50);
vbox.setPadding(new Insets(0, 20, 0, 20));
vbox.setAlignment(Pos.CENTER);
vbox.getChildren().addAll(new Text("Additional Info 1"),
new Text("Additional Info 2"), new Text("Additional Info 3"));
hbox.getChildren().addAll(new Separator(Orientation.VERTICAL), vbox);
return hbox;
}
private VBox getBottomVBox()
{
VBox vbox = new VBox();
HBox hbox = new HBox(20);
hbox.setPadding(new Insets(5));
hbox.setAlignment(Pos.CENTER);
hbox.getChildren().addAll(new Text("Footer Item 1")
, new Text("Footer Item 2"), new Text("Footer Item 3"));
vbox.getChildren().addAll(new Separator(), hbox);
return vbox;
}
private StackPane getCenterPane()
{
StackPane stackPane = new StackPane();
stackPane.setAlignment(Pos.CENTER);
final Rectangle rec = new Rectangle(200, 200);
rec.setFill(Color.DODGERBLUE);
rec.widthProperty().bind(stackPane.widthProperty().subtract(50));
rec.heightProperty().bind(stackPane.heightProperty().subtract(50));
stackPane.getChildren().addAll(rec);
return stackPane;
}
public static void main(String[] args)
{
Application.launch(args);
}
}
Any suggestions would be appreciated.
Thanks
For the sake of having an answer:
The StackPane needs to have its minimum size set in order to do clipping. So if you explicitly add stackPane.setMinSize(0, 0); to the getCenterPane() method, it should fix your problem.
So your getCenterPane() method would now look like this:
private StackPane getCenterPane()
{
StackPane stackPane = new StackPane();
stackPane.setMinSize(0, 0);
stackPane.setAlignment(Pos.CENTER);
final Rectangle rec = new Rectangle(200, 200);
rec.setFill(Color.DODGERBLUE);
rec.widthProperty().bind(stackPane.widthProperty().subtract(50));
rec.heightProperty().bind(stackPane.heightProperty().subtract(50));
stackPane.getChildren().addAll(rec);
return stackPane;
}
I am trying to add a ToolBar control, containing 2 Buttons and a TextField in my scene graph.
I want that the TextField control gets automatically resized and acquire all the space available into toolbar. So, I used the HBox layout control to add the buttons and textfield.
I did as followed:
ToolBar tb = new ToolBar();
HBox hbox = new HBox(8);
TextField tf = new TextField();
HBox.setHgrow(tf, Priority.ALWAYS);
hbox.getChildren().add(new Button("<-"));
hbox.getChildren().add(new Button("->"));
hbox.getChildren().add(tf);
tb.getItems().add(hbox);
But its not working. Where am I going wrong? Please help.
You can try next:
ToolBar tb = new ToolBar();
TextField tf = new TextField();
HBox hbox = new HBox(8);
hbox.prefWidthProperty().bind(tb.widthProperty().subtract(20));
HBox.setHgrow(tf, Priority.ALWAYS);
hbox.getChildren().add(new Button("<-"));
hbox.getChildren().add(new Button("->"));
hbox.getChildren().add(tf);
tb.getItems().add(hbox);