Java JTable Default table model cell edit and column size - java

I have a problem in my code that when using cell edit not allowed then the column size does not work properly
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import java.awt.Dimension;
import java.util.ArrayList;
import javax.swing.table.DefaultTableModel;
import javax.swing.ListSelectionModel;
public class cTable extends JPanel {
private final int keyIndex;
private final int keyIncrement;
private ArrayList<String> tHeaderTitle;
private ArrayList<Integer> tHeaderWidth;
DefaultTableModel dataModel = new DefaultTableModel() {
#Override
public boolean isCellEditable(int rowIndex, int mColIndex) {
return false;
}
};
JTable table = new JTable(dataModel);
public cTable(ArrayList<String> THeaderTitle, ArrayList< Integer> THeaderWidth, int KeyIndex, int KeyIncrement) {
if (THeaderTitle.isEmpty()) {
tHeaderTitle.add("Title1");
} else {
tHeaderTitle = new ArrayList<>(THeaderTitle);
}
if (THeaderWidth.isEmpty()) {
tHeaderWidth.add(30);
} else {
tHeaderWidth = new ArrayList<>(THeaderWidth);
}
keyIndex = KeyIndex;
keyIncrement = KeyIncrement;
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setAutoscrolls(true);
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setAutoscrolls(true);
for (int i = 0; i < tHeaderTitle.size(); i++) {
dataModel.addColumn(tHeaderTitle.get(i));
table.getColumnModel().getColumn(i).setPreferredWidth(tHeaderWidth.get(i));
}
table.setPreferredScrollableViewportSize(new Dimension(TotalWidth(tHeaderWidth) + 110, 100));
table.getTableHeader().setResizingAllowed(false);
table.getTableHeader().setReorderingAllowed(false);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setRowHeight(25);
add(scrollPane);
}
public void addColumn(String cName, int cWidth) {
dataModel.addColumn(cName);
table.getColumnModel().getColumn(dataModel.getColumnCount() - 1).setPreferredWidth(cWidth);
table.setPreferredScrollableViewportSize(new Dimension(TotalWidth(tHeaderWidth) + cWidth, 150));
tHeaderWidth.add(cWidth);
}
public void addRow(String[] values) {
boolean exists = false;
if (dataModel.getRowCount() == 0) {
dataModel.addRow(values);
} else {
for (int i = 0; i < dataModel.getRowCount(); i++) {
if (dataModel.getValueAt(i, keyIndex) == values[keyIndex]) {
dataModel.setValueAt(Integer.valueOf(String.valueOf(dataModel.getValueAt(i, keyIncrement))) + 1, i, keyIncrement);
exists = true;
}
}
if (!exists) {
dataModel.addRow(values);
}
}
}
private int TotalWidth(ArrayList<Integer> wl) {
int sum = 0;
for (Integer wl1 : wl) {
sum += wl1;
}
return sum;
}
}
and in my main frame class mainClass I used the cTable component to create my customized table but the column size does not appear to be right , actually it does not work and the cells should be editable
import javax.swing.JPanel;
........
public class mainClass {
public static void main(String args[]) {
......
// initialize frame settings to add a cTable component
......
ArrayList<Integer> TheaderWidth = new ArrayList<>();
ArrayList<String> TheaderTitle = new ArrayList<>();
cTable InvTable;
TheaderTitle.add("id");
TheaderTitle.add("Qty");
TheaderTitle.add("Description");
TheaderTitle.add("Notes");
TheaderWidth.add(30);
TheaderWidth.add(50);
TheaderWidth.add(200);
TheaderWidth.add(100);
InvTable = new cTable(TheaderTitle, TheaderWidth, 1, 2);
InvTable.setBounds(10, 10, 600, 300);
panel1.add(InvTable);
InvTable.setVisible(true);
this.pack();
}
}

Related

FIXED: Java Memory Game - Java Will not display other images

