How to get value of Last cell in JTable? - java

I have a query ... code is running fine, but am not able to get value of last cell of last row and last column. Below is the code... pls guide
with this code am adding rows dynamically to JTable :
if(e.getSource()==addb)
{
model.addRow(new Object[3]);
repaint();
}
Below is the code for getting values from JTable row wise and later on instead of System.out.println() am going to send data to database...
if(e.getSource()==submit)
{
int j = table.getRowCount();
for(int row=1;row<j;row++)
{
for(int column=0;column<3;column++)
{
System.out.println("row "+row+" Column is "+column);
System.out.println(model.getValueAt(row, column));
}
}
}

Something like this :
int i= table1.getRowCount()-1;
int j= table1.getColumnCount();
Object [] value = new Object[j];
for(int k = 0 ; k<j ; k++)
{
value[k] = model.getValueAt(i,k);
}
Also see this little example
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TableTest extends JFrame implements ActionListener{
JTable table ;
JButton button;
public TableTest(){
String []colNames = {"Subject","lecturer"};
String [][] rowDatas = { {"Java Programming","Jon"},
{"C++ Programming","Nuhara"},
{"Mathematicz","Mike"},
{"Database","Saran"}
};
table = new JTable(rowDatas,colNames);
button = new JButton("Show Last Record");
button.addActionListener(this);
this.add(table);
this.add(button);
this.setVisible(true);
this.setSize(300,200);
this.setDefaultCloseOperation(3);
this.setLayout(new FlowLayout());
}
#Override
public void actionPerformed(ActionEvent e) {
int i= table.getRowCount()-1;
int j= table.getColumnCount();
Object [] value = new Object[j];
for(int k = 0 ; k<j ; k++)
{
//value[k] = table.getValueAt(i,k);
System.out.println(table.getValueAt(i, k));
}
}
public static void main(String...ag){
new TableTest();
}
}

Making a wild guess that you are editing the last cell when you click on the "Submit" button.
If so then see: Table Stop Editing.

Thanks Azad,
Its working superb now...
I have a edited the code little bit to get data from all the rows...
int i= table.getRowCount()-1;
int j= table.getColumnCount();
for (int d=1;d<i+1;d++){ // will provide row wise data
for(int k = 0 ; k<j ; k++) // will provide column wise data
{
System.out.println("row num "+d+" "+model.getValueAt(d,k));
} }

Related

ListSelectionListener won't work propertly

Here is my code.
It got problem on while you selete from left to right..
import javax.swing.*;
import javax.swing.event.*;
public class swingex7 extends JFrame{
swingex7(){
JFrame f = new JFrame("Table Example");
String row[][]= {{"101","Hein Htet","10000000"},{"102","Hein Htet1","20000000"},{"103","Hein
Htet2","30000000"}};
String column[]= {"Id","Name","Salary"};
final JTable jt = new JTable(row,column);
jt.setCellSelectionEnabled(true);
ListSelectionModel lsm = jt.getSelectionModel();
lsm.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
lsm.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
String data=null;
int[] rows=jt.getSelectedRows();
int[] columns = jt.getSelectedColumns();
for(int i=0;i<rows.length;i++) {
for(int j=0;j<columns.length;j++) {
data = (String)jt.getValueAt(rows[i], columns[j]);
}
}
System.out.println("Table element seleted is "+data);
}
});
JScrollPane js = new JScrollPane(jt);
f.add(js);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(400, 400);
f.setVisible(true);
}
public static void main (String[]args) {
new swingex7();
}
}
It got problem on while you Selete from left to right.
I also want to output only once per action.
There are 2 problems in the code.
1.
First problem is ListSelectionListener is called 2 times when mouse is clicked and when mouse is released. But instead of that if you can add MouseListener to your JTable as below.
MouseListener tableMouseListener = new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
String data = null;
int[] rows = jt.getSelectedRows();
int[] columns = jt.getSelectedColumns();
for (int i = 0; i < rows.length; i++) {
for (int j = 0; j < columns.length; j++) {
data = (String) jt.getValueAt(rows[i], columns[j]);
System.out.println("Table element selected is " + data);
}
}
}
};
jt.addMouseListener(tableMouseListener);
2.
Second issue is the place where you printed the data. It should be inside the for loop. Otherwise the data will be rewritten in each iteration in the loop and only last value will be printed.
for (int i = 0; i < rows.length; i++) {
for (int j = 0; j < columns.length; j++) {
data = (String) jt.getValueAt(rows[i], columns[j]);
System.out.println("Table element selected is " + data);
}
}

