I am trying to move an item in a list upward but it is not working the way I want. The element that I select still remains after it has swapped position with the previous elements. I am using Jlist.
listTasks is a JLIst
and
listModel is ListModel
For instance if I have
1
2
as a list, after I select 2 and click the up button I get
2
1
2
This is the code snippet :
public void mouseClicked(MouseEvent e) {
int id = 0;
if(e.getSource() == this.lblUpArrow){
id = this.listTasks.getSelectedIndex();
if((id > 0 ) && (this.listModel.size() != 0)){
Object value = this.listModel.getElementAt(id);
Object previousValue = this.listModel.getElementAt(id - 1);
this.listModel.insertElementAt(value.toString(), (id - 1));
this.listTasks.remove(id);
this.listModel.insertElementAt(previousValue.toString(), (id));
this.listModel.remove(id + 1);
}
}
}
Thanks for your help.
You just need to remove the element to move and re-insert it above the current position. No swap required.
Related
I have a table that is generated programmatically in an application. I'm able to get the position of a selected row and assign it to a variable, but I'm not sure how to perform the equivalent for columns, like, at all. All I really need to know is how to get the column number on tap like I do with rows here:
fun createTable(rows: Int, cols: Int) {
/* Here, 'i' represents the number of rows, which is determined by
* the length of the location list active in the application. */
for (i in 0 until locationList.size) {
/* Instantiate the row that will be used to generate each table. */
val row = TableRow(this)
/* Set the basic layout parameters for the textView, which is being used to contain the table. */
row.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
row.setOnClickListener {
selectedRow = i.toString().toInt()
if (locationList[selectedRow].entranceNoteArray.size == 0) {
showAlert("There are no transitions associated with this location. You may only add a note to an existent transition.")
} else {
isEnterOrExit()
}
}
row.gravity = Gravity.CENTER
for (j in 0 until columns) {
var rowIterator = 0
val textView = TextView(this)
textView.apply {
// Cosmetic/UI Related Code
textView.setPadding(10, 5, 10, 5)
layoutParams = TableRow.LayoutParams(350, TableRow.LayoutParams.WRAP_CONTENT)
textView.setTextColor(Color.DKGRAY)
textView.gravity = Gravity.CENTER
textView.textSize = 12F
/* The purpose of this decision structure is to fill the
* table's cells properly based upon which column cell 'j'
* represents. When j = 0 and i = 0, the first column of
* the first row has been selected - therefore, the first
* value (message) of the first location in the reversed
* locationList should be placed there. */
if (j == 0) {
text = locationList[i].message
textView.setTypeface(null, Typeface.BOLD)
} else if (j == 1) {
text = locationList[i].entered
textView.setTypeface(null, Typeface.NORMAL)
} else if (j == 2) {
text = locationList[i].exited
}
}
row.addView(textView)
rowIterator++
}
tableLayout.addView(row)
}
logLayout.addView(tableLayout)
}
Is there a simple way to do this, or do I need to get the on tap coordinates from the view itself in order to achieve this in a roundabout way?
If You want to know which exactly TextView was clicked in Table You can do this in the following way:
Foreach TextView You have to add tag
textView.tag = "$i $j"
i is the row and j is the column.
Now You can add one listener for every TextView
textView.setOnClickListener {
val tag = it.tag.toString()
val row = tag.substring(0, tag.indexOf(' ')).toInt()
val column = tag.substring(tag.indexOf(' ') + 1).toInt()
//now You know which position was clicked
}
My code is very long so I will only be adding snippets that are relevant.
Okay so I've been trying to increment a label by one using the following code:
btnComplete.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
//if the list has a minimum of 1 item
if (currentCartTxt.getItems().size() > 0) {
int sales=0;
sales++;
String x = Integer.toString(sales);
numberOfSalesTxt.setText(x);
}
}});
However it only changes my textfield to 1 and never increases it. Any help would be greatly appreciated.
the currentCartTxt is a listView and the numberOfSalesTxt is a textfield.
Basically to explain my app, I have a list of items that I am adding to a textfield (currentCartTxt) and I need to press the complete button whenever but there must be at least 1 item in the textfield. And every time the button is pressed the textfield(numberOfSalesTxt) increases by 1.
Thanks!
You have to:
read current value (from Label/View/TextView...)
increment it (just add 1)
set new value to view
if (currentCartTxt.getItems().size() > 0) {
// get current value
String text = numberOfSalesTxt.getText();
// convert it from "String" to "int"
int sales = Integer.parseInt(text);
// increment it
sales++;
// Convert from "int" to "String"
String x = Integer.toString(sales);
// Set new value
numberOfSalesTxt.setText(x);
}
I am creating a method to help me find the next position in a grid of islands/objects in a 3d world(but ignoreing the Y coordinate for now), they have a distance of 200 for each island(islandDistance).
What I currently have is this:
public static Location findLocation(String latest,String server) {
if (latest == null) {
latest = sql.findLatestIslandEntry(server);
if (latest != null && latest.isEmpty()) // first creation
latest = "0,4,0";
else if (latest == null)
return null;
}
String split[] = latest.split(",");
List<String> locationString = Arrays.asList(split);
List<Double> locations = new ArrayList<>();
for (String xyz : locationString) {
locations.add(Double.valueOf(xyz));
}
String world = CC.getSTDConfig().getString("worldname");
Location l = new Location(Bukkit.getWorld(world),0,4,0);
if (locations.get(0) <= 0) {
l.setX(Math.abs(locations.get(0)) + islandDistance);
} else {
l.setX(0 - locations.get(0));
}
if (locations.get(2) <= 0) {
l.setZ(Math.abs(locations.get(2)) + islandDistance);
} else {
l.setZ(0 - locations.get(2));
}
return l;
}
Even before testing I could see that this wouldn't work. I would end always adding to both x and z when thats not always what I want. I made an example of the dataset I want as output here:
Basicly what I want to is to get the next position depending on how many I have already inserted and maybe the last one inserted ? thats the info I use in my code currently atleast. Say I just inserted island number 25 and now want island 26 I should get the result 0,600(the order can be different I just want to fill the grid out)
You want to generate integer coordinates ordered by Euclidean distance. To diminish calculation, it is enough to generate coordinates in the first octant (for 2d case), so X and Y are non-negative and Y<=X. For every calculated (X,Y)pair just generate also (X,-Y), (-X,Y), (-X,-Y),(Y,X),(Y,-X), (-Y,X), (-Y,-X) (except for zero components).
Create priority queue where comparison key is sum of squares (squared distance X*X+Y*Y). Push (0,0) item. At every step extract minimum item (MX, MY) and push next points
Output MX, MY and all permutations
if (MY = 0) and (MX < SomeBorderValue)
push (MX+1, 0)
if MY < MX
push (MX, MY+1)
I've got an array list of an object
Table[] tables = new Table[10];
this list stores information about 10 players and their position goes from top 1 which is tables[0] and top 10 that equals to tables[9]
however, sometimes I need to put a value in between the array, and let's say the player name i'm putting in must be top 5, that means, top 5 goes to top 4, and from top 4 to 3.. and 3 to 2.. and so on, but I also need to check if those values contain the player name that I just added so in that case I gotta remove it, and put all the list back up, pretty much add 1, does anyone have suggestions on the best way to do this, the way i'm thinking on doing it is probably not the best.
Here is what I made so far... however it's not complete..
private void addToBoard(Player damaged, Player killer) {
if(damaged.getName().equalsIgnoreCase(killer.getName())){
return;
}
for(Table table : tables){
if(table != null){
if(table.currentPlayer.equalsIgnoreCase("No One")){
table.currentPlayer = killer.getName();
break;
}else if(table.currentPlayer.equalsIgnoreCase(damaged.getName()) || table.currentPlayer.equalsIgnoreCase("Searching...")){
if(table.currentPlayer.equalsIgnoreCase(killer.getName())){
return;
}
if(table.currentPlayer.equalsIgnoreCase(killer.getName())){
return;
//update the list, and remove duplications
}
if(!table.currentPlayer.equalsIgnoreCase("Searching...")){
killer.chat("I killed "+damaged.getName()+" and now I am Top: "+table.topID+" gf :)");
}
table.currentPlayer = killer.getName();
if(table.topID != 10){
//make a list on a hashmap with the key from 1 to 10
HashMap<Integer, Table> addAll = new HashMap<Integer, Table>();
//add the top
for(int i = 0; i < tables.length; i++){
addAll.put(tables[i].topID, tables[i]);
}
HashMap<Integer, Table> updated = new HashMap<Integer, Table>();
String oldPlayer;
for(Entry<Integer, Table> top : addAll.entrySet()){
if(top.getValue().currentPlayer.equalsIgnoreCase(damaged.getName())){
//dont add
oldPlayer = top.getValue().currentPlayer;
top.getValue().currentPlayer = killer.getName();
Table next = updated.get((top.getValue().topID+1));
next.currentPlayer = oldPlayer;
updated.put(next.topID, next);
}else{
if(updated.containsKey(top.getValue().topID)){
updated.put((top.getValue().topID+1), top.getValue());
}else{
updated.put(top.getValue().topID, top.getValue());
}
}
}
for(int i = 0; i < tables.length; i++){
if(updated.get(i) != null){
tables[i] = updated.get(i);
}
}
}
break;
}
}
}
}
thanks!
Do not use an array. Use a List instead, which supports myList.add("New Guy", 4) -- that is, adding players in a given position and displacing all others one step up. You could then remove the 11th (old 10th) with myList.remove(10):
myList.add("New Guy", 4);
myList.remove(10);
You can do the same thing with arrays, but it is less readable:
// copies 4 elements from (old) pos. 4 to its new pos. 5
System.arraycopy(tables, 4, tables, 5, 4);
tables[4] = "New Guy";
Or use a loop, which is both hard to read (it has to go downwards to avoid losing information) and more verbose:
for (int i=9; i>=5; i--) tables[i] = tables[i-1];
tables[4] = "New Guy";
I get a StackOverflowError when I am trying to fill a cell with the multiplication of two other cells of the same row.
Here is the code :
tableModel.addTableModelListener(new TableModelListener(){
public void tableChanged(TableModelEvent e)
{
DefaultTableModel model = (DefaultTableModel)e.getSource();
//Object data = model.getValueAt(e.getFirstRow(), e.getColumn());
if (e.getColumn() == 0)
{
Object data = model.getValueAt(e.getFirstRow(), e.getColumn());
String stockSymbol = (String)data;
XMLService2 myService = new XMLService2(stockSymbol);
String stockName = XMLService2.getStockName();
model.setValueAt(stockName, e.getFirstRow(), e.getColumn() + 1);
}
if (model.getValueAt(e.getFirstRow(), 2) != null && model.getValueAt(e.getFirstRow(), 3) != null)
{
Double myDouble =(Integer)model.getValueAt(e.getFirstRow(), 2)*(Double)model.getValueAt(e.getFirstRow(), 3);
model.setValueAt(myDouble, e.getFirstRow(), 4);
}
}
});
The last line of this code that calls the setValueAt function is producing the StackOverflowError.
Thank you.
PS :
The table consists of 5 columns.
The type of the 3rd column is Integer.
The type of the 4th column is Double.
The type of the 5th column which gets the result of the multiplication of 3rd and 4th cell is Double.
The program is falling into an endless recursive loop (at least until the stack overflows) because the last model.setValueAt line fires another tableChanged event. Try changing the second conditional statement to
if (e.getColumn() != 4 && model.getValueAt(e.getFirstRow(), 2) != null && model.getValueAt(e.getFirstRow(), 3) != null)
This should prevent the event from re-firing when the last column is updated.
I think a better way is providing a custom TableModel to the grid, in which the getValueAt is overrided, so the operation you want is performed there (the col3*col5).
http://docs.oracle.com/javase/1.5.0/docs/api/javax/swing/table/TableModel.html