UPDATE: I just coded each button manually. Thanks Anyways.
I am trying to make a Memory Game written in Java. For some reason Java renders all the images as the same. It appears to render the latest image to all buttons when clicked.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import java.util.ArrayList;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
/**
* #author Steven
*
*/
public class Memory extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
private static final int GRIDSIZE = 4;
private PicButton[][] liteBut = new PicButton[GRIDSIZE][GRIDSIZE];
private Random rand = new Random();
private ClassLoader cl = this.getClass().getClassLoader();
private String[] imagelist = {"images/image01.jpg", "images/image02.jpg", "images/image03.jpg", "images/image04.jpg"};
private ArrayList<String> images = new ArrayList<String>();
private volatile String icon = "";
public Memory() {
initGUI();
setTitle("Memory");
setResizable(false);
pack();
setLocationRelativeTo(null);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void initGUI() {
assignimages();
TitleLabel framedTitle = new TitleLabel("Memory");
add(framedTitle, BorderLayout.PAGE_START);
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new GridLayout(GRIDSIZE, GRIDSIZE));
add(centerPanel, BorderLayout.CENTER);
for (int row = 0; row < GRIDSIZE; row++) {
for (int col = 0; col < GRIDSIZE; col++) {
liteBut[row][col] = new PicButton(row, col);
if (row == 0) {
if (col == 0) {
icon = images.get(0);
System.out.println(icon);
} else if (col == 1) {
icon = images.get(1);
System.out.println(icon);
} else if (col == 2) {
icon = images.get(2);
System.out.println(icon);
} else if (col == 3) {
icon = images.get(3);
System.out.println(icon);
}
} else if (row == 1) {
if (col == 0) {
icon = images.get(0);
System.out.println(icon);
} else if (col == 1) {
icon = images.get(1);
System.out.println(icon);
} else if (col == 2) {
icon = images.get(2);
System.out.println(icon);
} else if (col == 3) {
icon = images.get(3);
System.out.println(icon);
}
}
liteBut[row][col].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
PicButton button = (PicButton) e.getSource();
int row = button.getRow();
int col = button.getCol();
String id = button.getID();
System.out.println("Hi from " + id);
liteBut[row][col].setIcon(new ImageIcon(cl.getResource(icon)));
}
});
centerPanel.add(liteBut[row][col]);
}
}
}
private void assignimages() {
for (int x = 0; x < 4; x++) {
int i = rand.nextInt(GRIDSIZE);
images.add(imagelist[i]);
}
for (int x = 0; x < images.size(); x++) {
System.out.println(images.get(x));
}
}
public static void main(String[] args) {
try {
String className = UIManager.getCrossPlatformLookAndFeelClassName();
UIManager.setLookAndFeel(className);
} catch (Exception e) {
}
EventQueue.invokeLater(new Runnable() {
public void run() {
new Memory();
}
});
}
public class PicButton extends JButton {
private static final long serialVersionUID = 1L;
private static final int MAXSIZE = 150;
private int row = 0;
private int col = 0;
private String id = "";
//private Boolean hasPic;
public PicButton(int row, int col) {
this.row = row;
this.col = col;
id = Integer.toString(row) + Integer.toString(col);
System.out.println(id);
setBackground(Color.BLACK);
Dimension size = new Dimension(MAXSIZE, MAXSIZE);
setPreferredSize(size);
}
public int getRow() {
return row;
}
public int getCol() {
return col;
}
public String getID() {
return id;
}
public void setImage() {
setBackground(Color.RED);
//hasPic = true;
}
public void clearImage() {
setBackground(Color.BLACK);
//hasPic = false;
}
}
public class TitleLabel extends JLabel {
private static final long serialVersionUID = 1L;
public TitleLabel(String title) {
Font titleFont = new Font(Font.SERIF, Font.BOLD, 32);
setFont(titleFont);
setHorizontalAlignment(JLabel.CENTER);
setText(title);
setBackground(Color.BLACK);
setForeground(Color.WHITE);
setOpaque(true);
}
}
}
liteBut[row][col].setIcon(new ImageIcon(cl.getResource(icon)));
is assigning the last known value of icon as the image to the button (this is an instance field, so it remembers), this is not the "value" assigned to the button, but the last value assigned to icon by the for-loop in which you create the buttons, so basically, ALL the buttons will get the last icon, instead, supply the icon value the PictureButton itself so you can "update" the button when it's clicked.
This functionality could be self contained to the button itself, further making it easier to manage

