JavaFX title bar RTL not supported? - java-8

I cant seem to find a way of making the title bar of my window be RTL.
I can make the inner nodes RTL by changing the node orientation property, but not the title bar.
So I get a really weird looking app where everything is RTL except the title bar.
How can I fix this?

You need to invoke setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT) on the scene before showing the stage primaryStage.show():
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
Scene scene = new Scene(root, 300, 275);
primaryStage.setScene(scene);
scene.setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
See Node Orientation in JavaFX:
Because the orientation of children might be different for each child, the orientation of a child node when explicitly set can override the parent. For example, the top level window might be right-to-left, with the title and close box appearing on the left.

Just like what #Eng.Fouad said for scene object can be done for menubar.
Invoking
setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT)
for the menubar object makes it rtl:
MenuBar menuBar = new MenuBar();
menuBar.setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT);
except that the arg for this method can be
NodeOrientation.LEFT_TORIGHT
which makes it left to right and
NodeOrientation.INHERIT
that gets its value from the parent container.

Related

How do I add a controller (MVC) to my JavaFX application which I wrote in Java?

So I created an app containing the following classes: Main.java (where launch is along with window, scenes, buttons, etc.), Students.java (students), Connection.java (JDBC connects to MySQL database). There's also a class for login (with its own window, scenes, buttons), a class for charts (opens up a Pie Chart) as well as a confirmbox and alertbox (again with windows, scenes and buttons)...
I then read that good practice is to use MVC by looking through different tutorials plus previous answers here. Additionally the best tutorial was this: http://code.makery.ch/library/javafx-8-tutorial/part1/
The problem with this tutorial however was that it uses scene builder... I wish to create my application by writing code instead. And with my existing code (I can run the app on my IDE and buttons etc. work perfectly, fetches data from database too...) but what do I do with connector?
Do I create a new one?
(NOTE: all my classes are in .src)
A javafx controller is used to control UI elements. One way to attach controller is by adding fx:controller="controllerClassLocation" in your fxml file.
Another way would be to add controller in your code but this also involves fxml file as shown below.
String fxmlPath="MainLayout.fxml";
private Scene getScene(String fxmlPath, ControllerClass controller) {
FXMLLoader loader;
Parent parent;
Scene scene;
try {
//not FXMLLoader.load(getClass().getResource(fxmlPath)
loader = new FXMLLoader(getClass().getResource(fxmlPath));
loader.setController(controller);
parent = loader.load();
} catch (Exception e) {
e.printStackTrace();
return null;
}
scene = new Scene(parent);
return scene;
}
You use a controller if you want to bind your javafx UI elements.
If you do not want to use fxml file then you will have to code all the UI elements and bind to their respective functions and events for controlling them. For eg: In the below example a button btn is created and an event is handled when the button is clicked. The Button btn is binded to the function setOnAction(new EventHandler()) .
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("Hello World");
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 500, 250);
primaryStage.setTitle("Hello World");
primaryStage.setScene(scene);
primaryStage.show();
}
You can create a controller class just like you would using FXML. Create an instance of the controller and pass on all references of your controls that you created in the code where you create all the controls.
Doing this way, you cannot leverage the benefits of FXML binding, such as fx:id, fx:controller and event bindings.

JavaFX Real Fullscreen on macOS

I want a javafx.stage.Stage to be in fullscreen mode on macOS with no (native) menu bar visible. Also I want that the dock is not available while the application is in fullscreen mode.
I have a Stage and I set stage.setFullScreen(true). If the style of my stage is set to stage.initStyle(StageStyle.UNDECORATED), the application displays the native menu bar and the dock. Therefore the whole screen isn't available for the application.
If I set the style to stage.initStyle(StageStyle.UTILITY) the menu bar is not visible, but instead there is a grey area.
And if I move the cursor where usually the menu bar is placed, the menu bar will show itself additionally with a small closing button and a small bar.
Also If I cursor the mouse down where the dock is placed, the dock will show up itself.
How can I achieve a real fullscreen application with no menubar and no dock displayed and no grey bar at the top so my application can use all of the screen size?
Code
import javafx.application.Application;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Fullscreen extends Application {
#Override public void start(Stage stage) throws Exception {
AnchorPane pane = new AnchorPane();
Scene scene = new Scene(pane);
pane.setStyle("-fx-background-color: blue");
stage.initStyle(StageStyle.UTILITY);
stage.setFullScreen(true);
stage.setScene(scene);
stage.show();
//stage.setHeight(stage.getHeight() + 16);
//stage.setY(-16);
}
}
Annotation
If I set stage.setHeight(stage.getHeight() + 16) and stage.setY(-16) after stage.show() and the style is set to stage.initStyle(StageStyle.UTILITY), the grey bar isn't visible anymore. But this seems not to be a good solution for me because it depends on the screen size (in my case 2560x1440) and I don't know how to exactly get the size of the grey bar. Also the menubar and the dock are available.
Using Stage#setFullScreen(boolean) is the correct way. When I run this MWE, I get the expected OS X full screen (no dock, automatically hidden menu bar):
public class FullScreenDemo extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(final Stage primaryStage) {
primaryStage.setFullScreen(true);
primaryStage.setScene(new Scene(new Label("Foo")));
primaryStage.show();
}
}
I don't think you can get rid of the native menu bar that pops up when you hover over its position—that's just how the OS behaves. The corresponding Javadoc also states:
The implementation of full-screen mode is platform and profile-dependent.

Why RecyclerView is not working setBackground function?

