JavaFX MenuItem display bug - javafx

My first question here so I hope i can describe my problem correct.
What im facing right now is that i want to display a contextmenu for some entries of a JFXTreeTableView. Therefore i created a new cellFactory called "ProjectTreeItemWithContextMenuTreeTableFactory" which handles the creation of the contextMenu based on mouseReleasedEvent and displaying it.
Due to i dont have 10 reputations i cant post images but as an example what isnt working i try to describe it. If i open the contextmenu it will get displayed at the correct position. When hovering over a menu entry the menuItems will get displayed, but not rendered right next to the menu.
There can be some times a huge gab between the menuItems and the menu whic hwas hovered....
What i noticed is, that this problem will only occur when hovering for the first time over the menu. If hovering for the second time over the menu while the contextMenu stays open, everything will get displayed correct.
private class TreeTableCallback extends TreeTableCell<T, ProjectTreeParentItemFX> {
#Override
protected void updateItem(ProjectTreeParentItemFX item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
setGraphic(null);
setContextMenu(null);
} else {
this.setOnMouseReleased(evt -> handleMouseReleased(evt, item));
setText(item.getDisplayText());
}
}
Adding menus and menuItems to the contextMenu and showing the menu.
private void handleMouseReleased(MouseEvent evt, ProjectTreeParentItemFX item) {
if (evt.getButton().equals(MouseButton.SECONDARY)) {
setContentOfContextMenuBasedOnType(item);
contextMenu.show(getTreeTableRow(), evt.getScreenX(), evt.getScreenY());
}
}

Related

How to move search icon of search bar at right hand side in xamarin forms

How to move search icon of search bar at right hand side in xamarin forms.
I am looking for android and IOS.
For Android I used SearchBarRenderer With below code which does not worked
Anyone know how to do it?Please help.
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
Control.LayoutParameters=(new ActionBar.LayoutParams(GravityFlags.Right));
}
In android, with a custom renderer, you can use the following code to place the search icon at the right side of your search bar:
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
var searchView = base.Control as SearchView;
//Get the Id for your search icon
int searchIconId = Context.Resources.GetIdentifier("android:id/search_mag_icon", null, null);
ImageView searchViewIcon = (ImageView)searchView.FindViewById<ImageView>(searchIconId);
ViewGroup linearLayoutSearchView = (ViewGroup)searchViewIcon.Parent;
searchViewIcon.SetAdjustViewBounds(true);
//Remove the search icon from the view group and add it once again to place it at the end of the view group elements
linearLayoutSearchView.RemoveView(searchViewIcon);
linearLayoutSearchView.AddView(searchViewIcon);
}
}
In the above implementation, I simply removed the search icon from the search bar view group and then added it again to the same view group. This placed the normally first child to the last child, thus placing the search icon at the end.

Prevent a toggle group from not having a toggle selected - Java FX

I have a toggle group with two toggle buttons that should look like this (Yellow toggle is the selected toggle).
However when I click on the selected toggle both toggles become unselected and look like this.
Then if I try to get whether the toggle is selected, I get a nullPointerException.
(Boolean) toggleGroup.getSelectedToggle().getUserData();
Is it possible to prevent the selected toggle from being unselected when it is clicked?
This one works for me. If the new selected element is null that means theres no selected element, therefore just select the previous one (which is the "oldValue")
toggleGroup.selectedToggleProperty().addListener((obsVal, oldVal, newVal) -> {
if (newVal == null)
oldVal.setSelected(true);
});
You can try the following code to create a persistent toggle.
/**
* Create a toggle group of buttons where one toggle will always remain switched on.
*/
class PersistentButtonToggleGroup extends ToggleGroup {
PersistentButtonToggleGroup() {
super();
getToggles().addListener(new ListChangeListener<Toggle>() {
#Override public void onChanged(Change<? extends Toggle> c) {
while (c.next()) {
for (final Toggle addedToggle : c.getAddedSubList()) {
((ToggleButton) addedToggle).addEventFilter(MouseEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent mouseEvent) {
if (addedToggle.equals(getSelectedToggle())) mouseEvent.consume();
}
});
}
}
}
});
}
}
This just reacts to mouse events, so perhaps not ideal if you want to account for keyboard events or changing toggles in code.
A similar, but perhaps more complete approach that I haven't tried may be defined in the blog entry Button of Choice: Use ToggleButtons as RadioButtons.
Perhaps the simplest behavior to accomplish what you desire might be to just use RadioButtons instead of ToggleButtons.
If, additionally, you want the buttons styled like ToggleButtons, instead of RadioButtons, then you can try the styling technique which is outlined in: How to make a RadioButton look like regular Button in JavaFX.
RadioButton radioButton=new RadioButton("Radio");
radioButton.getStyleClass().remove("radio-button");
radioButton.getStyleClass().add("toggle-button");