Java JTable mistake in copying rows

Good day!
There is a problem in downloaded program. You can copy a row by clicking on it by right mouse button, but after that when you change data in one cell data will be changed in every cell in column. Please, help me to understand, what I've missed.
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
public class Main extends JFrame{
JMenuItem obrc;
JTable table;
DataModel tm;
JScrollPane scrollTable;
Main() {
super("Example JTable");
Container c = getContentPane();
ArrayList<String> columnNames = new ArrayList<String>();
columnNames.add("Type"); columnNames.add("Sort"); columnNames.add("Thickness"); columnNames.add("Width");
tm = new DataModel(columnNames);
table = new JTable(tm);
c.add(new JScrollPane(table), BorderLayout.CENTER);
setSize(400, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
table.getColumnModel().getColumn(0).setPreferredWidth(40);
table.getColumnModel().getColumn(1).setPreferredWidth(40);
table.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent event) {
if (SwingUtilities.isRightMouseButton(event)) {
JPopupMenu obrcd = new JPopupMenu();
obrc = new JMenuItem("Copy");
obrc.addActionListener(new MenuListener());
obrcd.add(obrc);
obrcd.show(c, event.getX(), event.getY());
}
}
});
}
public class MenuListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
int[] nums = table.getSelectedRows();
if (nums.length != 0) {
if (e.getSource() == obrc) {
ArrayList<Object[]> list = tm.getRows(nums);
tm.addRows(list);
}
else JOptionPane.showMessageDialog(null,
"Select at least one row", "Warning", JOptionPane.ERROR_MESSAGE);
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Main();
}
});
}
class DataModel extends AbstractTableModel{
ArrayList<Object[]> data = new ArrayList<Object[]>();
ArrayList<String> columnNames = new ArrayList<String>();
public DataModel(ArrayList<String> cNames){
super();
columnNames = cNames;
Object[] dat = new Object[4];
dat[0] = "board";
dat[1] = "1";
dat[2] = "25";
dat[3] = "150";
data.add(dat);
}
public boolean isCellEditable(int rowIndex, int columnIndex)
{
return true;
}
public Object getValueAt(int rowIndex, int columnIndex){
Object[] row = data.get(rowIndex);
return row[columnIndex];
};
public void setValueAt(Object newValue, int rowIndex, int columnIndex){
data.get(rowIndex)[columnIndex] = newValue;
fireTableDataChanged();
}
public int getRowCount()
{
return data.size();
};
public int getColumnCount()
{
return columnNames.size();
};
public String getColumnName(int column)
{
return columnNames.get(column);
}
public ArrayList<Object[]> getRows(int[] nums) {
ArrayList<Object[]> newdata = new ArrayList<Object[]>();
for (int i = 0; i < nums.length; i++) {
newdata.add(data.get(nums[i]));
}
return newdata;
}
public void addRows (ArrayList<Object[]> rows) {
for (int i = 0; i < rows.size(); i++) data.add(rows.get(i));
fireTableDataChanged();
}
}
}
Problem when you are adding new rows
public void addRows (ArrayList<Object[]> rows) {
for (int i = 0; i < rows.size(); i++) data.add(rows.get(i));
fireTableDataChanged();
}
Your copied row(s) will point to same object(s) with selected row(s). You need clone to new object:
public void addRows (ArrayList<Object[]> rows) {
for (int i = 0; i < rows.size(); i++) {
Object[] clone = rows.get(i).clone();
data.add(clone);
}
fireTableDataChanged();
}

Getting single INT value from jTable

