Is there any way to make JavaFX spinner repeat its value range when hitting the lowest/highest value? - javafx

Is there any way to make JavaFX spinner repeat its value range when hitting the lowest/highest value?
For example, here I have Spinner with minValue 1, maxValue 5, initial value 3:
Spinner spinner = new Spinner(1, 5, 3);
What I need is that when I reach number 1 and press down arrow, number 5 shows up and when I press up arrow, number 1 shows up.
I was wondering about checking when are the arrows pressed and edit the value if needed, but I think there might be some property or some other, simpler way, which does this automatically, but couldn't find any.
Thank You very much.

So, I think it is a good idea to sum this up and post the exact answer I needed.
To create JavaFX Spinner with wrap-around values, I had to do this:
SpinnerValueFactory<Integer> valueFactory = new SpinnerValueFactory.IntegerSpinnerValueFactory(1, 5, 3);
valueFactory.setWrapAround(true);
Spinner<Integer> spinner = new Spinner<>();
spinner.setValueFactory(valueFactory);

Related

How to fix QTableWidget setText/setCellWidget causing crash when loading QSettings

Hello I'm using a QTableWidget and essentially have code such that the first column will allow the table to grow/shrink dynamically. The last populated row's first cell will have a Plus button to add a new row that can be edited and the Minus button will remove its corresponding button's row. For example, If I click the Plus button 5 times, it will be at the 6th row and the previous 5 rows will all have a Minus buttons to remove their row. If the cell's row has a Minus button on it, the row is implied editable, otherwise not. However, I allow the table to have a default amount of rows, such that it can never visually shrink less than 5, for example, even if it's technically "empty". To edit the row, you need to hit the Plus button which will check if we need to insert a new row, for example if we're at 5 rows and the base row size is 5, then we need a new row and to populate each column's index of the new row.
The main reason for this table is to read and write the table's information to a QSettings and be able to import the past exported information to the same cells and essentially restore the table's state as it appeared last. However, when reading from the QSettings, the table will crash after all cells are populated correctly with the information and I can tell they are correctly populated because the debugger will freeze the GUI and I can visually see and qDebug() how far into the loop of the QSettings array I got to before seg-faulting.
Now when I do everything manually, such as clicking the Plus button, everything is fine and the program performs as expected.
//newRowCount is assumed to be the amount of rows with Minus Buttons currently, only creates a new row if the table needs to expand
void TableTest::enableNewRow(){
newRowCount++;
if(newRowCount > table->rowCount()){
table->insertRow(table->rowCount());
for(int i = 0; i < table->columnSize(); ++i){
QTableWidgetItem* item = new QTableWidgetItem;
item->setFlags(item->flags() ^ Qt::ItemisEditable);
table->setItem(newRowCount, i, item);
//Code to set the previous column's item (newRowCount--) to have an Qt::ItemisEditable flag set to true
...
}
}
//Some button setup to make Plus button and create a new Minus button connect and do their jobs and move the Plus button down into the newly inserted row
...
}
void MainWindow::importFile(){
int settingRows = settings->beginReadArray("Groups");
for(int i = 0; i < settingRows; ++i){
settings->setArrayIndex(i);
//Will only add a new row if needed, check inside above function and all row items will be allocated if made
table->enableRow();
for(int j = 1; j < table->columnCount(); ++j){
table->item(i, j)->setText("testing");
}
}
}
And the program crashes with the following stack trace:
1 QWidget::show()
2 QAbstractItemView::updateEditorGeometries()
3 QAbstractItemView::updateGeometries()
4 QTableView::updateGeometries()
5 QTableView::timerEvent(QTimerEvent *)
6 QObject::event(QEvent *)
7 QWidget::event(QEvent *)
8 QFrame::event(QEvent* )
9 QAbstractScrollArea::event(QEvent* )
10 QAbstractItemView::event(QEvent* )
11-21 ... Not useful information about any of the code
22 QCoreApplication::exec()
23 main
However, it's all byte code and I can't actually inspect which line is crashing the code in any of the traces using the debugger. What I don't understand is that the same process for manually clicking the Plus button is being completed (I connect the click event of the Plus button to the enableRow() function) and when I programmatically call enableRow() from the QSettings loop in importFile() it will crash after it loops through all of the items.
Things to note: setting the base size of the table to the size of the QSettings array I'm reading from (i.e. if I want 10 rows, just setting 10 rows to begin with before setting the item texts will work correctly), however, I want the base size of the table upon creation to be something like 5. It seems once the loop goes beyond the row count I specified from the constructor, then the program will crash, but not at say, index 6, but only after it has completely looped through the table. It does not crash on any line such as QTableWidgetItem::setText or QTableWidget::setCellWidget(). I'm kind of confused and wondering if the table is populating too quickly for the QTableWidget::timerEvent on stack trace line 5. Nothing I do in the loop is any different than what I do when manipulating the table normally.
It turns out that the error was that I was setting the QTableWIdgetItem one row earlier than I should have been. I'm not sure why the table would be able to iterate up until the end of the QSettings loop before crashing, but that was essentially the error. I'm not quite sure why the stack trace was so cryptic.
in my enableRow() function, I actually posted above from memory the correct logic, which differed in my code's logic by 1 index previously for the row value. Why the code did not crash when using it normally with the buttons whose slots called the same function as the import() seems to baffle me, perhaps a case of undefined behavior.

