JavaFX tooltip causes MouseOut - javafx

Simply put I only show buttons when I am hovered on the AnchorPane. I wanted a tooltip for a button, but when the mouse hovers on the tooltip this causes me to leave the anchorpane and everything disappears.
Any ideas? Using the stage for hovering to show or not doesn't seem to ever cause the buttons to hide.
//this is an AnchorPane
this.addEventHandler(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent event) {
//Doesn't help: if(!micTooltip.isShowing() && !screenTooltip.isShowing())
showButtons(false);
}
});
similarly the mouse entered shows the buttons. And a tooltip is bound to the buttons.

Try this:
ObservableBooleanValue hover = this.hoverProperty()
.or(micTooltip.getScene().getRoot().hoverProperty())
.or(screenTooltip.getScene().getRoot().hoverProperty());
hover.addListener((obs, wasHovering, isNowHovering) -> showButtons(isNowHovering));
Depending on the exact behavior you need, you might want
hover = this.hoverProperty().or(micTooltip.showingProperty()) ;
etc
You might also find it more convenient to use bindings instead of the listener:
this.getChildren().forEach(button -> button.visibleProperty().bind(hover));
(assuming you want all contents of the anchor pane to appear and disappear on mouseover/out; this line needs to be called after you add the content, obviously).

Related

Gluon AppBar keep in the view

I'm trying to build a message window with App Bar on the top
This screen consist of Gluon App Bar on the top and VBox in bottom which has rest of the element shown in the screen.
Issue is when i click on the text area to enter text the App Bar goes out of scope.
Is there a way I can set App Bar to be always on top?
If you are deploying your app on Android, the TextField and TextArea controls include a built-in check: when those input controls get focused, if required the scene is moved up to prevent the software keyboard from hiding the control.
These translation affects the whole scene, so all the nodes in it (View, VBox, TextField, TextArea, AppBar, ...), will be translated as well.
So if you want to keep the AppBar node always visible and in the same top position, a possible fix could be counteracting that translation whenever it happens.
If you have a BasicView for instance (Gluon IDE plugin -> single view project), with a TextField control at the bottom of the view:
public BasicView() {
Label label = new Label("Hello JavaFX World!");
Button button = new Button("Change the World!");
button.setGraphic(new Icon(MaterialDesignIcon.LANGUAGE));
button.setOnAction(e -> label.setText("Hello JavaFX Universe!"));
VBox controls = new VBox(15.0, label, button, new TextField());
controls.setAlignment(Pos.BOTTOM_CENTER);
controls.setPadding(new Insets(20));
setCenter(controls);
}
you can modify it like this:
public BasicView() {
...
setOnShown(e -> {
MobileApplication.getInstance().getAppBar().translateYProperty()
.bind(controls.getScene().getRoot().translateYProperty().multiply(-1));
});
}
Make sure that the view is already added to the scene when you add this binding (to prevent a NPE).
Now when the textfield gets the focus, the whole scene will be moved up, and the appBar will be moved down the same amount:

JavaFX - Combobox Expands Downward Off Screen (Post 8u60)