I have a table with two values: A and B
Is it possible to get A as int using getSelectedRow()?
At this moment I got this, it cannot find symbol for variable A
DefaultTableModel tm = (DefaultTableModel)jTabela.getModel();
int A = Integer.parseInt( tm.getValueAt(jTabela.A, getSelectedRow()).toString() );
You're putting the row number into the wrong parameter. Per the JTable API the getValueAt(...) method takes two int parameters, the first of which is the row index and the second is the column index. So you'll want something like:
DefaultTableModel tm = (DefaultTableModel)jTabela.getModel();
int row = tm.getSelectedRow();
if (row == -1) {
return;
}
Object value = jTabela.getValueAt(row, whateverYourColumnIs);
int intValue = value != null ? Integer.parseInt(value.toString()) : 0;
For example:
import java.awt.BorderLayout;
import java.util.Vector;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
#SuppressWarnings("serial")
public class TableExample extends JPanel {
private static final String[] COLUMNS = {"Name", "Value"};
private DefaultTableModel model = new DefaultTableModel(COLUMNS, 0) {
public java.lang.Class<?> getColumnClass(int columnIndex) {
Object value = getValueAt(0, columnIndex);
if (value == null) {
return super.getColumnClass(columnIndex);
} else {
return value.getClass();
}
};
};
private JTable table = new JTable(model);
public TableExample() {
for (int i = 0; i < 10; i++) {
String name = "Row " + (i + 1);
int value = (i + 1) * 10;
Vector<Object> row = new Vector<>();
row.add(name);
row.add(value);
model.addRow(row);
}
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting()) {
return;
}
int row = table.getSelectedRow();
if (row == -1) {
return;
}
Object value = table.getValueAt(row, 1); // numbers are in row 1
if (value != null) {
System.out.println("Selected value: " + value);
int intValue = Integer.parseInt(value.toString());
// can use value here
}
}
});
setLayout(new BorderLayout());
add(new JScrollPane(table));
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Table Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new TableExample());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

How to change rows with columns in JTable?

I have created my JTable like this:
String[] columns = {"Country", "Continent", "Latitude", "Longitude"};
String[][] data = {{"A","B","C","D"}};
table = new JTable(data,columns);
JScrollPane spTable = new JScrollPane(table);
panel2.add(spTable);
Now I want to change the look of the table in such a way that rows will be exchanged with columns, meaning that the table will have 4 rows and 1 column. Could not find such function between member methods, is it possible? Thanks.
To do that, I would consider a custom TableModel which can handle a "toggled" state.
From your example, the result may be surprizing but this code shows you the general idea and allows you to swap rows and columns with a button.
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
public class TestTable {
private static class TogglingTableModel extends AbstractTableModel {
private boolean toggled = false;
private final Object[][] data;
private final Object[] columnNames;
public TogglingTableModel(Object[][] data, Object[] columnNames) {
this.columnNames = columnNames;
this.data = data;
normalizeData();
}
private void normalizeData() {
for (int i = 0; i < data.length; i++) {
Object[] o = data[i];
if (o.length < columnNames.length) {
data[i] = Arrays.copyOf(o, columnNames.length);
}
}
}
#Override
public String getColumnName(int column) {
if (toggled) {
Object valueAt;
if (column == 0) {
valueAt = columnNames[0];
} else {
valueAt = data[column - 1][0];
}
return valueAt != null ? valueAt.toString() : null;
} else {
Object object = columnNames[column];
return object != null ? object.toString() : null;
}
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
#Override
public int getColumnCount() {
if (toggled) {
return data.length + 1;
} else {
return columnNames.length;
}
}
#Override
public int getRowCount() {
if (toggled) {
return columnNames.length - 1;
} else {
return data.length;
}
}
#Override
public Object getValueAt(int row, int column) {
if (toggled) {
if (column == 0) {
return columnNames[row + 1];
} else {
return data[column - 1][row + 1];
}
} else {
return data[row][column];
}
}
#Override
public void setValueAt(Object aValue, int row, int column) {
if (toggled) {
if (column == 0) {
columnNames[row + 1] = aValue;
} else {
data[column - 1][row + 1] = aValue;
}
} else {
data[row][column] = aValue;
}
}
public boolean isToggled() {
return toggled;
}
public void toggle() {
toggled = !toggled;
fireTableStructureChanged();
}
}
private TogglingTableModel tableModel;
public TestTable() {
JFrame frame = new JFrame(TestTable.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] columns = { "Country", "Continent", "Latitude", "Longitude" };
String[][] data = { { "A" }, { "B" }, { "C" }, { "D" }, { "E" } };
tableModel = new TogglingTableModel(data, columns);
JTable table = new JTable(tableModel);
JPanel buttonPanel = new JPanel();
JButton togglingButton = new JButton("Toggle table");
togglingButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
tableModel.toggle();
}
});
buttonPanel.add(togglingButton);
frame.add(new JScrollPane(table));
frame.add(buttonPanel, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
TestTable fs = new TestTable();
}
});
}
}