javafx tableView getting previous Item

Hey im doing a Playlist for Music and im doing the previous and Forward button but i dont know how i get the file before/ after the current one. I use this for the current
play(tableView.getSelectionModel().getSelectedItem());
For previous, use
int currentIndex = tableView.getSelectionModel().getSelectedIndex();
tableView.getItems().get(currentIndex - 1);
and similarly for next. You will want to add checks for the range (i.e. don't get the previous item if currentIndex == 0, and similarly for next).

JavaFX labels change when clicked

I'm new to FXML and am trying to figure out how to get the binary representation of a number to show up on the scene with each bit as an individual label. What I want to happen is when you click on a bit, the number and the label change accordingly (so if the label is a zero, then it will change to 1 and so on). Thanks so much!

Weighting function for favorites

I've got a list of items. Users can occasionally select them. Now I want to order the items by their popularity. What's a good weighting function for that?
Constraints:
The weight should be in [0,1)
Recursive calculation is prefered (not required)
Newer events must have more influence than old ones.
I'd favor approved functions. As I've developped something like this once and it worked not as expected.
Now I want to order the items by their popularity.
So you order by the number of times some user selected the item.
The weight should be in [0,1).
Fine, divide by the total number of times some user selected some item plus one.
Recursive calculation is prefered
Why? Maybe I'm missing the point of what you're trying to do because otherwise this constraint is lost on me.
Edit:
Responding to your edit, try
sum ( 1 / age of vote ) / age of item
the sum being taken over all votes for a given item.
If you have a counter of votes per item, you can use a 'fading constant' in order to make older votes "fade away" with time. Something like:
Nvotes(i) = IsClicked(i) + Nvotes(i) * Kfade
where: 0 < Kfade < 1
Thus, whenever a new click is intercepted, all counters are advanced where only the selected item is incremented by 1.
EDIT: Since the total is less than 1, you may want to normalize Nvotes by the total number of clicks so far.
Keep a list items of the items that need sorting. Let each item have a score. Keep a list clicks of the N most recent clicks, in order of decreasing recency. Each item can appear more than once in the list. Choose a constant fade a little smaller than 1. Then do:
for item in items:
item.score = 0.0
bonus = 1.0
for item in clicks:
item.score += bonus
bonus *= fade
Now sort the items by score, highest first.
The score isn't in the range 0 to 1, but i don't see why you actually need that. It would be straightforward to normalise the scores afterwards.
This isn't recursive, but it's straightforward to put in recursive form.
This isn't a known algorithm. I don't know of any known algorithms for this except move-to-front, which is almost certainly more aggressive than you want.

Change item sortorder in gridview - LINQToSQL

I've got a gridview with a list of categories. In the database (MSSQL2008), the category table has a SortOrder(INT) NULL field.
Currently categories are retrieved using:
Galleries.DataSource = From G In DB.GalleryCategories Order By G.SortOrder, G.Name
Now, what I need to be able to do is add "Move Up" and "Move Down" buttons to each row to allow the user to sort the items in an arbitrary way.
My initial thoughts are along the lines of:
Identify ID of selected item.
Identify ID of item before/after selected item.
Swap of identified items in the DB SortOrders.
I would then have make the sortorder NOT NULL and make sure it's initialised to a unique number
I'd appreciate any alternative suggestions / comments on this approach
Many thanks
I have generally seen it done this way, and have done it myself
SortOrder is an int
Each item increases by 10 (so, 10,20,30,40) or suitable increment
To move an item up, subtract 15
To move an item down, add 15
To insert an item, take the target and add/subtract 1
Apply a NormalizeSort() routine which resets the values to even intervals
10,20,25,30,40 => 10,20,30,40,50
That makes it all pretty simple, since inserting something above something else is just:
list.Add( New Item(..., target.SortOrder +1) )
list.NormalizeSort()
// or
item.SortOrder += 11, etc
If you want to make it a decimal, then you can just make it all sequential and just add .1, etc to the sort order and re-normalize again.
// Andrew
I believe
Galleries.AllowSorting = true;
would be far enough ;)

Resources