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
Related
need some help here with my code.
I have a combobox which in the initialization stage, its selectedIndex is set to -1 (empty).
In my state changed listener for the combo box i have the code i will paste below.
What its supposed to do is check if the selected index of the combobox is -1 then do nothing in my if statement, but if the index is not -1 it will print a row on my jTable with some information on it (this is my else statement) based on the selected index and then set the index back to -1 to deselect any items on my comboBox.
It prints the information on m jTable just fine, but the problem is my else statement seems to run even when the selected index for my combobox is -1.
This problem happens the first time i run the program. there is no other code which prints information on my jTable besides this code. please help
private void jComboBoxItemNameItemStateChanged(java.awt.event.ItemEvent evt) {
if(evt.getStateChange() == ItemEvent.SELECTED) {
if(jComboBoxItemName.getSelectedIndex() == -1){
System.out.println("nothing");
}
else {
try {
addResultOnTable();
jComboBoxItemName.setSelectedIndex(-1);
//displaySearchOnTable();
}
catch (Exception ex) {
System.out.println("comboBox is empty");
Logger.getLogger(Inventory.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
The only way to set the selected index of the JComboBox to -1 (minus one) is through code and not through a user action. When you set the JComboBox index to -1 in the code (as you do in the jComboBoxItemNameItemStateChanged method), the JComboBox fires an ItemEvent but it is always a DESELECTED state change and never a SELECTED state change. Hence your inner if statement will never be true. I am referring to this line of the code in your question:
if(jComboBoxItemName.getSelectedIndex() == -1 && firstRun == true){
By the way, since you always set firstRun to true in method jComboBoxItemNameItemStateChanged, the && firstRun == true will always be true. Besides which, people usually just write firstRun. Since firstRun is a boolean, there is no need for the == true.
All you need to do (in the jComboBoxItemNameItemStateChanged method) is print the value of the state change and the JComboBox selected index to verify this.
private void jComboBoxItemNameItemStateChanged(ItemEvent evt) {
String state = switch (evt.getStateChange()) {
case ItemEvent.DESELECTED -> "De-selected";
case ItemEvent.SELECTED -> "Selected";
default -> "Unknown";
};
System.out.print("State change: " + state);
JComboBox<?> combo = (JComboBox<?>) evt.getSource();
int ndx = combo.getSelectedIndex();
System.out.println(" , index = " + ndx);
}
Note that the JComboBox index is always set before the above code is executed. The above code also verifies this. So the following statement, in your question, is not true.
my else statement seems to run even when the selected index for my combobox is -1
Whenever the following condition (also from your code) is true, the JComboBox selected index cannot be -1 (minus one).
evt.getStateChange() == ItemEvent.SELECTED
Also note that the above code uses switch expressions which were added since Java 12.
I don't mean to be rude or condescending, but my code, above, is one way to debug
your code. Every programmer needs to learn how to debug their code.
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
}
I tried a lot of stuff but didn't come up with the good plan it seems.
My mini application fails sometimes with null error. Sometimes I think that I 'touched' some cell and sometimes I don't know why it happens. But when I delete empty rows and columns (near my filled rows) - all is good, no more null.
And I don't want a client to delete empty cells it's stupid.
And I also want to use some null values (if they are in my semi/filled row), so I can perform a check and see if required cell is filled.
But I don't want null values around my filled rows (right side and bellow).
Anyway, if someone understood above, here is the code as well:
workbook.getSheetAt(11);
for (int i = sheet.getFirstRowNum() + 1; i <= sheet.getLastRowNum(); i++) {
Row rows = sheet.getRow(i);
for (int c = 0; c < 8; c++) {
Cell cells = rows.getCell(c);
if ((c == 0 && cells == null) || (c == 1 && cells == null)) {
//if required cells are not filled throw error or blabla
}
}
}
aand picture:
null
Thank you!
I have a foreach that is suppose to go through and arraylist and perform an action every time an item changes.
So it for something like:
ID | Request
1 | z
2 | e
it sends an email to 1 saying "You have 1 request". Then an email to 2 "You have 1 request" and so on.
My loop doesn't address the last item when there's only 2 items in the list and I'm having a difficult time trying to figure out the elegant way to address it.
Integer managerId = null;
Integer previousManagerId = null;
if(requests != null && requests.size() > 0){
for(Request request : requests){
managerId = request.getId();
if((!managerId.equals(previousId) && previousId != null)){
e.sendEmail(previousId, numReq.toString());
numReq = 0;
}
numReq++;
previousId = managerId;
}
//Suppose to address the last item. Fails when size == 2
if((!managerId.equals(previousId) && previousId != null)){
eusendEmail(previousId, numReq.toString());
}
The last statement of the loop ensures that previousId is always equal to managerId after the loop ends, so it can never go into the if.
I think you always want to send the last email because you know there was at least one request.
You have to save the previousId outside the for each because it will delet this value every time it goes trough the next object ;)
But why are you doing the first if? Wouldn't the foreach do that anyway?
How if you try like this:
String managerId = "";
for(Request request : requests){
managerId = request.getId();
if(!managerId.equals(previousId)){
request.sendEmail(previousId, numReq.toString());
numReq = 0;
}
numReq++;
}
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.