Getting old values from Jtable

I am facing a strange problem with the Jtable. I have a small standalone java application in which I have used Jtable that shows data that is retrieved from database. User can view and edit the data. Once he edit the cell and presses the update button then the edited values will be updated in the database. Now what happening is for the first time when user edit the data and click on update button then the values are properly persisted in the database and user gets out of the module. But again if he/she goes to the same module and edits some more cells and click on update button then in back end i get old value from those cells although the Jtable shows the latest updated values in the cells.
Below is the code.
private JTable jt;
private TableRowSorter<TableModel> tableSorter;
private Dao dao=new Dao();
updateDetails.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
boolean isSuccessful = true;
int rowCount = jt.getRowCount();
List<EmployeeMaster> empMasterList = new ArrayList<>();
int j = 0;
for (int i = 0; i < rowCount; i++) {
EmployeeMaster master = new EmployeeMaster();
j = 0;
try {
master.setEmpId(Long.parseLong((String) jt.getValueAt(i, j)));
j++;
compId.setName(Long.parseLong((String) jt.getValueAt(i, j)));
j++;
compId.setNumber((String) jt.getValueAt(i, j));
j++;
empMasterList.add(master);
}
dao.updateAllEmpDetails(empMasterList);
homePanel.setVisible(true);
UpdateEmp.setVisible(false);
}
}
});
getDataFromDBtoJtable.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
List<EmployeeMaster> empMasterList = dao.getAllEmpDetails();
String data[][] = new String[empMasterList.size()][3];
int i = 0;
int j = 0;
for (EmployeeMaster employeeMaster : empMasterList) {
j = 0;
data[i][j] = String.valueOf(employeeMaster.getEmpId());
j++;
data[i][j] = String.valueOf(employeeMaster.getName());
j++;
data[i][j] = String.valueOf(employeeMaster.getNumber());
i++;
}
String column[] = { "ID", "Name", "Number"};
jt = new JTable(data, column) {
public boolean isCellEditable(int row, int column) {
if (column == 0 || column == 1 || column == 2)
return false;
else
return true;
};
};
tableSorter = new TableRowSorter<TableModel>(jt.getModel());
jt.setBounds(12, 12, 1200, 400);
jt.setRowSorter(tableSorter);
homePanel.setVisible(false);
UpdateEmp.setVisible(true);
JScrollPane pane = new JScrollPane(jt);
pane.setBounds(1, 40, 1150, 300);
setBounds(0, 0, 2000, 800);
UpdateEmp.add(pane);
}
});
updateDetails -> button to get the data from jtable and update it in database
getDataFromDBtoJtable -> button to get data from Database and show it in Jtable
Whenever user hits the updateDetails i am updating the database and forcing user to get out of the module. So everytime whenever user get into jtable module he/she gets new Jtable instance. But still unable to identify what's going wrong.

Why are all my ActionListener's added to JButtons in a loop identical?

