Loop through multiple ComboBoxes to get data JavaFX - javafx

I am trying loop through all the ComboBoxinstances I made in order to get the value the user picks and add that value to a new ArrayList, but I am stuck on how to proceed making the loop to get the values.
// row for comboboxes
HBox numBox = new HBox();
numBox.setSpacing(16);
numBox.setAlignment(Pos.CENTER);
vbox.getChildren().add(numBox);
// setup loop to create 8 combo boxes for user to pick
int comboNum = 8;
ComboBox<Integer> binaryBox = new ComboBox<Integer>();
for (int i = 0; i < comboNum; i++) {
binaryBox = new ComboBox<Integer>();
List<Integer> binaryList = new ArrayList<Integer>();
binaryList.add(0);
binaryList.add(1);
for (Integer num : binaryList) {
binaryBox.getItems().addAll(num);
}
binaryBox.setValue(0);
numBox.getChildren().add(binaryBox);
}
// way to get the value from each combo box
ChangeListener<Number> update =
(ObservableValue <? extends Number> ov, Number oldValue, Number newValue) -> {
for (int i = 0; i < comboNum; i++){
//todo
}
};

Each ComboBox has a SelectionModel from which you can obtain the selectedItem. First, create a list of combo boxes and populate it with your instances of ComboBox<Integer>:
List<ComboBox<Integer>> list = new ArrayList<>();
for (int i = 0; i < comboNum; i++) {
ComboBox<Integer> binaryBox = new ComboBox<Integer>();
list.add(binaryBox);
…
}
Later, you can loop through the list to retrieve the selected items using getSelectedItem():
for (ComboBox<Integer> combo : list) {
System.out.println(combo.getSelectionModel().getSelectedItem());
}

Related

Binding JavaFx Label to a Function Output which Changes According to Three Nodes Property

I want to make a Label textProperty binds to a value from a function, which would take an array of Nodes (i.e., three Line Nodes), and then do some computation based on the Nodes' position property (i.e., startXProperty), so that whenever the positions of the Nodes are changed, the Label text will update accordingly.
This is my attempt:
Label label = new Label();
DoubleProperty myFunction(Line[] lines){
DoubleProperty property= new SimpleDoubleProperty();
// This is a sample computation, because the actual computation is much more complex.
// That's why I tried to avoid using the arithmetic methods provided by the Property class,
// i.e., property().add().multiply()
double computation = Math.sqrt(Math.pow(lines[0].startXProperty().getValue() - lines[1].startXProperty().getValue());
property.setValue(computation);
return property;
}
label.textProperty().bind(myFunction(lines).asString());
And this approach doesn't work. I am looking a way to fix this. Thanks!
UPDATE: Solved
Thanks to the answers provided in the comment, I changed the function to return a DoubleBinding and bind the label to it, and then it works!
Label label = new Label();
DoubleBinding myFunction(Line[] lines){
DoubleProperty line_StartX[] = new DoubleProperty[lines.length];
DoubleProperty line_EndX[] = new DoubleProperty[lines.length];
DoubleProperty line_StartY[] = new DoubleProperty[lines.length];
DoubleProperty line_EndY[] = new DoubleProperty[lines.length];
for (int i = 0; i < lines.length; i++) {
line_StartX[i] = lines[i].startXProperty();
line_EndX[i] = lines[i].endXProperty();
line_StartY[i] = lines[i].startYProperty();
line_EndY[i] = lines[i].endYProperty();
}
DoubleBinding distBinding = new DoubleBinding() {
{
for (int i=0; i<3; i++){
super.bind(line_StartX[i]);
super.bind(line_EndX[i]);
super.bind(line_StartY[i]);
super.bind(line_EndY[i]);
}
}
#Override
protected double computeValue() {
double a = Math.sqrt(Math.pow(lines_StartX[0].getValue() - lines_StartX[1].getValue(),2));
return a;
}
};
return distBinding;
}
label.textProperty().bind(myFunction(lines).asString());
It acts as expected now! Just one last question, when using super.bind(prop1, prop2, prop3), is there any easier way to add whole bunch of elements in an array at once?

observableList doesn't show rows in a loop for?

I have a problem where I am hanging out several days to display the lines in an observablelist in a loop! Yet the code function very well in console! Any help would be welcome.
private void showActivitiesDriver() throws IOException {
Path path = Paths.get("Download/Cards/F__100000015956101711071539.C1B");
byte[] data = Files.readAllBytes(path);
dataFileCard = new FileBlockTGD(data);
w = new WrapperActivityChangeInfo(dataFileCard.getDriver_activity_data()
.getActivityDailyRecords().get(i), dataFileCard.getDriver_activity_data()
.getActivityDailyRecords().get(i).getActivityChangeInfo().get(j));
for (i = 0; i < dataFileCard.getDriver_activity_data().getActivityDailyRecords().size(); i++) {
w.setTheDateTime(dataFileCard.getDriver_activity_data()
.getActivityDailyRecords().get(i).getActivityRecordDate().toString());
System.out.println(w.getTheDateTime());
dateActivitiesColumn.setCellValueFactory(cellData -> new SimpleStringProperty(
cellData.getValue().getTheDateTime()));
/*
dateActivitiesColumn.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(
DateUtil.parseDateToString(cellData.getValue().getActivityRecordDate())));
*/
for (j = 0; j < dataFileCard.getDriver_activity_data().getActivityDailyRecords().get(i).
getActivityChangeInfo().size(); j++) {
driverActivitiesColumn.setCellValueFactory(cellData -> new SimpleStringProperty(
cellData.getValue().getTheActivity()));
WrapperActivityChangeInfoList = FXCollections.observableArrayList();
WrapperActivityChangeInfoList.add(new WrapperActivityChangeInfo(dataFileCard.getDriver_activity_data()
.getActivityDailyRecords().get(i), dataFileCard.getDriver_activity_data()
.getActivityDailyRecords().get(i).getActivityChangeInfo().get(j)));
System.out.println(WrapperActivityChangeInfoList);
}
}
// Set data to tableview
activitiesDriverTableView.setItems(WrapperActivityChangeInfoList);
//System.out.println(WrapperActivityChangeInfoList.toString());
}
}
I expect to see all the lines, but just one, yet the code works nice in console.
You create a new ObservableList (initially empty) in every iteration of the inner loop. This way after the add invocation you've got a list containing a single list. One of those lists is assigned to the TableView in the end. Should see a sequence of dates followed by a number of WrapperActivityChangeInfo.toString results surrounded by [] in the output indicating that you're printing multiple lists.
Furthermore there is no point in assigning a cellValueFactory in every iteration of the loop.
You need to move the list creation outside of the loops.:
...
WrapperActivityChangeInfoList = FXCollections.observableArrayList();
driverActivitiesColumn.setCellValueFactory(cellData -> new SimpleStringProperty(
cellData.getValue().getTheActivity()));
for (i = 0; i < dataFileCard.getDriver_activity_data().getActivityDailyRecords().size(); i++) {
...
for (j = 0; j < dataFileCard.getDriver_activity_data().getActivityDailyRecords().get(i).
getActivityChangeInfo().size(); j++) {
WrapperActivityChangeInfoList.add(new WrapperActivityChangeInfo(dataFileCard.getDriver_activity_data()
.getActivityDailyRecords().get(i), dataFileCard.getDriver_activity_data()
.getActivityDailyRecords().get(i).getActivityChangeInfo().get(j)));
System.out.println(WrapperActivityChangeInfoList);
}
}
activitiesDriverTableView.setItems(WrapperActivityChangeInfoList);

