When I type something in AutoCompleteTextField it shows me a drop-down list with suggestions based on my input. If there is too much items a scroll bar appears on the right of the drop-down list. But the scroll only works on Windows desktop and only by using a mouse wheel. On mobile touch devices (android, iphone) AutoCompleteTextField always reacts as if I select an item (touch) from the drop-down list, not scroll (slide): the moment I touch the drop-down list and start sliding it up or down - it closes, and if my finger was pointing to an item the control selects it. The same thing happens when I try to move the scroll bar with mouse pointer on desktop (Windows and macOS).
The code is trivial:
#FXML
private AutoCompleteTextField<String> field;
...
field.setCompleter(s -> {
List<String> res = new ArrayList<>();
for (int i=0; i<items.size(); i++) {
if (items.get(i).startsWith(s)) {
res.add(String.valueOf(i));
}
}
return res;
});
No ResultNodeFactory is provided, so the drop-down list is populated with Labels by default. Same happens when providing a custom ResultNodeFactory.
Is it a bug or am I missing something?
Related
I have an app where, when the user is typing in a text input, typing a normal letter causes the menu bar to activate (drop down its sub-menu) instead of filling the input as it should.
The easiest way to see this issue is to grab SceneBuilder, drop down a panel and an area chart and start typing into the Title field. I typed "The", and the "e" caused the "Edit" menu to drop down as shown.
It doesn't always happen, and it goes away if you Alt your way out of the menu bar, so I presume it's some kind of MenuBar state issue.
I'm wondering how to make the MenuBar respect the input's sovereignty and if there is a fix, why does it behave this way under SceneBuilder?
Currently using SceneBuilder v18 on Windows, though I've seen this going back to v12 or v13. Always on Windows.
EDIT: Going on #Slaw's suggestion, I think the real issue is that once the Menu bar is activated with an Alt, it never deactivates until you press Alt again. So, you can hit Alt, give various inputs the focus and type into them, drag and drop new controls...basically do anything all while the Menu Bar is waiting to eat the keystroke.
The desired behavior is for either the menu bar to only activate WHILE Alt is being pressed or for it to give up the focus if the next key doesn't activate. Not to lie in wait, letting all keystrokes pass by until it can pounce on one.
When the stage regains focus, send an Esc key press event to the menu bar. You'll need to change up the variable names in the code below to match those from your own code base.
// After the app loses focus, when the user switches back using Alt+Tab,
// the menu is engaged on Windows. Simulate an ESC keypress to the menu
// to disable the menu, giving focus back to the application proper.
//
// JavaFX Bug: https://bugs.openjdk.java.net/browse/JDK-8090647
stage.focusedProperty().addListener( ( c, lost, found ) -> {
if( found ) {
mMainScene.getMenuBar().fireEvent( keyDown( ESCAPE, false ) );
}
} );
public static Event keyDown( final KeyCode code, final boolean shift ) {
return keyEvent( KEY_PRESSED, code, shift );
}
private static Event keyEvent(
final EventType<KeyEvent> type, final KeyCode code, final boolean shift ) {
return new KeyEvent(
type, "", "", code, shift, false, false, false
);
}
Tested on Windows 10, Java 19, and JavaFX 19.
I'm working with Android TV for the first time and I'm learning to use Leanback by modifying the example tv app that is provided.
The issue I'm having is that when I press left on the first item in the lists the navigation drawer opens and focus goes to the headers in the navigation drawer. When this happens, the info_field view in the ImageCardViews collapse behind the image.
What happens: The info field on the ImageCardView hides when I open the navigation drawer.
What I want to Happen: The info field remains visible when I open the navigation drawer.
I'm sure there's a way to do this because I've seen it in some Android TV apps, like Twitch. What's the best way to have the info_field visible when the navigation drawer is open?
I've worked out how to do it. In the CardPresenter, in onCreateViewHolder, when creating the ImageCardView I've overridden the BaseCardView method, setActivated(boolean activated) to always pass 'true' into it's super. And then call setActivated so that it's activated from the beginning. Like this:
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent) {
ImageCardView cardView = new ImageCardView(parent.getContext()) {
#Override
public void setActivated(boolean activated) {
super.setActivated(true);
}
#Override
public void setSelected(boolean selected) {
updateCardBackgroundColor(this, selected);
super.setSelected(selected);
}
};
cardView.setActivated(true);
cardView.setFocusable(true);
cardView.setFocusableInTouchMode(true);
return new ViewHolder(cardView)
}
So that did the trick for me. The ImageCardView never collapses.
I think if you look at this SO post you'll get most of the way there. The info view hides due to what leanback calls "expanding".
Try just calling enableMainFragmentScaling(false); in your BrowseFragment and see if that does what you want. If it doesn't feel like exactly what you want, refer to the post I linked to.
Additionally, if you've tried what I recommend in the linked SO post, you could also call the API on the BaseCardView setInfoVisibility() and pass it CARD_REGION_VISIBLE_ALWAYS. This just requires calling on a reference to your card which shouldn't need an override of the Presenter or Card.
I'm working in flex and I made a custom drop down where there are check boxes to allow the user to select multiple options. I used this template.
However this does not have scrolling because if you allow scrolling for some reason the checkboxes start to mess up. For instance if you have options 1 to 8 and only 1 to 5 are shown. You select option 1 and then scroll down to select option 7. When you scroll up the checkboxes start to switch around like option 3 all of a sudden is showing selected. Keep scrolling up and down and the checkbox selection just changes on it's own. I think this is a rendering issue and the actual selection data isn't changed at all (it knows only option 1 and option 7 were selected). Any ideas on how to fix this?
public function onOpen(event:DropDownEvent):void
{//load the checkboxes and set the mouse tracker
activateAllCheckBoxes();
this.scroller.verticalScrollBar.addEventListener(Event.CHANGE, list_verticalScrollBar_change);
callLater(observeMouse);
}
private function list_verticalScrollBar_change(evt:Event):void
{
//currentlySelectedCheckBoxes = selectedCheckboxes;
UpdateCheckBoxesWhenScrolling();
selectedIndex = -1;
}
protected function UpdateCheckBoxesWhenScrolling():void
{
for (var c:int = 0; c < dataGroup.numElements; c++) {
var obj:DropDownCheckBox = dataGroup.getElementAt(c) as DropDownCheckBox;
if(obj!=null)
{
var judgDebtorFromCheckBox:JudgDebtor = (obj.data) as JudgDebtor;
if(FindInCurrentList(judgDebtorFromCheckBox.JudgmentDebtorId)>0)
{
obj.checkbox.selected = true;
}
else
{
obj.checkbox.selected = false;
}
}
}
}
private function FindInCurrentList(ID:int):int
{
for(var i:int=0;i<currentlySelectedCheckBoxes.length;i++)
{
var JD:JudgDebtor = currentlySelectedCheckBoxes.getItemAt(i) as JudgDebtor;
if(JD.JudgmentDebtorId == ID)
return 1;
}
return -1;
}
So above code I register a scroll event listener on the drop down. It will update the drop down entries which has a check box and it uses an array collection called: currentlySelectedCheckBoxes. I debug the UpdateCheckBoxesWhenScrolling function and it's working fine, in other words it will check off the ones selected but for some reason it still is showing the wrong results for instance 11 entries in the list and only the second one is selected I scroll down and I can't see the the second entry but all of a sudden the last entry is showing that it's checked off.
This happens because the drop down list reuses the renderers when you scroll. For example if you have checked 1st item and scroll, the renderer for that is reused to display the item that becomes visible when you scroll. So the last item shows as checked. To avoid messing up the selection, you will have to do the following in the renderer that you are using
override public function set data(value:Object):void
{
super.data = value;
//inspect the property which indicates whether to select the checkbox or not
//and set the value of selected property accordingly
}
Hope this helps
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).
I have a Datagrid filled with a table. Now the vertical scrollbar shows up because the table doesn't fit. That's fine so far. Now in the last column I have defined a Button in the xaml file. All these buttons have the same callback, but I can distinguish from the selectedIndex of the table what this callback should do. Because clicking the button automatically also selects the line in the DataGrid where this button lives. That's fine so far. Now in my app, for some rows I want to disable the Button, because it has no meaning for that specific row. So what I did is take a subscription on event Load of each Button and let the callback set the MaxWidth = 0, if the button has no meaning. This works fine too, but only initially. As soon as I start dragging the scrollbar, at random places in the Button column buttons show up, or wrong buttons get MaxWidth = 0. I have the strong feeling that cells that scrolled out at the top are being reused at the bottom, but I don't get an event, or at least I don't know which event I should subscribe on. I don't know how to identify the scrollbar. Has anyone a suggestion to tackle this problem?
I finally found a solution to this problem myself, and I will post it for the record.
The event you should subscribe on is LoadingRow (generated by the DataGrid).
In the callback
void TableLoadingRow(object sender, DataGridRowEventArgs e)
you can identify an element in a cell by using VisualTreeHelper for instance as follows:
private void ButtonSetMaxWidth(DependencyObject reference, int maxWidth)
{
if (reference != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(reference); i++)
{
var child = VisualTreeHelper.GetChild(reference, i);
if (child.GetType() == typeof(Button))
{
Button b = (Button)child;
if (b.Name == "TheNameOfTheButtonInTheXAML")
{
b.MaxWidth = maxWidth;
return;
}
}
ButtonSetMaxWidth(child, maxWidth);
}
}
return;
}