Ok so I am trying to make a chess game in swing. I have a program that creates a 2d array of JButton's 8x8. I then create them all in a loop doing stuff like going back and forth between white/black and adding an action event. The problem i am having is that each button has the same action event and it is the event that is created last I.E. button on Row 8 column H is the action listener for all of the buttons in the array. Here is a snippet of code that is where I am creating the buttons and adding them.
I also have an Enum Columns that just goes from int to character 1 to H for example. selectPosition and targetPosition are objects that have two members columns and rows.
public void initializeGui(boolean isWhite) {
boolean shouldBeWhite = true;
for(int i = 0; i< 8; i++){
for(int j = 0; j < 8; j++){
column = i+1;
row = j+1;
JButton square = new JButton();
square.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
final int thisRow = row;
final int thisColumn = column;
selectPosition.setColumn(Columns.getColumnsFromInt(thisColumn));
selectPosition.setRow(thisRow);
if(isSelecting){
System.out.print("Selecting square to move. Row: " + thisRow + " Column: " + Columns.getColumnsFromInt(thisColumn));
selectPosition.setColumn(Columns.getColumnsFromInt(thisColumn));
selectPosition.setRow(thisRow);
} else{
System.out.print("Targeting square to move to. Row: " + thisRow + " Column: " + Columns.getColumnsFromInt(thisColumn) + "\n");
targetPosition.setColumn(Columns.getColumnsFromInt(thisColumn));
targetPosition.setRow(thisRow);
}
System.out.println("");
isSelecting = !isSelecting;
}
});
if(shouldBeWhite){
square.setBackground(Color.WHITE);
shouldBeWhite = false;
}else{
square.setBackground(Color.BLACK);
shouldBeWhite = true;
}
if (j == 7){
shouldBeWhite = !shouldBeWhite;
}
chessBoardSquares[i][j] = square;
gui.add(chessBoardSquares[i][j]);
}
}
if(isWhite){
setInitialPiecesWhiteStart();
}else{
setInitialPiecesBlackStart();
}
}
Further up as a member of this class are the following:
int column = 0, row = 0;
When I click on any of these buttons i see printed
Selecting square to move. Row: 8 Column: H
Targeting square to move to. Row: 8 Column: H
Selecting square to move. Row: 8 Column: H
Targeting square to move to. Row: 8 Column: H
and so on. My question is why are these buttons all given the same action event? My logic walk through would be something like create the first button set column = i+1 and row = j+1 then add an action listener with an action event that sets the current row/column values to the inner final variables and then prints out the thisRow and thisColumn associated with that action event. Am i overriding the values at the end or do i have the scope wrong? Basically how am i creating these buttons actions listeners incorrectly?
You could...
Use the actionCommand API to pass information between the button and the ActionListener...
JButton btn = new JButton();
btn.setActionCommand(row + "x" + column);
btn.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
//...
}
});
The problem here is you're relying on String parsing to extract the values, which can get messy quickly
You could...
Create a custom ActionListener which takes the values you want to use...
public class SquareActionListener implements ActionListener {
private int column;
private int row;
public SquareActionListener(int row, int column) {
this.row = row;
this.column = column;
}
#Override
public void actionPerformed(ActionEvent e) {
//...
}
}
This de-couples the ActionListener from the rest of the code and provides you the information you need, although, you may need to pass additional information (such as the model) as well for it to work
You could...
Make use of the Action API which is designed to be provide self contained units of work, it's generally a more re-usable solution, but might be a little beyond what you need right now
public class SquareAction extends AbstractAction {
private int column;
private int row;
public SquareAction(int row, int column) {
this.row = row;
this.column = column;
}
#Override
public void actionPerformed(ActionEvent e) {
//...
}
}
This looks alot like the last suggestion, but instead of adding it as the button's ActionListener, you actually apply it to the button directly...
JButton btn = new JButton(new SquareAction(row, column));
The button then uses other properties (which I've not set) to set itself up
I had the same issue when making a tic-tac-toe game. I used each button's hashcode to trace back which button was actually pushed. This is what my button setup looked like:
hashcodes= new ArrayList<Integer>();
for (int i=1;i<=9;i++) {
JButton button = new JButton();
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setHash(button.hashCode());
testWinner();
testDraw();
}
});
hashcodes.add(button.hashCode());
panel.add(button);
}
}
private void setHash(int hashcode) {
for (int h:hashcodes) {
if (h==hashcode) {
//do stuff
}
}
}
This is my Test class, and it works perfectly.
public class Test extends javax.swing.JFrame {
private javax.swing.JButton[][] buttons;
private final int ROW = 8;
private final int COLUMN = 8;
public Test() {
initComponents();
}
private void initComponents() {
this.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
this.setExtendedState(javax.swing.JFrame.MAXIMIZED_BOTH);
this.buttons = new javax.swing.JButton[ROW][COLUMN];
this.setLayout(new java.awt.GridLayout(ROW, COLUMN));
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COLUMN; j++) {
final int row = i;
final int column = j;
buttons[i][j] = new javax.swing.JButton(
String.format("Button %d-%d", i, j));
buttons[i][j].addActionListener(new java.awt.event.ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent e) {
// System.out.println(
// String.format("You have just pressed the button at row %d and column %d", row, column));
javax.swing.JOptionPane.showMessageDialog(
Test.this, String.format("You have just pressed the button at row %d and column %d", row, column));
}
});
this.add(buttons[i][j]);
}
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
new Test().setVisible(true);
}
}