Get random items from firebase min 3 max 5

I am trying to get random items from my firebase database and it almost works,
sometimes I only get one or two items when the minimum is 3 and max is 5.
Every item has an index and it's getting the items that startAt(startindex) and endAt(startIndex+randomNumber).
Is there any other way to do this other than using an index on each item in the database?
Here is how the code looks now:
randomNumber = getRandomInt(3,5);
listView = (ListView)view.findViewById(R.id.listView);
int startIndex = (int)(Math.random() * childs+1);
adapter = new FirebaseListAdapter<TraningData>(getActivity(),TraningData.class,R.layout.layout_traning_item,ref_1
.orderByChild("index")
.startAt(startIndex)
.endAt(startIndex+randomNumber)) {
#Override
protected void populateView(View view, final TraningData td, int i) {
//Populating over here!
}
};
listView.setAdapter(adapter);
Since Firebase never want to add this feature.
Here how I solved it by adding all to an array and then make a random selection.
ArrayList<TraningData> randomSelected = new ArrayList<>();
Random rand = new Random();
int numElements = getRandomInt(3,5);
for(int i = 0;i < numElements;i++){
int randomIndex = rand.nextInt(traningData.size());
randomSlected.add(traningData.get(randomIndex));
}
cAdapter = new CustomAdapter(getActivity(),randomSlected);
listView.setAdapter(cAdapter);

make a dynamic tableview javaFX editable