I tried many Times for setting backgroundColor on RecyclerView. but i try to scroll then background was removed.So I can fix backgroundColor in RecyclerView. Help me please.
Or I Want to change ForegroundColor.
My Issue Video
https://www.youtube.com/watch?v=C29qhPb44FE
I don't know the reason...
You need to first understand how RecyclerView works.
As you scroll through the cells, the views that gets out of the screen will be RECYCLED, and they will subsequently be reused to display the incoming views. Hence the name RecyclerView. This way, views will always be recycled and reused, thus saving memory.
What you need to do is something like this:
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
//mList and mSelectedObjects are array lists
View yourView = holder.itemView.findViewById(R.id.your_view);
Object object = mList.get(position);
yourView.setTag(object);
yourView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Object object = (Object) v.getTag();
if (mSelectedObjects.contains(object)) {
mSelectedObjects.remove(object);
v.setBackground(null);
} else {
mSelectedObjects.add(object);
v.setBackgroundColor(Color.GRAY);
}
}
});
}
If you set programmatically the background color. You have to set every time the normal color and the selected color.
RecyclerViews are reusing their views. When an item leaves the screen it will be reused to increase the performance of the recycler view.
In this case when one set programmatically a background color and the item leaves the screen. It will be reused in the new item and the background color is still the same as when the item has left the screen.

Create a Sizeable Draggable Pane in JavaFX 8

I am attempting to create a "workspace" where users can open several containers to display distinct information. These need to be moveable and sizeable (ScrollPane for example).
I have successfully created the majority of the functionality - however one thing is really causing me issues and I am not able to figure out the issue.
I created the following class:
public class WorkspaceMoveableSizeablePane extends Pane
public WorkspaceMoveableSizeablePane(Node view) {
getChildren().add(view);
init();
}
private void init() {
...set up the event handlers....
I attempt to use this pane by wrapping an existing pane like so in my WorkspaceController:
#FXML private openSampleWorkspaceNode() {
FXMLLoader loader = new FXMLLoader();
Parent node = loader.load(
this.getClass().getResource("MyView.fxml").openStream());
WorkspaceMoveableSizeablePane dn = new WorkspaceMoveableSizeablePane(node);
pane.getChildren().add(dn);
}
When I open it this way - I can size my Pane and drag it, however the children on the "node" which is an anchor pane stay in their current positions rather than get hidden.
To correct this issue, I wrapped the AnchorPane in a ScrollPane in the FXML file. This allowed the resize to happen - and as expected the portions out of bounds were not visible and the scrollbars appeared, however the drag stopped. When I attempted to track the mouse dragged event, it actually didn't fire unless I was resizing the WorkspaceMoveableSizeablePane.
//Event Listener for MouseDragged
onMouseDraggedProperty().set(event -> {
System.out.println("You are in the Mouse Dragged Event");
if(isTopSelected){
dragPaneToNewLocation(event);
}else if(isResizingHeight) {
handleResizeHeight(event);
}else if(isResizingWidth) {
handleResizeWidth(event);
}
});
I reverted my FXML to AnchorPane and changed the WorkspaceMoveableSizeablePane as follows to see if that would help:
public class WorkspaceMoveableSizeablePane extends ScrollPane
public WorkspaceMoveableSizeablePane(Node view) {
setContent(view);
init();
}
private void init() {
...set up the event handlers....
As before the resize worked, but the drag didn't. The mouse dragged event never fired. Additionally, my scroll pane was blank with nothing in it.
So I am at a loss on how to proceed with this attempt.
Is there a limitation on the event handlers of the ScrollPane? Is there a different event I should be listening for? Thanks!!
The issue was that the ScrollPane was trapping the MouseDragged event.
Added an Event Filter and all is good...
addEventFilter(MouseEvent.MOUSE_DRAGGED, event -> {
if(isTopSelected){
dragPaneToNewLocation(event);
}else if(isResizingHeight) {
handleResizeHeight(event);
}else if(isResizingWidth) {
handleResizeWidth(event);
}
});

JavaFX: Focusing textfield programmatically

I wrote an application with JavaFX which will only be usable with keyboard's arrows.
So I prevented MouseEvent on Scene's stage, and I "listen" to KeyEvents.
I also switched off focusability of all nodes :
for(Node n : children) {
n.setFocusTraversable(false);
Now I have some textfields, checkboxes, and buttons.
I would like to change the state of my input controls (textfield, checkbox,..) programatically: for example I would like to enter the textfield to edit the content programatically.
So my question is: how to enter in a non-focus-traversable textfield?
Because textfield.requestFocus(); doesn't work anymore since I set false to focustraversable property of my textfield.
Thanks
By
n.setFocusTraversable(false);
the node is made non-focus-traversable instead of non-focusable. It can still be focused for example by mouse or programmatically. Since you prevented mouse events, here the other option:
Platform.runLater(new Runnable() {
#Override
public void run() {
textfield.requestFocus();
}
});
Scene scene = new Scene(root);
EDIT: as per comment,
The javadoc of requestFocus states:
... To be eligible to receive the focus, the node must be part of a scene,
it and all of its ancestors must be visible, and it must not be
disabled. ...
So this method should be called after construction of scene graph as follow:
Scene scene = new Scene(root);
textfield.requestFocus();
However, Platform.runLater in the above will run at the end, after the main method start(), which ensures the call of requestFocus will be after scene graph cosntruction.
There maybe other reasons depending on the requestFocus implementation code.
set the .requestFocus(); on initialize method to fire on .fxml file loading controller
#Override
public void initialize(URL url, ResourceBundle rb) {
/* the field defined on .fxml document
#FXML
private TextField txtYear;
*/
txtYear.requestFocus();
}

Resources