Javafx : TreeTableView refresh after updateItem

I have a TreeTableView and I have a custom TreeTableCell in which I override the updateItem method in order to render my cells(set disabled or enabled) depending on some condition. The problem is if I do some scroll, the table doesn't refresh, and as you can see on the attached image some cells become disabled even if they don't satisfy the condition. After heavy scrolling all cells become disabled(grayed out). I tried two things to solve the problem:
add some event listeners to refresh the table "manually" like:
treeTable.addEventFilter(ScrollEvent.ANY, event -> treeTable.refresh());
the rendering problem disappears, but if I do a little heavier scrolling, it becomes so laggy like if the application runs on 10-15 fps because the refreshing event triggers too frequently.
The other thing that I have tried is to make a timer(java.util.Timer) to trigger the refresh for example in only every 50 milliseconds, while scrolling. Then the lag disappears but there is a delay on rendering the cells, so you can observe the change of the cell color from gray to white.
If i choose smaller time interval it becomes laggy, and i could't find a balance between the lag and delay, and I also think both of my solutions are just workarounds, not real solutions for the problem.
Do you have any other idea to solve this problem?
The attached image : TableCells
#Override
public void updateItem(Boolean item, boolean empty) {
MyCustomRow row = getTreeTableRow().getItem();
if (row != null && row.isCondition()) {
editableProperty().set(false);
super.updateItem(item, empty);
}
}
Your updateItem method must:
Always call super.updateItem(), and
Update the state of the cell so that it is consistent for any possible values of item and empty
(see the Cell documentation.)
In your code, if the cell is used for a row where isCondition returns true, and then subsequently reused for a row where isCondition returns false, you don't revert the editable property to true. (So, eventually, all cells can be changed to non-editable, but can never be changed back to editable.)
You should do something like
#Override
public void updateItem(Boolean item, boolean empty) {
super.updateItem(item, empty);
MyCustomRow row = getTreeTableRow().getItem();
if (row != null && row.isCondition()) {
setEditable(false);
} else {
setEditable(true);
}
}

Change css for a new row added in TableView Javafx

I'm sorry for mistake I'm french.
So I have a tableView empty. I have a button "Add" when on click added row in a tableView. And when I select an row in my tableView, a new button "Cancel" show.
And when I click on a button "Cancel", the row's css change on my row selected (added a class css ".cancel").
The problem is that I click on button "Cancel", and after I click in the button "Add", the css ".cancel" is applicated at an other row while I don't clicked in the button "Add".
I think that there is a problem in index row.
In my method initialize :
articleTable.setRowFactory(param -> new TableRow<LigneTicket>() {
#Override
protected void updateItem(LigneTicket paramT, boolean empty) {
super.updateItem(paramT, empty);
if (!isEmpty() && paramT != null && paramT.getArticle().isArticleCanceled()) {
getStyleClass().add("cancel");
}
}
});
my code on button "Cancel" :
public void cancelLigneTicket() {
int indexSelected = articleTable.getSelectionModel().getSelectedIndex();
articleTable.getItems().get(indexSelected).getArticle().setArticleAnnuler(true);
articleTable.getSelectionModel().clearSelection();
List<LigneTicket> items = new ArrayList<>(articleTable.getItems());
articleTable.getItems().setAll(items);
buttonAnnulArt.setVisible(false);
Help !!
Thanks.
TableRows are used to display the table items. That doesn't mean however, that it will be used with only one item.
This can result in the following sequence of events for a row r:
The item of r is updated to a canceled item and thus the cancel CSS class is added.
The item of r is updated to a non-canceled item, but the cancel CSS class is not removed.
You need to remove the class again. Furthermore with your code the style class could be added multiple times leading to unnecessary memory consumption.
boolean canceled = !empty && paramT != null && paramT.getArticle().isArticleCanceled());
if (canceled) {
if (!getStyleClass().contains("cancel"))
getStyleClass().add("cancel");
} else {
getStyleClass().remove("cancel");
}
or using PseudoClass:
private static final PseudoClass CANCELED = PseudoClass.getPseudoClass("cancel");
...
pseudoClassStateChanged(CANCELED, !empty && paramT != null && paramT.getArticle().isArticleCanceled());
Furthermore you should prefer the TableView.refresh (available in JavaFX >= 8u60) method to refresh the cell items instead of copying the list and setting the items.