Java Connect4 Game with GUI bug issues

http://imgur.com/a/V7LPP
Grid images are in the link
I have 2 main issues with my current connect4 code, sometimes the "AI" places 2 discs in one turn and the player can't fill the entire board without the "AI" entering an infinite loop. Any help is appreciated.
/**
* Auto Generated Java Class.
*/
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class EmptyFrame1 implements ActionListener
{
//Array of JButtons
static JButton [] mnuBtn = new JButton[2];
static JButton [] btnArray = new JButton[7];
static JLabel [][] board = new JLabel[6][7];
static int [][] numBoard = new int[6][7];
static int choice = 0;
static int playerColour = 1;
static int computerColour = 2;
static int computerTurn = 0;
static ImageIcon emptyGrid = new ImageIcon("EmptyGrid.png");
static ImageIcon yellowGrid = new ImageIcon("YellowGrid.png");
static ImageIcon redGrid = new ImageIcon("RedGrid.png");
static JPanel pnlBoard;
static boolean validTurn;
static int pieceCount = 42;
public EmptyFrame1()
{
JFrame game = new JFrame("Connect 4");
//mainFrame panel to hold all components
JPanel mainFrame = new JPanel();
pnlBoard = new JPanel();
pnlBoard.setLayout(new GridLayout(7,6));
//Change mainFrame layout to vertical BoxLayout
mainFrame.setLayout(new BoxLayout(mainFrame, BoxLayout.Y_AXIS));
//For every single button
//Set the button text to its index value, add an action listener and add it to the pnlButtons
for (int i = 0; i < btnArray.length; i++)
{
btnArray[i] = new JButton("place");
btnArray[i].addActionListener(this);
pnlBoard.add(btnArray[i]);
}//end for
for (int r = 0; r < board.length; r++)
{
for (int c = 0; c < board[r].length; c++)
{
board[r][c] = new JLabel(emptyGrid);
board[r][c].setPreferredSize(new Dimension(69, 69));
pnlBoard.add(board[r][c]);
}//end for
}//end for
//Add all the panels to the mainFrame panel
mainFrame.add(pnlBoard);
//add mainFrame to the JFrame
game.add(mainFrame);
game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Added this for security
game.pack();
game.setVisible(true);
game.setResizable(false);
}
//*Action listener for all buttons*
public void actionPerformed(ActionEvent e)
{
for (int i = 0; i < btnArray.length; i++)
{
//if the current button was triggered, set the choice to the button index
if (btnArray[i] == e.getSource())
{
choice = i;
colCheck(choice, 1);
//System.out.println("User turn used");
pieceCount--;
for (int j = 0; j < btnArray.length; j++)
{
if (numBoard[0][j] == 0) btnArray[j].setEnabled(true);
}
if (pieceCount > 0)
{
validTurn = false;
while(!validTurn)
{
computerTurn = (int) (Math.random() * 7);
System.out.print(computerTurn + " ");
validTurn = colCheck(computerTurn, 2);
//System.out.println("CPU tried to move");
}
}
System.out.println();
setGrid();
pieceCount--;
System.out.println(pieceCount);
validTurn = false;
}//end if
}//end for
pnlBoard.repaint();
}//end actionPerformed
public static boolean colCheck(int choice, int currentTurn)
{
int row = -1;
for (int r = 5; r >= 0; r--)
{
if (numBoard[r][choice] == 0)
{
row = r;
break;
}
}
//System.out.println("Row That CPU Chooses: " + row);
if (row > -1)
{
numBoard[row][choice] = currentTurn;
if (row == 0)
{
btnArray[choice].setEnabled(false);
return false;
}
return true;
}
return false;
}
public static void setGrid()
{
for (int r = 0; r < numBoard.length; r++)
{
for (int c = 0; c < numBoard[r].length; c++)
{
if (numBoard [r][c] == 0)
{
board[r][c].setIcon(emptyGrid);
}
else if (numBoard [r][c] == 1)
{
board[r][c].setIcon(redGrid);
}
else if (numBoard [r][c] == 2)
{
board[r][c].setIcon(yellowGrid);
}
}
}
}
/**
* Inner helper class that defines the graphics
*/
public static void main(String[] args)
{
new EmptyFrame1();
}
//end constructor
Some problems and suggestions:
Your colCheck method and the while (!validTurn) { loop in the actionPerformed method is where the problem is located.
This method should not set numBoard value or disable buttons. In other words, it should not have any "side effects".
Instead it should only check for validity and then return a boolean value, nothing more or less
You should have another method that is called first, one that checks if no valid columns are available, if the game is effectively over. This should be called before the while loop above and should prevent the while loop from entering. This will end your endless loop problem because it's looping because no valid columns can be found for the computer turn.
You should have another method for setting the numBoard state and for enabling and disabling JButtons.
Change your colCheck to this to see where the loop is coming from:
public static boolean colCheck(int choice, int currentTurn) {
int row = -1;
for (int r = 5; r >= 0; r--) {
if (numBoard[r][choice] == 0) {
row = r;
break;
}
}
// System.out.println("Row That CPU Chooses: " + row);
if (row > -1) {
numBoard[row][choice] = currentTurn;
if (row == 0) {
btnArray[choice].setEnabled(false);
System.out.printf("debug 1 row %d %n", row);
return false;
}
System.out.printf("debug 2 row %d %n", row);
return true;
}
System.out.printf("debug 3 row %d %n", row);
return false;
}
Other issues not directly related to your problem at hand, but which should be addressed
You're grossly over-using the static modifier, and in fact none of your fields should be static. All should be private instance fields.
You've got your program logic code, the model, mixed in the same class as the GUI, the view, making it hard to debug problems and enhance the program. Much better if you could make your model a completely separate class, one that is "view-agnostic" meaning that it is testable on its own and can work with any view, be it a command line or Swing or Android UI.
Your question depends on images, EmptyGrid.png, YellowGrid.png.... that we have no access to, preventing us from testing it.
You're using magic numbers, such as 0, 1, 2 for position values, and need to avoid doing this.
Instead use an enum for empty, user and computer
This is Java not Javascript. You'll want to be clear on the difference because they're two completely different languages.

JTable select and deselect not working

I have a problem with my JTable. Firstly I selected some entries in my table. However when I deselect some of them, the table could not understand it.
Example scenario: I select job1 and 2 for the testing after that I change my mind and de-select job2. But in the result I saw job1 job1 and job2 ( job 1 seen 2 times and even though I dis-select job 2 I saw them.) Or after selected all the jobs ( choose all button) I want to deselect all of them (Clear button) when I click clear all the table seems empty. It is good but somehow the background of the program still protect the all old selection. How can I solve this?
Try:
I created the row of my table by read csv file.
public class JobSelectionListPanel extends JPanel {
private static final long serialVersionUID = 5198916547962359735L;
private static JobSelectionListPanel INSTANCE = new JobSelectionListPanel();
public static JobSelectionListPanel getInstance() {
return INSTANCE;
}
private JTable table;
private JButton next, back, btnClear, btnNewButton, btnChooseAll;
private JobList fnnJobList = new JobList();
private JobSelectionListPanel() {
table = new JTable();
JScrollPane scrollPane = new JScrollPane(table);
table.setBorder(new CompoundBorder());
// Read all FNN jobs from file
try {
fnnJobList.readFromFile("rules.csv");
} catch (IOException e1) {
System.out.println("You are not able to read the rules.csv file");
}
// Create ArrayList of JobNames
Object[][] initialData = new Object[fnnJobList.size()][1];
int i = 0;
for (Job jobDes : fnnJobList) {
initialData[i][0] = (Object) jobDes.getJobname();
i++;
}
String[] columnNames = new String[] { "", "Your preferences" };
table.setModel(new DefaultTableModel(initialData, columnNames) {
private static final long serialVersionUID = 1L;
#SuppressWarnings("rawtypes")
Class[] columnTypes = new Class[] { Object.class, Boolean.class };
#SuppressWarnings({ "unchecked", "rawtypes" })
public Class getColumnClass(int columnIndex) {
return columnTypes[columnIndex];
}
});
table.getColumnModel().getColumn(1).setPreferredWidth(80);
table.getColumnModel().getColumn(1).setMinWidth(40);
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.setCellSelectionEnabled(true);
I user want to choose all rows then I implemented this.
btnChooseAll = new JButton("Choose all");
btnChooseAll.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultTableModel chooseAllData = (DefaultTableModel) table.getModel();
if (DeviceGroups.DeviceAList.size() == 0 || DeviceGroups.DeviceBList.size() == 0
|| DeviceGroups.DeviceCList.size() == 0 || DeviceGroups.DeviceDList.size() == 0)
JOptionPane.showMessageDialog(null,
"You should choose at least 1 device for each test device to apply this test case", "Invalid OPTION",
JOptionPane.ERROR_MESSAGE);
else
for (int i = 0; i < chooseAllData.getRowCount(); i++) {
for (int j = 1; j < chooseAllData.getColumnCount(); j++) {
chooseAllData.setValueAt(true, i, j);
}
}
}
});
For clear all preferences :
btnClear = new JButton("Clear all");
// Clear button create a model of JTable and delete all the rows of table!!
btnClear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultTableModel clearTableData = (DefaultTableModel) table.getModel();
for (int i = 0; i < clearTableData.getRowCount(); i++) {
for (int j = 1; j < clearTableData.getColumnCount(); j++) {
clearTableData.setValueAt(null, i, j);
}
}
}
});
I see the following problem in your code: mixing up view indexes and model indexes. This is the offending snippet:
for (int i = 0; i < table.getRowCount(); i++) {
if (table.getValueAt(i, 1) != null) {
if (((Boolean) table.getValueAt(i, 1)).booleanValue()) {
String jobName = (((DefaultTableModel) table.getModel()).getValueAt(i, 0).toString());
You are using the i variable to denote view row indices, since you are checking values in this statement: table.getValueAt(i, 1) != null.
But then a bit further you are using i to index the model:
String jobName = ((DefaultTableModel) table.getModel()).getValueAt(i, 0).toString();
If i is to be a view index, you need to convert it to a model index before indexing the model:
String jobName = ((DefaultTableModel) table.getModel()).getValueAt(table.convertRowIndexToModel(i), 0).toString();
Also, when columns would be switched around in the view (ie on screen in your GUI), the following will probably not work as intended:
table.getValueAt(i, 1) != null
You most likely mean to say, get the second column value in the model, not the view. Best rewrite then as
table.getValueAt(i, table.convertColumnIndexToView(1)) != null

Categories

Resources