I'm trying to loop through all of the rows in a column in a jTable at the moment I can get it to loop through a column but it only gives me the first 5 values and it also gives me a strange output.
here is the code:
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
// Button to Start
Object[] columnData = new Object[jTable1.getColumnCount()];
Object[] rowData = new Object [jTable1.getRowCount()];
for (int i = 0; i < jTable1.getColumnCount(); i++) {
columnData[i] = jTable1.getValueAt(i, 4);
System.out.println(Arrays.toString(columnData));
}
here is the output:
I think you are using your column iteration as the row number in your code. jTable1.getValue(i, 4) has parameters row, column in that order. If you only have five columns, you will only get five values.
Try changing the loop to count through the rows and select the 5th column.
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
// Button to Start
Object[] columnData = new Object[jTable1.getRowCount()]; // One entry for each row
Object[] rowData = new Object [jTable1.getRowCount()];
for (int i = 0; i < jTable1.getRowCount(); i++) { // Loop through the rows
// Record the 5th column value (index 4)
columnData[i] = jTable1.getValueAt(i, 4);
}
System.out.println(Arrays.toString(columnData));
Related
I'm making a singleplayer Battleship game in Processing 3.
To generate the playing field, I create a two-dimensional array that holds a boolean value for whether the grid cell has been clicked. To generate this array, I use to following function:
boolean[][] clicked = {};
void initArray(int gridSize) {
boolean[] row = {};
for (int i = 0; i < gridSize; i++) row = (boolean[]) append(row, false);
for (int i = 0; i < gridSize; i++) clicked = (boolean[][]) append(clicked, row);
}
The issue I'm having is that whenever I try to change one cell's value to true, all the values in that row become true as well. This is the code I use to change and print the array:
void setup() {
initArray(3);
clicked[2][1] = true;
println(clicked[0]);
println(clicked[1]);
println(clicked[2]);
}
I only want to change the second value of the third row, but instead it changes the second value of every row. Here is the output:
[0] false
[1] true
[2] false
[0] false
[1] true
[2] false
[0] false
[1] true
[2] false
I'm not allowed to use OOP for this assignment.
Thanks in advance.
You create only one row object and you append this object to each row. At the end each row refers to the same row object. So it seems to be that changing the element of one row affects the other rows too.
Create a sparte row object for each row of the grid, to solve your issue:
boolean[][] clicked = {};
void initArray(int gridSize) {
for (int i = 0; i < gridSize; i++) {
boolean[] row = {}; // <--- new object for each row
for (int j = 0; j < gridSize; j++)
row = (boolean[]) append(row, false);
clicked = (boolean[][]) append(clicked, row);
}
}
I need convert HashMaps to xlsx using poi. For sheet data2 i need something like that:
table1:
But i have table2:
Here's my list of HashMaps:
rows=[{kol2=s, kol1=s}, {kol2=bbbb, kol3=bbbb, kol1=aaaa}, {kol2=bbbb, kol3=bbbb, kol1=aaaa}, {kol2=bbbb, kol3=bbbb, kol1=aaaa}, {kol2=s, kol1=s}]}
Here's my code:
XSSFWorkbook workBook = new XSSFWorkbook();
XSSFSheet sheet = workBook.createSheet("data");
XSSFSheet sheet2 = workBook.createSheet("data2");
int rowCount = 0;
int help = 1;
List<HashMap<String, Object>> rows = ((List<HashMap<String, Object>>) x);
int rowCount2 = 0;
int header = 1;
Row header2 = sheet2.createRow(0);
for (int i = 0; i < rows.size(); i++) {
int li = 0;
Row row2 = sheet2.createRow(++rowCount2);
HashMap<String, Object> row = rows.get(i);
int columnCount2 = 0;
for (HashMap.Entry<String, Object> subElement : row.entrySet()) {
if (subElement.getValue() != null) {
if (i == li) {
Cell cell = header2.createCell(header);
cell.setCellValue(subElement.getKey().toString());
header++;
}
li++;
Cell cell2 = row2.createCell(++columnCount2);
cell2.setCellValue(subElement.getValue().toString());
}
}
}
Someone can help?
Iterating over a HashMap's EntrySet
The first problem is that you are iterating over the entrySet of your HashMap
for (HashMap.Entry<String, Object> subElement : row.entrySet()) {
// no guaranteed order
}
Looking at the JavaDoc of the Set#iterator() method you will see this:
Returns an iterator over the elements in this set. The elements are returned in no particular order (unless this set is an instance of some class that provides a guarantee).
There are Sets which are ordered (such as the TreeSet), but since you are using a HashMap, your EntrySet won't be ordered too.
Notice the column order in your sheet is kol2-kol3-kol1. Don't you want it to be kol1-kol2-kol3?
Not creating empty columns
You are forgetting to create empty cells for columns you don't have in your Map.
if (subElement.getValue() != null) {
// there won't be an empty cell if you e.g. don't have kol2 in your rows Map,
// since this just skips your current value
}
This is why you end up with something like:
kol2 kol3 kol1
s s
bbbb bbbb aaaa
...
instead of:
kol2 kol3 kol1
s s
bbbb bbbb aaaa
...
Creating the header row inside the loop
By creating the header row inside your loop, you are making your solution more complicated than necessary. It would be much easier just to create the header row and then loop over your entries in the List.
if (i == li) {
Cell cell = header2.createCell(header);
cell.setCellValue(subElement.getKey().toString());
header++;
}
If you are doing this outside the loop, there is no need for the li and the header variable
Suggested solution
I would (for a start) come up with something like this (I added some extra comments I normally wouldn't put there to make more clear what the intentions are and what aspects of the solution you need to understand):
XSSFSheet sheet2 = workBook.createSheet("data2");
List<HashMap<String, Object>> rows = ((List<HashMap<String, Object>>) x);
List<String> headers = Arrays.asList("kol1", "kol2", "kol3");
int currentRowNumber = 0;
// create header row
Row header = sheet2.createRow(currentRowNumber);
for (int i = 0; i < headers.size(); i++) {
Cell headerCell = header.createCell(i);
headerCell.setCellValue(headers.get(i));
}
// create data rows (we loop over the rows List)
for (int i = 0; i < rows.size(); i++) {
HashMap<String, Object> row = rows.get(i);
// we neet to increment the rowNumber for the row in the sheet at the beginning of
// each row. entry 0 in the rows List is in sheetRow 1, entry 1 in sheetRow 2, etc.
currentRowNumber++;
Row sheetRow = sheet2.createRow(currentRowNumber);
// we can now loop over the columns inside the row loop (using the headers List)
// we create a Cell for each column, but only fill it if there is
for (int j = 0; j < headers.size(); j++) {
Cell cell = sheetRow.createCell(j);
// only fill the cell if we are having data in the row map for the current column
String currentColumnName = headers.get(j);
if (row.containsKey(currentColumnName)) {
cell.setCellValue(row.get(currentColumnName).toString());
}
}
}
If you want a different column order, just change the header List and you are done (e.g. Arrays.asList("kol2", "kol3", "kol1")).
The line array doesn't update after the variable row has been incremented.
private int col = 5;
private int row = 0;
// The array should update according to this defintion
public int [][] line ={{col,row},{col,row+1},{col,row+2},{col,row+3}};
public void drop(){
Timer timer = new Timer();
TimerTask drop = new TimerTask() {
#Override
public void run() {
canDrop();
row++;
System.out.println(line[0][1]);
repaint();
}
};
timer.scheduleAtFixedRate(drop,100,500);
}
This code should output the fowllowing lines, but I get lines of zeros instead:
123...
As far as I understand your question, you want to conveniently update the line array. However, when you increment row, it does not affect your array. The line
int [][] line ={{col,row},{col,row+1},{col,row+2},{col,row+3}};
creates an array and copies the values of col and row, but it does not store a reference to your initial variables col and row, so that you can update them just by changing their values.
Just create another function:
// Updates row in the line array like in your initial definition
public void updateRowInLine(int[][] line, int row) {
for (int i = 0; i < 4; i++) {
line[i][1] = row + i;
}
}
Then call it after row++, like updateRow(line, row);.
I want to write a board game using LibGDX and during a game I want make it possible to add or remove rows / columns on that board. First, I made some tests to prepare myself to that. Here is the code :
public class Test extends Game {
Skin skin;
Stage stage;
Texture texture1;
static int columns = 7;
static int rows = 12;
Window window2;
Table table2;
ArrayList<ArrayList<TextButton>> buttons;
#Override
public void create () {
skin = new Skin(Gdx.files.internal("data/uiskin.json"));
buttons = new ArrayList<ArrayList<TextButton>>();
for(int i = 0 ; i< rows; ++i)
{
buttons.add(new ArrayList<TextButton>());
for( int k = 0; k < columns; ++k)
{
buttons.get(i).add(new TextButton(("ASD" + i + k), skin));
}
}
texture1 = new Texture(Gdx.files.internal("data/badlogicsmall.jpg"));
TextureRegion image = new TextureRegion(texture1);
stage = new Stage(new ScreenViewport());
Gdx.input.setInputProcessor(stage);
ImageButtonStyle style = new ImageButtonStyle(skin.get(ButtonStyle.class));
style.imageUp = new TextureRegionDrawable(image);
ImageButton iconButton = new ImageButton(style);
window2 = new Window("Dialog2", skin);
window2.getTitleTable().add(new TextButton("X", skin)).height(window2.getPadTop());
window2.setSize(300, 400);
table2 = new Table();
for(int i = 0 ; i< rows; ++i)
{
for( int k = 0; k < columns; ++k)
{
table2.add(buttons.get(i).get(k));
}
table2.row();
}
ScrollPane pane= new ScrollPane(table2,skin);
pane.setScrollbarsOnTop(false);
pane.setFadeScrollBars(false);
window2.add(iconButton).row();
window2.add(pane);
stage.addActor(window2);
iconButton.addListener(new ChangeListener() {
public void changed (ChangeEvent event, Actor actor) {
new Dialog("Some Dialog", skin, "dialog") {
protected void result (Object object) {
System.out.println("Chosen: " + object);
if((Boolean) object )
{
for(int i = 0 ; i <columns; ++i){
table2.getCells().removeIndex(0).getActor().remove();}
}
}
}.text("Are you enjoying this demo?").button("Yes", true).button("No", false).key(Keys.ENTER, true)
.key(Keys.ESCAPE, false).show(stage);
}
});
}
#Override
public void render () {
Gdx.gl.glClearColor(0.2f, 0.2f, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));
stage.draw();
}
As you can see here, I'm creating a standalone button and a table and fill it with buttons. Then after button clicked I want to remove first row of that table and also move rest of rows up. It works but only once (for first row), then (with second click) I got this exception :
Exception in thread "LWJGL Application" java.lang.IndexOutOfBoundsException: index can't be >= size: 70 >= 70
Don't know what to do and how to fix it. Hope you can help me with this.
UPDATE
Thanks for reply; my code looks like this now :
// initialization
for(int i = 0 ; i< rows; ++i)
{
for( int k = 0; k < columns; ++k)
{
table2.add(new TextButton(("ASD" + i + k), skin));
}
table2.row();
}
// sample operation - remove left column
for(int i = 0 ; i <rows; ++i){
table2.removeActor( table2.getChildren().get(i*columns-i) );
}
columns--;
Also, I got similar Array in logical model and want to change state of UI table based on that array. So is this approach correct or should I change something?
The issue is about row() you are using - before the first row there is no row cell (marked with row() method) and that's why it does not cause error but when removing the second one it does.
Compare with table2 without any rows to test it:
for(int i = 0 ; i< rows; ++i)
{
for( int k = 0; k < columns; ++k)
{
table2.add(buttons.get(i).get(k));
}
//table2.row(); - we don't want any rows!
}
Ok we know where problem lays but it is not the solution (ok maybe some solution it is:) ). Instead of hard removing indexes of Table cells you should operate on Actors of table using following code:
for(int i = 0 ; i <columns; ++i){
table2.removeActor( table2.getChildren().first() );
}
Working with a table in such a way is a bit cumbersome, at least I don't know better. A quick fix for your code would be:
// Global field
int removedRows = 0;
// In your listener
System.out.println("Chosen: " + object);
if ((Boolean) object)
{
for (int i = 0; i < columns; ++i)
{
table2.getCells().get(i + columns * removedRows).clearActor();
}
removedRows++;
}
But if you want to remove complete rows, I would use a VerticalGroup and add each row there, so you can directly access a row and remove it from the VerticalGroup. If you use a fixed size for the buttons then it will align properly, too.
table2.getCells()
Returns an Array, this means we now operate on that Array and NOT the table2 anymore!
This means if you execute this:
table2.getCells().removeIndex(0);
It will just remove that cell from the array. This does NOT update the table2 as a complete object, just the cells array of that table (since no copy of that array is returned)
In other words you are doing this:
Array<Cell> table2Cells = table2.getCells();
Cell tableCell = table2Cells.removeIndex(0);
tableCell.clearActor();
So you delete the cell from the table2 cell array, and then you clear the cells contents (actor in this case). But you are not updating the table to reflect the changes of the removed cell, table2 still "thinks" that the cell is there, but you deleted it.
Thus you get the index error, because the stage draws the table, and the table wants to draw a cell that no longer exists.
So if you want to create some kind of board for a game the best way would be to code your own class that provides the functionality you desire.
A workaround would be that you reset the table and fill it again:
int table2Rows = table2.getRows();
table2.reset();
// Omit the first row
for (int i = rows - table2Rows + 1; i < rows; ++i)
{
for (int k = 0; k < columns; ++k)
{
table2.add(buttons.get(i).get(k));
}
table2.row();
}
table2.layout();
Thus the first cell will contain the first button and so on, since the table internal values are properly updated.
this function should refresh my JTable:
list = null;
list = (ArrayList<String[]>) interface_engine.getData();
info = new String[list.size()][header.length];
Iterator it = list.iterator();
for (int i = 0; i < list.size(); i++) {
String[] current = (String[]) it.next();
for (int j = 0; j < header.length; j++) {
info[i][j] = current[j];
}
}
DefaultTableModel model = (DefaultTableModel) data_table.getModel();
model.addRow(info);
when i call it for add a new row (getData is a remote method for retrieve data from db), the added row it's not display as a string, but a a variable reference (such as String#128dda...). Where's the problem?
the added row it's not display as a string, but a a variable reference (such as String#128dda...).
Read the DefaultTableModel API. You can't add a 2-Dimensional array using the addRow() method. You can only add one row at a time.
The addRow() method should be inside your loop. Build one row of data, then invoke the addRow() method.