row selection not moving with row moves in JTable

I have following code:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import javax.swing.table.DefaultTableModel;
public class NewClass1 extends JFrame {
private JTable table;
private JScrollPane scrollPane;
private DefaultTableModel defaultTableModel;
public NewClass1() {
setLocationByPlatform(true);
setLayout(new BorderLayout());
setPreferredSize(new Dimension(600, 400));
setTitle("Table Issues");
setDefaultCloseOperation(EXIT_ON_CLOSE);
createTableModel();
table = new JTable(defaultTableModel);
scrollPane = new JScrollPane(table);
getContentPane().add(scrollPane, BorderLayout.CENTER);
pack();
}
private void createTableModel() {
Vector cols = new Vector();
cols.add("A");
Vector rows = new Vector();
for (int i = 0; i < 50; i++) {
Vector row = new Vector();
row.add((i + 1) + "");
rows.add(row);
}
defaultTableModel = new DefaultTableModel(rows, cols) {
Class[] types = new Class[]{
String.class
};
#Override
public Class getColumnClass(int columnIndex) {
return types[columnIndex];
}
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(new NimbusLookAndFeel());
} catch (Exception e) {
}
final NewClass1 nc = new NewClass1();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
nc.setVisible(true);
}
});
while (true) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
int row = (int) (Math.random() * 50);
int move = (int) (Math.random() * 50);
nc.defaultTableModel.moveRow(row, row, move);
}
});
try{
Thread.sleep(1000);
}catch(Exception e){
}
}
}
}
Please run the above code and select row.
My problem is with row movement, row selection is not moving. It is staying at fixed position. Suppose I selected row with column value 25, selected row must be of column value 25 after row movements.
Please help me on this.
My real problem is, user will select row and clicks menu to perform action, meanwhile other threads may have moved rows, and performed action will be on other row than actual one.
The easiest way is to remember the selected row somewhere outside of the ListSelectionModel and adjust the selection whenever the TableModel changes. For example you could do this:
public class NewClass1 extends JFrame {
private JTable table;
private DefaultTableModel defaultTableModel;
private JScrollPane scrollPane;
private class SelectionHelper implements ListSelectionListener, TableModelListener {
private Object selectedRow;
#Override
public void valueChanged(ListSelectionEvent event) {
if (!event.getValueIsAdjusting()) return;
int selectedIndex = table.getSelectedRow();
if (selectedIndex >= 0) {
selectedRow = defaultTableModel.getDataVector().get(selectedIndex);
} else {
selectedRow = null;
}
}
#Override
public void tableChanged(TableModelEvent event) {
if (selectedRow == null) return;
int selectedIndex = defaultTableModel.getDataVector().indexOf(selectedRow);
table.getSelectionModel().setSelectionInterval(selectedIndex, selectedIndex);
}
}
public NewClass1() {
// ...
createTableModel();
table = new JTable(defaultTableModel);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
SelectionHelper helper = new SelectionHelper();
table.getModel().addTableModelListener(helper);
table.getSelectionModel().addListSelectionListener(helper);
// ...
}
// ...
}
Note however, that you should adjust this code for production use, for example in regards to thread safety or portability (using the table and defaultTableModel attributes in the inner class is bad style).

Categories