I'm trying to make an autocomplete combobox in javafx and im almost done but every time i try to submit and clear selection so the user can choose another choice , all the items get hidden except the one he chose last time
// this the class that i used turn a normal combobox to an autocomplete one
public class AutoCompleteComboBoxListener<T> implements EventHandler<KeyEvent> {
private ComboBox<T> comboBox;
private ObservableList<T> data;
private boolean moveCaretToPos = false;
private int caretPos;
public AutoCompleteComboBoxListener(final ComboBox<T> comboBox) {
this.comboBox = comboBox;
data = comboBox.getItems();
this.comboBox.setEditable(true);
this.comboBox.setOnKeyReleased(AutoCompleteComboBoxListener.this);
this.showOnFocus();
}
#Override
public void handle(KeyEvent event) {
if(event.getCode() == KeyCode.UP) {
caretPos = -1;
moveCaret(comboBox.getEditor().getText().length());
return;
} else if(event.getCode() == KeyCode.DOWN) {
if(!comboBox.isShowing())
comboBox.show();
caretPos = -1;
moveCaret(comboBox.getEditor().getText().length());
return;
}
if (event.getCode() == KeyCode.RIGHT || event.getCode() == KeyCode.LEFT
|| event.isControlDown() || event.getCode() == KeyCode.HOME
|| event.getCode() == KeyCode.END || event.getCode() == KeyCode.TAB) {
return;
}
System.out.println(caretPos);
comboBox.hide();
if(event.getCode() == KeyCode.BACK_SPACE) {
moveCaretToPos = true;
caretPos = comboBox.getEditor().getCaretPosition();
} else if(event.getCode() == KeyCode.DELETE) {
moveCaretToPos = true;
caretPos = comboBox.getEditor().getCaretPosition();
}
ObservableList<T> list = FXCollections.observableArrayList();
for (int i=0; i<data.size(); i++) {
if(data.get(i).toString().toLowerCase().startsWith(
AutoCompleteComboBoxListener.this.comboBox
.getEditor().getText().toLowerCase())) {
list.add(data.get(i));
}
}
String t = comboBox.getEditor().getText();
comboBox.setItems(list);
comboBox.getEditor().setText(t);
if(!moveCaretToPos) {
caretPos = -1;
}
moveCaret(t.length());
if(!list.isEmpty()) {
comboBox.show();
String editorText;
editorText=comboBox.getEditor().getText();
list.sort((a, b) -> Integer.compare(a.toString().length(), b.toString().length()));
comboBox.getSelectionModel().selectFirst();
comboBox.getEditor().setText(editorText);
moveCaret(comboBox.getSelectionModel().getSelectedItem().toString().length());
}
if (event.getCode()==KeyCode.ENTER){
comboBox.hide();
comboBox.getEditor().setText(comboBox.getSelectionModel().getSelectedItem().toString());
}
}
private void moveCaret(int textLength) {
if(caretPos == -1)
comboBox.getEditor().positionCaret(textLength);
else
comboBox.getEditor().positionCaret(caretPos);
moveCaretToPos = false;
}
public void showOnFocus(){
this.comboBox.focusedProperty().addListener((obs, oldVal, newVal) ->
this.comboBox.show());
}
}
// and this is what the submit button does the the comboboxes
button.setOnAction(e-> {
combo1.getSelectionModel().clearSelection();
combo1.getSelectionModel().clearSelection();
});
Related
I have a Xamarin.Forms app with FreshMvvm, and I use secondary ToolbarItems. To do it in iOS, I had to make a custom renderer (unlike in Android). I was given a solution on how to implement it here:
ToolbarItems do not look right in iOS
This solution works perfectly for me. But by now, the toolbar menu grew longer, and some of its elements do not fit the iPhone's screen. I can slide the menu and see all the elements, but as soon as I release the screen, the view jumps back up, and while it is held by a finger, the elements are not clickable. How can this be solved? Can the menu made to wrap, or something else?
On Android, the menu stays where I scroll and I can click every item. Can it made stay where scrolled on iOS, too?
Here is my renderer's code:
using CoreGraphics;
using MobileApp.iOS.Renderers;
using MobileApp.iOS.Services;
using MobileApp.Pages;
using MobileApp.Services;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(CustomToolbarContentPage),
typeof(RightToolbarMenuCustomRenderer))]
namespace MobileApp.iOS.Renderers
{
class RightToolbarMenuCustomRenderer : PageRenderer
{
private List<ToolbarItem> _primaryItems;
private List<ToolbarItem> _secondaryItems;
private UITableView _table;
private UITapGestureRecognizer _tapGestureRecognizer;
private UIView _transparentView;
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
if (e.NewElement is IAddToolbarItem item)
{
item.ToolbarItemAdded += Item_ToolbarItemAdded;
}
base.OnElementChanged(e);
}
private void Item_ToolbarItemAdded(object sender, System.EventArgs e)
{
if (Element is ContentPage page)
{
_primaryItems = page.ToolbarItems.Where(i => i.Order == ToolbarItemOrder.Primary).ToList();
_secondaryItems = page.ToolbarItems.Where(i => i.Order == ToolbarItemOrder.Secondary).ToList();
_secondaryItems.ForEach(t => page.ToolbarItems.Remove(t));
}
var element = (ContentPage)Element;
if (_secondaryItems?.Count == 0 && element.ToolbarItems.Any(a => (a.IconImageSource as FileImageSource)?.File == "more.png"))
{
element.ToolbarItems.Clear();
}
else if (_secondaryItems?.Count >= 1 && !element.ToolbarItems.Any(a => (a.IconImageSource as FileImageSource)?.File == "more.png"))
{
element.ToolbarItems.Add(new ToolbarItem()
{
Order = ToolbarItemOrder.Primary,
IconImageSource = "more.png",
Priority = 1,
Command = new Command(ToggleDropDownMenuVisibility)
});
}
}
private void ToggleDropDownMenuVisibility()
{
if (!DoesTableExist())
{
if ((View?.Subviews != null)
&& (View.Subviews.Length > 0)
&& (View.Bounds != null)
&& (_secondaryItems != null)
&& (_secondaryItems.Count > 0))
{
_table = OpenDropDownMenu(Element as IAddToolbarItem);
Add(_table);
}
}
else
CloseDropDownMenu();
}
private bool DoesTableExist()
{
if (View?.Subviews != null)
{
foreach (var subview in View.Subviews)
{
if (_table != null && subview == _table)
{
return true;
}
}
}
if (_tapGestureRecognizer != null)
{
_transparentView?.RemoveGestureRecognizer(_tapGestureRecognizer);
_tapGestureRecognizer = null;
}
_table = null;
_tapGestureRecognizer = null;
return false;
}
private UITableView OpenDropDownMenu(IAddToolbarItem secondaryMenuSupport)
{
_transparentView = _transparentView = new UIView(new CGRect(0, 0, View.Bounds.Width, View.Bounds.Height))
{
BackgroundColor = UIColor.FromRGBA(0, 0, 0, 0)
};
_tapGestureRecognizer = new UITapGestureRecognizer(CloseDropDownMenu);
_transparentView.AddGestureRecognizer(_tapGestureRecognizer);
Add(_transparentView);
UITableView table = null;
if (_secondaryItems != null && _secondaryItems.Count > 0)
{
table = new UITableView(GetPositionForDropDownMenu(secondaryMenuSupport.RowHeight, secondaryMenuSupport.TableWidth))
{
Source = new TableSource(_secondaryItems, _transparentView),
ClipsToBounds = false
};
table.ScrollEnabled = true;
table.Layer.ShadowColor = secondaryMenuSupport.ShadowColor.ToCGColor();
table.Layer.ShadowOpacity = secondaryMenuSupport.ShadowOpacity;
table.Layer.ShadowRadius = secondaryMenuSupport.ShadowRadius;
table.Layer.ShadowOffset = new SizeF(secondaryMenuSupport.ShadowOffsetDimension, secondaryMenuSupport.ShadowOffsetDimension);
table.BackgroundColor = secondaryMenuSupport.MenuBackgroundColor.ToUIColor();
}
return table;
}
public override void ViewWillDisappear(bool animated)
{
CloseDropDownMenu();
base.ViewWillDisappear(animated);
}
private RectangleF GetPositionForDropDownMenu(float rowHeight, float tableWidth)
{
if ((View?.Bounds != null)
&& (_secondaryItems != null)
&& (_secondaryItems.Count > 0))
{
return new RectangleF(
(float)View.Bounds.Width - tableWidth,
0,
tableWidth,
_secondaryItems.Count() * rowHeight);
}
else
{
return new RectangleF(0.0f, 0.0f, 0.0f, 0.0f);
}
}
private void CloseDropDownMenu()
{
if (_table != null)
{
if (_tapGestureRecognizer != null)
{
_transparentView?.RemoveGestureRecognizer(_tapGestureRecognizer);
_tapGestureRecognizer = null;
}
if (View?.Subviews != null)
{
foreach (var subview in View.Subviews)
{
if (subview == _table)
{
_table.RemoveFromSuperview();
break;
}
}
if (_transparentView != null)
{
foreach (var subview in View.Subviews)
{
if (subview == _transparentView)
{
_transparentView.RemoveFromSuperview();
break;
}
}
}
}
_table = null;
_transparentView = null;
}
}
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
if (_table != null)
{
if (Element is IAddToolbarItem secondaryMenuSupport)
PositionExistingDropDownMenu(secondaryMenuSupport.RowHeight, secondaryMenuSupport.TableWidth);
}
}
private void PositionExistingDropDownMenu(float rowHeight, float tableWidth)
{
if ((View?.Bounds != null)
&& (_secondaryItems != null)
&& (_secondaryItems.Count > 0)
&& (_table != null))
{
_table.Frame = GetPositionForDropDownMenu(rowHeight, tableWidth);
}
}
}
}
ADDITION:
public class TableSource : UITableViewSource
{
List<ToolbarItem> _tableItems;
string[] _tableItemTexts;
string CellIdentifier = "TableCell";
UIView _tableSuperView = null;
public TableSource(List<ToolbarItem> items, UIView tableSuperView)
{
_tableItems = items;
_tableSuperView = tableSuperView;
_tableItemTexts = items.Select(a => a.Text).ToArray();
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return _tableItemTexts?.Length ?? 0;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell(CellIdentifier);
string item = _tableItemTexts[indexPath.Row];
if (cell == null)
{ cell = new UITableViewCell(UITableViewCellStyle.Default, CellIdentifier); }
cell.TextLabel.Text = item;
return cell;
}
public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
return 56;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
var command = _tableItems[indexPath.Row].Command;
command.Execute(_tableItems[indexPath.Row].CommandParameter);
tableView.DeselectRow(indexPath, true);
tableView.RemoveFromSuperview();
if (_tableSuperView != null)
{
_tableSuperView.RemoveFromSuperview();
}
}
}
public interface IAddToolbarItem
{
event EventHandler ToolbarItemAdded;
Color CellBackgroundColor { get; }
Color CellTextColor { get; }
Color MenuBackgroundColor { get; }
float RowHeight { get; }
Color ShadowColor { get; }
float ShadowOpacity { get; }
float ShadowRadius { get; }
float ShadowOffsetDimension { get; }
float TableWidth { get; }
}
Here you can download the project that reproduces the issue:
https://github.com/DavidShochet/Public
Well, I still can't reproduce the problem with your updated code. I don't if it is a solution and I just want to clarify my comment here.
In your code, you add the _table to the View:
_table = OpenDropDownMenu(Element as IAddToolbarItem);
Add(_table);
What I want you to have a try is add the _table to _transparentView :
_table = OpenDropDownMenu(Element as IAddToolbarItem);
//Add(_table);
_transparentView.Add(_table);
It would be better if you can provide us a Minimal, Reproducible Example so that I can debug it on my side.
Update:
I found the problem is here, you set the height of table _secondaryItems.Count() * rowHeight) which is longer then the view when the toolbar menu grew longer:
private RectangleF GetPositionForDropDownMenu(float rowHeight, float tableWidth)
{
if ((View?.Bounds != null)
&& (_secondaryItems != null)
&& (_secondaryItems.Count > 0))
{
return new RectangleF(
(float)View.Bounds.Width - tableWidth,
0,
tableWidth,
//here is the cause
_secondaryItems.Count() * rowHeight);
}
else
{
return new RectangleF(0.0f, 0.0f, 0.0f, 0.0f);
}
}
Solution: change the height of tablview to (float)View.Bounds.Height:
private RectangleF GetPositionForDropDownMenu(float rowHeight, float tableWidth)
{
if ((View?.Bounds != null)
&& (_secondaryItems != null)
&& (_secondaryItems.Count > 0))
{
return new RectangleF(
(float)View.Bounds.Width - tableWidth,
0,
tableWidth,
(float)View.Bounds.Height);
}
else
{
return new RectangleF(0.0f, 0.0f, 0.0f, 0.0f);
}
}
I created a table with 3 columns. In middle column i have 3 checkboxes. When my window is initialize checkboxes are ticked if info from database is suitable. It works. User can unticked checkbox what changing informations in database. My problem is when I verify did checkbox are selected one time returns true, one time returns false but the checkboxes is in the same state (selected or not).
public CheckBox podglad2, edycja2, dodawanie2, usuwanie2, importowanie2, eksportowanie2, nadawanie2;
private static void setAccessLabelStyle2(CheckBox label, AccessLevel level, Integer value) {
if (check(level, value)) {
label.setSelected(true);
} else {
label.setSelected(false);
}
}
private static boolean check(AccessLevel accessLevel, Integer value) {
return (accessLevel.getBit() & value) > 0;
}
public TableCell getFunctionCell2(TableCell cell, Integer accessLevel) {
HBox graphics = new HBox();
graphics.setAlignment(Pos.CENTER_LEFT);
graphics.setSpacing(7.0);
podglad2 = new CheckBox("P");
setAccessLabelStyle2(podglad2, AccessLevel.VIEW, accessLevel);
dodawanie2 = new CheckBox("D");
setAccessLabelStyle2(dodawanie2, AccessLevel.CREATE, accessLevel);
edycja2 = new CheckBox("E");
setAccessLabelStyle2(edycja2, AccessLevel.UPDATE, accessLevel);
}
accessLevelCol.setCellFactory(param -> {
return new TableCell<FunctionTableModel, Integer>() {
#Override
protected void updateItem(Integer item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
setStyle("");
} else {
getFunctionCell2(this, item);
podglad2.setOnAction(e -> {
FunctionTableModel row = getTableView().getItems().get(getIndex());
if (check(AccessLevel.VIEW, row.getAccessLevel())) {
if (podglad2.isSelected() == false) {
row.setAccessLevel(row.getAccessLevel() - AccessLevel.VIEW.getBit());
}
} else {
if (podglad2.isSelected() == true) {
row.setAccessLevel(row.getAccessLevel() + AccessLevel.VIEW.getBit());
}
}
});
dodawanie2.setOnAction(e -> {
FunctionTableModel row = getTableView().getItems().get(getIndex());
if (check(AccessLevel.CREATE, row.getAccessLevel())) {
if (dodawanie2.isSelected() == false) {
row.setAccessLevel(row.getAccessLevel() - AccessLevel.CREATE.getBit());
}
} else {
if (dodawanie2.isSelected() == true) {
row.setAccessLevel(row.getAccessLevel() + AccessLevel.CREATE.getBit());
}
}
});
edycja2.setOnAction(e -> {
FunctionTableModel row = getTableView().getItems().get(getIndex());
if (check(AccessLevel.UPDATE, row.getAccessLevel())) {
if (edycja2.isSelected() == false) {
row.setAccessLevel(row.getAccessLevel() - AccessLevel.UPDATE.getBit());
}
} else {
if (edycja2.isSelected() == true) {
row.setAccessLevel(row.getAccessLevel() + AccessLevel.UPDATE.getBit());
}
}
});
}
How can I solved this?
I am looking for the solution for light color background gradient animation. I have looked into other examples with KeyFrames and was unable to do it by myself.
So I made a primitive version of what I need:
boolean rbottomforward = true;
boolean gbottomforward = true;
boolean bbottomforward = true;
int redbottom = 171;
int greenbottom = 186;
int bluebottom = 171;
boolean rtopforward = true;
boolean gtopforward = true;
boolean btopforward = true;
int redtop = 255;
int greentop = 255;
int bluetop = 255;
#Override
protected Void call() throws Exception {
Timeline backgroundAnimator = new Timeline(new KeyFrame(Duration.millis(200), event -> {
backgroundPane.getStylesheets().clear();
backgroundPane.setStyle("-fx-background-color: linear-gradient(to top, "+ randomBottomColor()+", "+randomTopColor()+");");
}));
backgroundAnimator.setCycleCount(Timeline.INDEFINITE);
backgroundAnimator.play();
return null;
}
private String randomBottomColor() {
greenbottom = newBottomGreen();
redbottom = newBottomRed();
bluebottom = newBottomBlue();
return String.format("rgb(%d,%d,%d)", redbottom, greenbottom, bluebottom);
}
private int newBottomGreen() {
if(greenbottom <255 && greenbottom >155){
if(gbottomforward)
greenbottom +=getRandomNumber();
else
greenbottom -=getRandomNumber();
} else if(greenbottom >=255) {
gbottomforward=false;
greenbottom -=getRandomNumber();
} else {
gbottomforward=true;
greenbottom +=getRandomNumber();
}
return greenbottom;
}
private int getRandomNumber() {
int r = (int) (Math.random() * (3 - 1)) + 1;
return r;
}
private int newBottomRed() {
if(redbottom <255 && redbottom >155){
if(rbottomforward)
redbottom +=getRandomNumber();
else
redbottom -=getRandomNumber();
} else if(redbottom >=255) {
rbottomforward=false;
redbottom -=getRandomNumber();
} else {
rbottomforward=true;
redbottom +=getRandomNumber();
}
return redbottom;
}
private int newBottomBlue() {
if(bluebottom <255 && bluebottom >155){
if(bbottomforward)
bluebottom +=getRandomNumber();
else
bluebottom -=getRandomNumber();
} else if(bluebottom >=255) {
bbottomforward=false;
bluebottom -=getRandomNumber();
} else{
bbottomforward=true;
bluebottom +=getRandomNumber();
}
return bluebottom;
}
private String randomTopColor() {
greentop = newTopGreen();
redtop = newTopRed();
bluetop = newTopBlue();
return String.format("rgb(%d,%d,%d)", redtop, greentop, bluetop);
}
private int newTopGreen() {
if(greentop <255 && greentop >155){
if(gtopforward)
greentop +=getRandomNumber();
else
greentop -=getRandomNumber();
} else if(greentop >=255) {
gtopforward=false;
greentop -=getRandomNumber();
} else {
gtopforward=true;
greentop +=getRandomNumber();
}
return greentop;
}
private int newTopRed() {
if(redtop <255 && redtop >155){
if(rtopforward)
redtop +=getRandomNumber();
else
redtop -=getRandomNumber();
} else if(redtop >=255) {
rtopforward=false;
redtop -=getRandomNumber();
} else {
rtopforward=true;
redtop +=getRandomNumber();
}
return redtop;
}
private int newTopBlue() {
if(bluetop <255 && bluetop >155){
if(btopforward)
bluetop +=getRandomNumber();
else
bluetop -=getRandomNumber();
} else if(bluetop >=255) {
btopforward=false;
bluetop -=getRandomNumber();
} else{
btopforward=true;
bluetop +=getRandomNumber();
}
return bluetop;
}
This is a bit overkill. Can anyone help me convert this to a more advanced level code. Thanks :)
There's really not much you can do about this but reduce the repetition in code. (You won't be able to interpolate anything, since on every update the next color is chosen at random.)
You should use the same code for all the color channels:
/**
* Class containing logic for a single color channel.
*/
private class AnimatedChannel {
private boolean increment = true;
private int value;
AnimatedChannel(int value) {
this.value = value;
}
/**
* Changes channel by random amount in [1, 3] keeping it in range [155, 255]
*/
private void update() {
int delta = getRandomNumber();
if (increment) {
value += delta;
if (value > 0xFF) {
value = (2 * 0xFF) - value; // v = max - (v - max)
increment = false;
}
} else {
value -= delta;
if (value < 155) {
value = (2 * 155) - value; // v = min + (min - v)
increment = true;
}
}
}
}
private final Random random = new Random();
private int getRandomNumber() {
return random.nextInt(3 - 1) + 1;
}
private final AnimatedChannel bottomRed = new AnimatedChannel(171);
private final AnimatedChannel bottomGreen = new AnimatedChannel(186);
private final AnimatedChannel bottomBlue = new AnimatedChannel(171);
private final AnimatedChannel topRed = new AnimatedChannel(0xFF);
private final AnimatedChannel topGreen = new AnimatedChannel(0xFF);
private final AnimatedChannel topBlue = new AnimatedChannel(0xFF);
private final AnimatedChannel[] channels = new AnimatedChannel[] {
bottomRed,
bottomGreen,
bottomBlue,
topRed,
topGreen,
topBlue
};
#Override
protected Void call() throws Exception {
Timeline backgroundAnimator = new Timeline(new KeyFrame(Duration.millis(200), event -> {
for (AnimatedChannel channel : channels) {
channel.update();
}
backgroundPane.setBackground(new Background(new BackgroundFill(
new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE,
new Stop(0, channelsToColor(topRed, topGreen, topBlue)),
new Stop(1, channelsToColor(bottomRed, bottomGreen, bottomBlue))),
CornerRadii.EMPTY,
Insets.EMPTY)));
}));
backgroundAnimator.setCycleCount(Timeline.INDEFINITE);
backgroundAnimator.play();
return null;
}
private static Color channelsToColor(AnimatedChannel red, AnimatedChannel green, AnimatedChannel blue) {
return Color.rgb(red.value, green.value, blue.value);
}
This code is not that much shorter than your code, but it's easier to maintain. If you want to modify the logic for updating the channels, you only need to adjust 1 method instead of 6 methods. Also it relieves JavaFX of the burden of parsing the inline CSS on every update.
Note:
You seem to be extending Task<Void> or some similar concurrency-related class. This is not really necessary, since Timeline.play is not a long running operation but simply triggers repeated execution of logic (in this case the EventHandler<ActionEvent>) on the application thread at a later time.
I have a program that searches an observable list and displays all of the matching cases on the table. The search works fine, but I am only able to run this part of the program once. The search button stops responding after the program has returned to displaying the full observable list.
I have a separate class(Search.class) that handles all of the logic for searching the observable list.
The code for the search button and text field are below:
partSearchBtn.setOnAction(searchPartEvent ->{
ObservableList<Part> searchPartDisplay = FXCollections.observableArrayList();
String searchQuery = partSearchField.getText();
try{
searchPartDisplay = Search.searchPartByNumber(Integer.parseInt(searchQuery));
partTable.setItems(searchPartDisplay);
partSearchBtn.setText("Clear");
partSearchBtn.setOnAction(clearSearchEvent ->{
partSearchBtn.setText("Search");
partTable.setItems(Inventory.partBin);
});
} catch(NumberFormatException hasText){
searchPartDisplay = Search.searchPartByText(searchQuery);
partTable.setItems(searchPartDisplay);
partSearchBtn.setText("Clear");
partSearchBtn.setOnAction(clearSearchEvent ->{
partSearchBtn.setText("Search");
partTable.setItems(Inventory.partBin);
});
}
});
What changes would I need to make to re-run the search process?
Or should I turn this into a method as part of my Search class that I can reuse?
The search logic is below:
package inventorymngmnt;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class Search {
public static ObservableList<Part> searchPartByNumber(int inNum){
ObservableList<Part> searchBin = FXCollections.observableArrayList();
for(Part e: Inventory.partBin){
boolean typeCaseIn = (e.getClass() == Inhouse.class);
if(typeCaseIn == true){
Inhouse testIn = (Inhouse) e;
if(inNum == testIn.getMachineID())
searchBin.add(e);
}
if((inNum == e.getPartID()) || (inNum == e.getInstock()) || (inNum == e.getMax())
|| (inNum == e.getMin()) || ((double)inNum == e.getPrice())
|| (Integer.toString(inNum).contains(e.getName()))){
searchBin.add(e);
}
}
return searchBin;
}
public static ObservableList<Part> searchPartByText(String inString){
ObservableList<Part> searchBin = FXCollections.observableArrayList();
for(Part e: Inventory.partBin){
boolean typeCaseOut = (e.getClass() == Outsourced.class);
if(typeCaseOut == true){
Outsourced testOut = (Outsourced) e;
if(inString.equals(testOut.getCompanyName())){
searchBin.add(e);
}
}
if(inString.equals(e.getName())){
searchBin.add(e);
}
}
return searchBin;
}
public static ObservableList<Part> searchProdByNumber(int inNum){
ObservableList<Part> searchProd = FXCollections.observableArrayList();
for(Part e: Inventory.partBin){
boolean typeCaseIn = (e.getClass() == Inhouse.class);
if(typeCaseIn == true){
Inhouse testIn = (Inhouse) e;
if(inNum == testIn.getMachineID())
searchProd.add(e);
}
if((inNum == e.getPartID()) || (inNum == e.getInstock()) || (inNum == e.getMax())
|| (inNum == e.getMin()) || ((double)inNum == e.getPrice())
|| (Integer.toString(inNum).equals(e.getName()))){
searchProd.add(e);
}
}
return searchProd;
}
public static ObservableList<Part> searchProdByText(String inString){
ObservableList<Part> searchProd = FXCollections.observableArrayList();
for(Part e: Inventory.partBin){
boolean typeCaseOut = (e.getClass() == Outsourced.class);
if(typeCaseOut == true){
Outsourced testOut = (Outsourced) e;
if(inString.equals(testOut.getCompanyName())){
searchProd.add(e);
}
}
if(inString.equals(e.getName())){
searchProd.add(e);
}
}
return searchProd;
}
}
It doesn't work, because when you clear the search, the action on the button is still set to clear the search...
Consider a different strategy entirely. You can use a FilteredList as the list for the table. Then just toggle the predicate on the list:
Predicate<Part> noFilter = part -> true;
FilteredList<Part> filteredParts = new FilteredList<>(Inventory.partBin, noFilter);
partTable.setItems(filteredParts);
partSearchBtn.setOnAction(searchPartEvent -> {
if (filteredParts.getPredicate()==noFilter) {
String searchQuery = partSearchField.getText();
try {
int searchNumber = Integer.parseInt(searchQuery);
filteredParts.setPredicate(part -> Search.filterByNumber(part, searchNumber));
} catch (NumberFormatException exc) {
filteredParts.setPredicate(part -> Search.filterByText(part, searchQuery));
}
} else {
filteredParts.setPredicate(noFilter);
}
});
partSearchButton.textProperty().bind(Bindings
.when(filteredParts.predicateProperty().isEqualTo(noFilter))
.then("Search")
.otherwise("Clear"));
and
public class Search {
public static boolean filterByNumber(Part part, int number) {
if (part.getClass() == Inhouse.class) {
Inhouse testIn = (Inhouse) part ;
if (testIn.getMachineID() == number) {
return true ;
}
}
if((number == part.getPartID()) || (number == part.getInstock()) || (number == part.getMax())
|| ( number == part.getMin()) || ((double) number == part.getPrice())
|| (Integer.toString(number).contains(part.getName()))){
return true ;
}
return false ;
}
public static boolean filterByText(Part part, String text) {
//similarly...
}
}
I am stuck on a complex situation, when I am refreshing my adapter of recyclerview by notifyDataSetChanged, while it having focus on particular cell (with D-PAD), is being loss. After refresh focus is not showing
private void refreshedData() {
flag1 = true;
// new MyAsycTas().execute();
focusedElement();
// select();
runnable = new Runnable() {
#Override
public void run() {
Log.e(TAG, "Data refreshed starrt.......");
// isRefreshedData = true;
fetchXmlFromUrl = new FetchDataFromUrl(Demo2Activity.this, 0, Demo2Activity.this);
handler.removeCallbacks(runnable);
select();
handler.postDelayed(runnable, 9000);
}
};
// handler.postDelayed(runnable,
// Integer.valueOf(MyStaticClass.refreshTime) * 60000);
handler.postDelayed(runnable, 9000);
}
...
public void select() {
if (verticalListView != null) {
View view = verticalListView.getChildAt(vertical_position);
if (view != null) {
view = verticalListView.getChildAt(vertical_position);
recyclerView = (RecyclerView) view.findViewById(R.id.horizontal_recyclerview);
if (recyclerView != null) {
verticalListView.scrollToPosition(vertical_position);
((View) recyclerView.getChildAt(horizontal_position)).findViewById(R.id.cat_button_thumabnail)
.requestFocus();
} else {
LinearLayout linearLayout = (LinearLayout) view.findViewById(R.id.home_fragment_menu_container);
linearLayout.getChildAt(horizontal_position).requestFocus();
}
}
}
// refreshedData();
}
..
public void focusedElement() {
if (verticalListView != null) {
View view = verticalListView.getLayoutManager().getFocusedChild();
if (view != null) {
recyclerView = (RecyclerView) view.findViewById(R.id.horizontal_recyclerview);
if (recyclerView != null) {
vertical_position = (Integer) recyclerView.getTag();
horizontal_position = recyclerView.getChildAdapterPosition(recyclerView.getFocusedChild());
} else {
LinearLayout ll = (LinearLayout) view.findViewById(R.id.home_fragment_menu_container);
horizontal_position = ll.indexOfChild(ll.getFocusedChild());
}
}
}
}