I'm trying to make editable a table view dynamic in javaFX, i already have the dynamic table loading values from a object and works perfect, but i can't make this editable.
i create the dinamic table with this
ArrayList<reportes> rs = BD.ConsultarVarios(selecionado);
for (int column = 1; column +1< rs.size(); column++) {
tablevarios.getColumns().add(
createColumn(column, rs.get(column).getNombre()));
}
// Add data to table:
ArrayList<ObservableList<StringProperty>> data = new ArrayList<>(FXCollections.observableArrayList());
for (int i = 0; rs.get(0).getValor().size() > i; i++) {
ObservableList<StringProperty> data2 = FXCollections.observableArrayList();
for (int k = 0; rs.size() > k+1; k++) {
data2.add(new SimpleStringProperty(rs.get(k).getValor().get(i)));
}
data.add(data2);
tablevarios.getItems().add(data.get(i));
}
but when i try to make editable with this
tablevarios.getColumns().get(i).setCellFactory(column -> new EditCell());
i have this error from the console
Error:(1687, 78) java: incompatible types: bad return type in lambda expression
sample.Main.EditCell cannot be converted to javafx.scene.control.TableCell,capture#1 of ?>
thanks for the help
Does your EditCell extends ListCell ?
I did it in my project like this:
class EditCell extends ListCell<?> {
// your cell properties here
#Override
protected void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
}
tablevarios.getColumns().get(i).setCellFactory(lv -> {
ListCell<?> cell = new EditCell();
//maybe add context menu to cell or other thins
return cell;
}

searching for a particular entry in a table by qlineedit?

What i want is that if i enter an ID in the textbox and then press enter,then if the ID is present ,then it gets displayed on the table the valuesof the table are inserted with the help of map in another window from which this window Box1 is opened as map.So as far as i have an idea,we have to run find command of map and then using if loop if that entered value in textbox is presentthen will display it in the same way as dummy data is displayed.
code used
Box1::Box1(QWidget *parent)
:QDialog(parent)
{
searchgroup = new QGroupBox(tr("Data Search"));
QHBoxLayout *layout2 = new QHBoxLayout;
text = new QLineEdit(this);
searchh = new QLabel(tr("&Enter ID:"));
searchh->setBuddy(text);
layout2->addWidget(searchh);
layout2->addWidget(text);
searchgroup->setLayout(layout2);
tableegroup = new QGroupBox(tr("Searched Data"));
QVBoxLayout *layout1 = new QVBoxLayout;
tablee = new QTableView(this);
mode1 = new QStandardItemModel(1,2,this);
mode1->setHorizontalHeaderItem(0, new QStandardItem(QString("ID")));
mode1->setHorizontalHeaderItem(1, new QStandardItem(QString("DATA")));
map<int,QString>::iterator itt;
itt=dataa.begin();
for (int colu = 0; colu < 2; colu++)
{
item1 = new QStandardItem();
if (colu == 0)
{
item1->setData(((*itt).first), Qt::DisplayRole);
mode1->setItem(0,0,item1);
} else
{
item1->setData(((*itt).second), Qt::DisplayRole);
mode1->setItem(0,1,item1);
}
}
tablee->setModel(mode1);
layout1->addWidget(tablee);
tableegroup->setLayout(layout1);
QVBoxLayout *mainlayout1 = new QVBoxLayout;
//mainlayout1->addWidget(menubarr);
mainlayout1->addWidget(searchgroup);
mainlayout1->addWidget(tableegroup);
setLayout(mainlayout1);
}
Thanks for any help in advance
EDIT
what i want
void Box1::textReturn()
{
bool ok;
int id = text->text().toInt(&ok);
// map<int,QString>::iterator itt;
if (ok && dataa.contains(id))
{
// add row (id, data[id] to table
}
else
{
QMessageBox msgbox = new QMessagebox();
msgbox->setWindowTitle("Alert");
msgbox->setText("No such ID present!");
msgbox->show();
}
}
EDIT2
void Box1::textReturn()
{
int id = (text->text()).toInt();
map<int,QString>::iterator itt;
itt = dataa.find(id);
if(itt != dataa.end()) //returns 1 if we found something
{
QList<QStandardItem *> items;
items << new QStandardItem(QString("%1").arg(id));
items << new QStandardItem((*itt).second);
mode1->appendRow(items);
tablee->update();
}
else
{
QMessageBox *msgbox = new QMessageBox();
msgbox->setWindowTitle("Alert");
msgbox->setText("INVALID ID ENTERED");
msgbox->show();
}
}
As #KCiebiera said, you have to do this connection
connect(text, SIGNAL(returnPressed()), this, SLOT(textReturnPressed());
Then you need to find your key in the table using
QList<QStandardItem *> QStandardItemModel::findItems ( const QString & text,
Qt::MatchFlags flags = Qt::MatchExactly, int column = 0 )
As you have map, so elements shouldn't repeat, your QList should be NULL or contains just one element. When u'll get your element (as QStandardItem) you just need to invoke
tablee->showColumn ( int column )
tablee->showRow ( int row )
Where your column will be QStandarItem->column() and row QStandardItem->row();
EDIT
void Box1::textReturnPressed()
{
int id = (test->text()).toInt();
map<int, string>::iterator it;
it = dataa.find(id);
if(it != dataa.end()) //we found something
{
QList<QStandardItem *> items;
items << new QStandardItem(QString("%1").arg(id));
items << new QStandardItem((*it).second);
mode1->appendRow(items);
}
else
QMessageBox::information(this, "Info", "ID not found!", QMessageBox::ok);
}
Something like this;
As far as I understand your question. You need to create a new slot in the Box1 class. Let's call it textReturnPressed(). Then you have to connect it to returnPressed() signal from text
connect(text, SIGNAL(returnPressed()), this, SLOT(textReturnPressed());
and here is textReturnPressed (I hope it compiles)
void textReturnPressed()
{
bool ok;
int id = text->text().toInt(&ok);
if (ok && dataa.count(id) > 0) {
QList<QStandardItem *> items;
items << new QStandardItem(QString("%1").arg(id));
items << new QStandardItem(dataa[id]);
mode1.appendRow(items);
}
}
You don't need an iterator to check if an item is in the map. Just call map.count() function.

Resources