JavaFX TreeView: remove expand / collapse button (disclosure node) & functionality

I want to have a TreeView that has all of its children permanently expanded, and I don't want the user to be able to expand or collapse any of the children.
To do this I've found that I need to do the following:
Remove icon with CSS (Done)
Change expand and collapse image TreeView JavaFX 2.2
[edit] Above link should be used to change image; to remove completely, use this solution: https://stackoverflow.com/a/27831191/4430591
Remove double click functionality (Done)
Disable TreeItem's default expand/collapse on double click JavaFX 2.2
[edit] Remove ability to collapse / expand using keyboard arrrow keys (Done)
Given in José Pereda's solution below ( https://stackoverflow.com/a/27831085/4430591 )
[edit] Remove ability to right click for a ContextMenu (Done)
Given in José Pereda's solution below ( https://stackoverflow.com/a/27831085/4430591 )
Remove icon's clickablity (How do I do this?)
[edit] solution: https://stackoverflow.com/a/27831191/4430591
Even though the icon is no longer visible, it's still clickable. I don't see any way of filtering this; I only see ways to be able to respond to it after the fact.
Also, if I'm missing anything else that I need to do to ensure this functionality, please let me know.
I feel quite silly. I think this was mostly just a matter of not knowing what that darn arrow was called. Apparently it's a disclosureNode? Maybe that's common knowledge.
In the custom defined TreeCell, all I did was add this line in the updateItem method:
setDisclosureNode(null);
The solution to avoid modifying the skin or the default behavior is more simple if we trap the clicks before they are dispatched, and consume the right ones.
For that we can use an EventDispatcher, to filter both the mouse pressed and the right click over the arrows, which are StackPane nodes:
class CellEventDispatcher implements EventDispatcher {
private final EventDispatcher original;
public CellEventDispatcher(EventDispatcher original) {
this.original = original;
}
#Override
public Event dispatchEvent(Event event, EventDispatchChain tail) {
if (event.getEventType().equals(MouseEvent.MOUSE_PRESSED) ||
event.getEventType().equals(ContextMenuEvent.ANY)){
event.consume();
}
if(event instanceof KeyEvent && event.getEventType().equals(KeyEvent.KEY_PRESSED)){
if((((KeyEvent)event).getCode().equals(KeyCode.LEFT) ||
((KeyEvent)event).getCode().equals(KeyCode.RIGHT))){
event.consume();
}
}
return original.dispatchEvent(event, tail);
}
}
Now we apply our custom dispatcher to the tree view:
#Override
public void start(Stage primaryStage) {
TreeView<String> tree = new TreeView<>();
...
EventDispatcher treeOriginal = tree.getEventDispatcher();
tree.setEventDispatcher(new CellEventDispatcher(treeOriginal));
Scene scene = new Scene(tree);
primaryStage.setScene(scene);
primaryStage.show();
}
This will consume any click (left or right) over the arrows on the tree.
EDIT
Added to the event dispatcher class the case where the user uses the keyboard to traverse the tree view, consuming the collapse/expand events with arrow LEFT or RIGHT.

Resources