I thought this bug was supposed to be fixed a long time ago... but when I place a ComboBox near the bottom of a window it expands downward and off the screen. I think the reason it does this is because there are other controls above it, so rather than "bump" into those it just expands downward instead. Why doesn't the combo box expand over the the rest of the layout? All I know is that when I add some padding above it, it will expand upward instead of downward.
Example:
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
ObservableList<String> choiceList = FXCollections.observableArrayList();
choiceList.addAll("Choice1", "Choice2", "Choice3", "Choice4");
ComboBox<String> choices = new ComboBox<>(choiceList);
choices.setMinWidth(100);
Button button1 = new Button("First Button");
button1.setMinWidth(150);
Button button2 = new Button("Second Button");
button2.setMinWidth(150);
VBox layout = new VBox(10);
layout.setPadding(new Insets(10, 10, 10, 10));
layout.getChildren().addAll(button1, button2, choices);
Scene scene = new Scene(layout);
primaryStage.setScene(scene);
primaryStage.setTitle("Example");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Image of window displayed by the above code
Anybody got a fix for this?
Note, if in your case, you are moving your main application window to the bottom of the screen and the combo box is still dropping down and being cut off so that some contents of the popup are not visible, then it may well be a bug. But my guess is, that if that is what is happing, that it is a system specific issue as I cannot replicate such an issue on OS X. If that is the case, try a Java 9 early access release and see if the issue still replicates, and if it does you could file a bug report.
This is not bug, it is by design.
The ComboBox popup is internally implemented as a PopupControl. A PopupControl is a new window, which isn't constrained to lie within the bounds of its parent window (your main stage). JavaFX has logic to ensure that popups such as the ContextMenus and ComboBox popups are shown within the visible screen area, not the owning stage area.
If you move your main application towards the top of the screen, then open the combo box popup, the popup will drop down because there is room on the screen to display it. But if you move the main application towards the bottom of the screen, then the open the combo box popup, the popup will drop up (I don't know a better way to explain that concept ;-) because there is no room to display the popup if it were to drop down.
Drop up sample. Created by running your example code on OS X, moving the main application window near the bottom of the screen and opening the combo box popup.

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.

javafx setFocus after tabPaine change

Problem:
Have tabPane tabs OK.
In the first tab there is a text field. I am able to get focus on this field when starting the application.
After changing the tabs and coming back to the first tab I want focus to be on this textfield (barcodereader should be active in this field) without having to select the field with the mouse.
I am able to catch event from tabs with
tp.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>()
{ etc
(could not post with code)
and I am able to trigger en event for the first tab.
But field.requestFocus(); does not work. Probably because this method comes before rendering the textfield.
So here is my question:
How do you set focus on a control after clicking tabs in TabPane?
If you handle the mouse release event, it works: (The doFocus enables the requestFocus handling only when a tab selection changed before, otherwise it kicks in every time you click somewhere in the TabPane.)
final SimpleBooleanProperty doFocus = new SimpleBooleanProperty(false);
tabPane.setOnMouseReleased(new EventHandler<Event>() {
#Override
public void handle(Event event) {
if (!doFocus.get()) {
return;
}
doFocus.set(false);
switch (tabPane.selectionModelProperty().getValue().selectedIndexProperty().intValue()) {
case 0: tf1b.requestFocus(); break;
case 1: tf2a.requestFocus(); break;
default: break;
}
}
});
tabPane.selectionModelProperty().getValue().selectedIndexProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observable,
Number oldValue, Number newValue) {
doFocus.set(true);
}
});
When the TabPane has focus, one can change tab selection with the cursor keys and there the TextFields also won't get the focus with selection based approach. This probably should be handled too, if you need it.
(Recently I had a similar problem. I noticed, that the TabPane switches tabs immediately when you press the mouse button. My guess would be, that the selection based approach requests focus on the TextField right after mouse down, but the continued mouse down steals the focus back to the TabPane. Or maybe even the single mouse down event which changes selection causes the focus to go back to TabPane. However, my assumptions regarding the reasons may not be correct, as I am a newbie to JavaFX.)
EDIT: That handling certainly is not optimal. For instance, if you change tabs with the keys, the doFocus will be enabled and then clicking anywhere in the TabPane will trigger the requestFocus call. I thought this should be mentioned.
Also, take a look at my solution for setting focus on TextArea, when user changes selected tab(using mouse or keyboard) https://stackoverflow.com/a/19046535/2791746

Qt, how to make Tooltip visible without hovering over the control?

I want tooltips to be visible by default when the container widget gets focus/visible.
I want tooltip to appear without being mouse hover on the respective control.
You need to subclass the widget and override handler(s) for event(s) which should produce tooltip display. In the handler, create a QHelpEvent of type QEvent::ToolTip and enqueue it at the event loop. Finally call the parent's original handler, to let it do what was originally intended.
So specifically for getting focus on button, it would be
class MyButton : public QPushButton {
virtual void focusInEvent(QFocusEvent *) {
if(evt->gotFocus()) {
QPoint pos(0,0);
QHelpEvent* help = new QHelpEvent(
QEvent::ToolTip,pos,this->mapToGlobal(pos));
QCoreApplication::postEvent(this,help);
}
QPushButton::focusInEvent(evt);
}
}
For visibility you would override
void QWidget::showEvent(QShowEvent * event);
and do similar code. You need to adjust relative pos to your taste, because originally tooltip dependens on mouse position which you don't have here. Also keep very tight control over making your widgets focused and/or visible. By default, something gets focus all the time, so you will get tooltips all over the place.

Resources