javafx reused pane initalization - javafx

Here's my situation. I have a javafx pane which I don't want to recreate each time I show it, because I want to keep all filled by user fields in between switching between views.
For that purpose I did this:
#FXML
private void initialize() {
createOrderPane = FxmlUtils.fxmlLoader(CREATE_ORDER_FXML);
}
public void setCenter(String fxmlPath) {
if(CREATE_ORDER_FXML.equals(fxmlPath)) {
borderPane.setCenter(createOrderPane);
}
else {
borderPane.setCenter(FxmlUtils.fxmlLoader(fxmlPath));
}
}
so in case user wants to see CREATE_ORDER_FXML it doesn't reload it, but uses already existing instance.
The problem is that some parts of the view should be reinitalized. For example database might change and I want to refresh some comboboxes which reads value from DB. How to achieve that?
Is there some onShow property? Or maybe I am able to get to the controller of createOrderPane object?

Related

How does one call a method on the changing of a Tab in JavaFx?

Ok so here is what i am trying to do: I have a page called 'SettingsPage'. Now, in this page i Have a tabPane with 3 tabs; users, buttons, and sales. Buttons and Users both have tables which need to be populated with data before they are viewed by the user. When I was first making the program I just used a 'initialize' method to populate the user table on the opening of 'SettingsPage'. However, now that I am beginning to try and populate the buttons table, I am encountering a memory error because now there is too much data to be loaded at once together.
So, I though a good solution to this would be to make an Event method that is called whenever a certain tab is opened. I am using SceneBuilder atm, and what seemed to be the equivalent of this was onSelectionChanged, however I can't seem to use this as you would use 'methodEg(ActionEvent event)...'. So my question is, how can ensure that a method will be called on the opening of a certain tab.
For example, when 'buttonTab' is clicked, the 'populateButtonTable' method is called.
The answer to this was this code:
And if anyone asks why I didn't use .isSelected()... I did, it for some reason didn't work, but what I have done below does, so I dunno...
'''
#FXML public void initialize(URL url, ResourceBundle rb){
tabs.getSelectionModel().selectedItemProperty().addListener(
new ChangeListener<Tab>() {
#Override
public void changed(ObservableValue<? extends Tab> ov, Tab t, Tab t1)
{
if (tabs.getSelectionModel().getSelectedItem() == ExampleTab)
{
//do whatever
}
}
}
);

JavaFX: set fullscreen exclusive mode (FSEM) in non-mouse/keyboard-handler

my application consists of a TabPane named tabPane with, lets say, two Tabs: firstTab and secondTab. Whenever firstTab is selected, I want the application to be in FSEM (full-screen exclusive mode, see documentation); otherwise it should be in normal windowed mode.
My usual way of being notified about which Tab is active is either
BooleanBinding isFirstTabActive = tabPane.getSelectionModel().
selectedItemProperty().isEqualTo(firstTab);
or
tabPane.getSelectionModel.selectedItemProperty().addListener(...);
Since stage.fullScreenProperty() is read-only and therefore cannot be binded (as stated in docs), I can not use my first method and do, lets say,
stage.fullScreenProperty().bind(isFirstTabActive) //not working.
Since I am not planning on sigining the application for now and, as the docs state:
Applications can only enter FSEM in response to user input. More specifically, entering is allowed from mouse (Node.mousePressed/mouseReleased/mouseClicked) or keyboard (Node.keyPressed/keyReleased/keyTyped) event handlers.
I can not use the second method either, by doing
tabPane.getSelectionModel.selectedItemProperty().addListener(new ChangeListener<Tab>() {
#Override
public void changed(ObservableValue<? extends Tab> observable, Tab oldValue, Tab newValue) {
stage.setFullScreen(newValue == firstTab);
}
);
because this way the application does not enter FSEM but only emulated fullscreen mode.
I do know that I can enter FSEM by creating EventHandlers which listen to tabPane events. But this way I had to add two EventHandlers for both MouseEvent.MOUSE_CLICKED and KeyEvent.KEY_TYPED, and the EventHandlers would have to explicitly find out whats going on ignoring their Event, like:
tabPane.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
stage.setFullScreen(tabPane.getSelectionModel().getSelectedItem() == firstTab);
}
});
So is this really the way to go here? Or can I do some workaround with the Bindings? Any suggestions here? Thanks.

Manually Open custom inspector for serializable object

I have a window editor that holds nodes. I would like to open a custom inspector when one of these nodes is selected. The node class is a custom serializable class. Is this possible?.
It seems that custom inspectors can be created manually through the Editor.CreateEditor method but can't see how to let it appear docked like an usual inspector in the unity inspector window.
I would like to achieve the same behaviour that we have when we select a gameobject in sceneview that inmediately show properties for the object (Components, etc...) in the unity inspector.
Cheers
As I'm not sure what you're asking, here are multiple different solutions;
Selection
If you just want your nodes to become the focus of the hierarchy, then in your custom window's OnGUI method, use the code below;
[CustomEditor(typeof(NodeManager))]
public class NodeManager : EditorWindow
{
private static NodeManager window;
private Node[] m_nodes;
[MenuItem("Custom Windows/Node Inspector")]
public static void Init()
{
if(window == null)
window = GetWindow<NodeManager>("Node Manager", true, typeof(SceneView));
}
public void OnGUI()
{
m_nodes = GameObject.FindObjectsOfType<Node>();
foreach(Node node in m_nodes)
{
GUILayout.BeginHorizontal();
{
GUILayout.Label(node.name);
if (GUILayout.Button("Select"))
Selection.objects = new Object[] { node.gameObject };
}
GUILayout.EndHorizontal();
}
}
}
This adds a Button for each object in your custom window view, that will then select that object in the hierarchy.
Auto-Docking
I originally found the second response to this question, which goes into the details of parameters of the GetWindow method, and with this you can clearly see how to dock the window (I've converted it from JS to C# below).
(I looked fairly extensively in UnityEditor and UnityEditorInternal namespaces but couldn't find the Hierarchy or the Inspector).
GetWindow<T>(string title, bool focus, params System.Type[] desiredDockNextTo)
Which we can write for this example as;
EditorWindow.GetWindow<NodeInspector>("Node Test", true, typeof(SceneView));
This example docks the windows next to the SceneView window. This functionality can be combined with a custom inspector's OnInspectorGUI method, to automatically launch the custom node window, if it's not already open.
[CustomEditor(typeof(Node))]
public class NodeInspector : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
NodeManager.Init();
}
}
Sorry if this isn't what you are looking for, if it's not then please give more details and I will amend my answer to better suit the question.
Hope this helped.
Has a possibility, you can make a custom ScriptableObject and Custom Editor for It, and when open the node inspector, just find a instance of the scriptable object and use Selection.selectedObject = scriptableObject, and in the custom editor, make a static field called 'editor' to draw inside.
It will work.

Out of memory imageview

I'm developing an application with a menu which contains a list of buttons, when you click one of these buttons, another activity (the same activity with different image for each button) is opened showing an imageview. The problem is that when i click several times in different buttons (opening new images) the app crashes and i'm not able to solve it. Any help? Thanks.
That problem is because your are using a lot of images in your views and never clean the memory, then in one momento your don't have more memory for the new ones.
One form to resolve that problem is cleaning the memory always your destroy and activity.
You can override the next method in your activity for clean the memory.
#Override
public void unbindDrawables(View view) {
if (view.getBackground() != null) {
view.getBackground().setCallback(null);
}
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
unbindDrawables(((ViewGroup) view).getChildAt(i));
}
((ViewGroup) view).removeAllViews();
}
}
that method review a view, in your case those views will be your ImageView and ImageButton.
Finally you need call this method in the method onDestroy() (need override that method too).

Rewiring actions of parent to a child viewmodel

So here's my screnario. I have a toolbar at the top (office style), with buttons. This is hosted in a shell. Some of those buttons are applicable only to certain child view models as they get loaded. Ideally what I would like to happen is have the buttons action.target repositioned to child view model as it gets created (I kind of got this working by settings Action.Target="ActiveItem" on them. This doesn't solve the problem fully though:
a) When the child viewmodel is closed and there is no active item, I want them to reposition to Shell as the target so they can be set to "default" state.
b) I noticed that when child viewmodel is closed and the shell being the conductor has it ActiveItem=null, the hooks from the action are still bound to the living instance of the last viewmodel, so doesn't looks like it got disposed of. Memory leak?
Any suggestions how to implement this scenario?
What about adding a property to your ShellViewModel which points to the action target and updating it when stuff gets activated/deactivated:
e.g.
public class ShellViewModel
{
public object ActionTarget
{
get { return _actionTarget; }
set
{
_actionTarget = value;
NotifyOfPropertyChange(() => ActionTarget);
}
}
// Then when the active item changes just update the target:
public override NotifyOfPropertyChange(string propertyName)
{
if(propertyName == "ActiveItem")
{
if(ActiveItem == null) ActionTarget = this;
else ActionTarget = ActiveItem;
}
}
}
Now bind to that:
<SomeMenu cal:Action.Target="{Binding ActionTarget}" />
Not sure if that will work or not but I'm sure I've done something similar in the past. (You may also have to explicitly call NPC on your actions before they will update after you have changed ActiveItem)

Resources