What I'm trying to do:
I want to have two JTables side by side, and when you make a selection on the left JTable you see more detailed information about that row in the JTable to the right.
What's my problem?:
I have no idea how to implement this. I have tried using the addListSelectionListener, but I'm unsure on how I can use a listener from one table to interact with a completely different table. Such as, having the listener replace table2 with a new table that has completely new data.
I've included an SSCCE which shows the gist of what I did. I would appreciate any help, as I've been scouring the internet trying to piece this problem together.
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
public class TableInteraction extends JPanel
{
private JTable table1;
private JTable table2;
public TableInteraction()
{
super();
String[][] tableOneData = {{"Kathy", "Smith"}};
String[][] tableTwoData = {{"Kathy", "Smith"}};
String[][] tableThreeData = {{"Matt", "Bird"}};
setLayout(new BorderLayout());
FirstTableModel model1 = new FirstTableModel(tableOneData);
table1 = new JTable(model1);
table1.setPreferredScrollableViewportSize(new Dimension(500,200));
table1.setFillsViewportHeight(true);
table1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table1.setRowSelectionInterval(0,0);
JScrollPane scrollPane1 = new JScrollPane(table1);
SecondTableModel model2 = new SecondTableModel(tableTwoData);
table2 = new JTable(model2);
table2.setPreferredScrollableViewportSize(new Dimension(500,200));
table2.setFillsViewportHeight(true);
table2.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JScrollPane scrollPane2 = new JScrollPane(table2);
table1.getSelectionModel().addListSelectionListener(
new ListSelectionListener()
{
public void valueChanged(ListSelectionEvent event)
{
int index = table1.getSelectedRow();
}
});
add(scrollPane1, BorderLayout.WEST);
add(scrollPane2, BorderLayout.EAST);
}
public class FirstTableModel extends AbstractTableModel
{
private String[] columnNames = {"First Name", "Last Name"};
private String[][] data;
public FirstTableModel(String[][] data)
{
this.data = data;
}
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
return data.length;
}
public String getColumnName(int col) {
return columnNames[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
}
public class SecondTableModel extends AbstractTableModel
{
private String[] columnNames = {"First Name", "Last Name"};
private String[][] data;
public SecondTableModel(String[][] data)
{
this.data = data;
}
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
return data.length;
}
public String getColumnName(int col) {
return columnNames[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("TableFilterDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TableInteraction newContentPane = new TableInteraction();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Consider this (extension of my comment)
private String[] columnNames1 = {"First Name", "Last Name"};
private String[][] data1 = {{"Kathy", "Smith"},{"John","Doe"}};
private String[] columnNames2 = {"First Name", "Last Name"};
private String[][] data2 = {{"Kathy", "Smith"},{"John","Doe"}};
DefaultTableModel tableModel1 = new DefaultTableModel(data1, columnNames1);
DefaultTableModel tableModel2 = new DefaultTableModel(data2, columnNames2);
JTable jTable1 = new JTable(tableModel1);
JTable jTable2 = new JTable(tableModel1);
jTable1.getSelectionModel().addListSelectionListener(
new ListSelectionListener()
{
public void valueChanged(ListSelectionEvent event)
{
int index = jTable1.getSelectedRow();
jTable2.removeRow(index);
}
});
When a row from table1 is selected, The same row from table2 is deleted. This is a bizarre example that would not work without some null checks, but it shows how two tables can interact using the table model
Edit: with OP added comment
If you want to set the second table based on the first table, you can do something like this
jTable2.setModel(jTable1.getModel());
Also, you should place you listener AFTER creating tables and models, so that you can can use the model. If they haven't been declared yet, you cant use them in the listener, unless they are declared as global
Related
I have two JTables, and they are set up so that you can drag and drop the rows within each JTable. The problem is that it lets me drag a row from one JTable to the other JTable, and I am trying to figure out how to stop that. I only want the user to be able to drag and drop a row within that same JTable.
In other words, when I drag a row outside the current table and hover the mouse over the empty panel space, the mouse cursor displays a circle with a diagonal line through it, which is what I want. However, when I drag the mouse over the other table, it displays the small rectangular "drop" icon, which is what I am trying to block. When the user tries to drag this row on top of other table, I would like the small circle with diagonal line to appear.
This is a working example that demonstrates the problem:
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DragSource;
import java.util.ArrayList;
import java.util.List;
import javax.activation.ActivationDataFlavor;
import javax.activation.DataHandler;
import javax.swing.DropMode;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;
import javax.swing.table.AbstractTableModel;
public class JTableDnD extends JFrame
{
private JTable tableA;
private JTable tableB;
public JTableDnD()
{
// *** Create First Table ***
List<Object[]> dataA = new ArrayList<Object[]>();
dataA.add(new Object[] {"A1", "A1"});
dataA.add(new Object[] {"A2", "A2"});
dataA.add(new Object[] {"A3", "A3"});
List<String> columnsA = new ArrayList<String>();
columnsA.add("Column 1");
columnsA.add("Column 2");
tableA = new JTable(new TableModel(columnsA, dataA));
tableA.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
tableA.setDragEnabled(true);
tableA.setDropMode(DropMode.INSERT_ROWS);
tableA.setFillsViewportHeight(true);
tableA.setTransferHandler(new TableTransferHandler(tableA));
JScrollPane scrollPaneA = new JScrollPane(tableA);
// *** Create Second Table ***
List<Object[]> dataB = new ArrayList<Object[]>();
dataB.add(new Object[] {"B1", "B1"});
dataB.add(new Object[] {"B2", "B2"});
dataB.add(new Object[] {"B3", "B3"});
List<String> columnsB = new ArrayList<String>();
columnsB.add("Column 1");
columnsB.add("Column 2");
tableB = new JTable(new TableModel(columnsB, dataB));
tableB.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
tableB.setDragEnabled(true);
tableB.setDropMode(DropMode.INSERT_ROWS);
tableB.setFillsViewportHeight(true);
tableB.setTransferHandler(new TableTransferHandler(tableB));
JScrollPane scrollPaneB = new JScrollPane(tableB);
// *** Add ScrollPanes to Panel ***
this.getContentPane().setLayout(new FlowLayout());
add(scrollPaneA);
JPanel emptyPanel = new JPanel();
emptyPanel.setPreferredSize(new Dimension(100, 200));
add(emptyPanel);
add(scrollPaneB);
} // end JTableDnD constructor
private static void createAndShowGUI()
{
JFrame frame = new JTableDnD();
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
interface Reorderable
{
public void reorder(int from, int to);
}
class TableModel extends AbstractTableModel implements Reorderable
{
private List<String> columnNames;
private List<Object[]> data;
public TableModel(List<String> columnNames, List<Object[]> data)
{
super();
this.columnNames = columnNames;
this.data = data;
}
#Override
public void reorder(int from, int to)
{
if (from < to)
{
to--;
}
Object[] row = data.remove(from);
data.add(to, row);
fireTableDataChanged();
}
#Override
public int getRowCount()
{
return data.size();
}
#Override
public int getColumnCount()
{
return columnNames.size();
}
#Override
public String getColumnName(int column)
{
return columnNames.get(column);
}
#Override
public Object getValueAt(int rowIndex, int columnIndex)
{
return data.get(rowIndex)[columnIndex];
}
} // end TableModel
class TableTransferHandler extends TransferHandler
{
private final DataFlavor localObjectFlavor = new ActivationDataFlavor(Integer.class, DataFlavor.javaJVMLocalObjectMimeType, "Integer Row Index");
private JTable table = null;
public TableTransferHandler(JTable table)
{
this.table = table;
}
#Override
protected Transferable createTransferable(JComponent component)
{
return new DataHandler(new Integer(table.getSelectedRow()), localObjectFlavor.getMimeType());
}
#Override
public boolean canImport(TransferHandler.TransferSupport support)
{
boolean b = support.getComponent() == table &&
support.isDrop() &&
support.isDataFlavorSupported(localObjectFlavor);
table.setCursor(b ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop);
return b;
}
#Override
public int getSourceActions(JComponent component)
{
return TransferHandler.COPY_OR_MOVE;
}
#Override
public boolean importData(TransferHandler.TransferSupport support)
{
JTable target = (JTable) support.getComponent();
JTable.DropLocation dropLocation = (JTable.DropLocation) support.getDropLocation();
int index = dropLocation.getRow();
int max = table.getModel().getRowCount();
if (index < 0 || index > max)
{
index = max;
}
target.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
try
{
Integer rowFrom = (Integer) support.getTransferable().getTransferData(localObjectFlavor);
if (rowFrom != -1 && rowFrom != index)
{
((Reorderable) table.getModel()).reorder(rowFrom, index);
if (index > rowFrom)
{
index--;
}
target.getSelectionModel().addSelectionInterval(index, index);
return true;
}
}
catch (Exception e)
{
e.printStackTrace();
}
return false;
}
#Override
protected void exportDone(JComponent component, Transferable transferable, int action)
{
if (action == TransferHandler.MOVE)
{
table.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
} // end TableTransferHandler
I believe I need to add some extra logic to the canImport() method to make sure that the row that is being dropped is from that same table, but I can't seem to figure it out. I've tried inspecting the data inside the TransferSupport object that gets passed into canImport(), but it does not seem to have any function that returns the exact JTable object source.
In the simplified Swing DnD, there is no support for getting at the source of the transferable. The component returned by TransferSupport` is the target of the drop, that is the component that somehow should handle the associated transferable. So if you have a per-component TransferHandler configured with a particular table, the support's component will always be that same table instance and your check will be true trivially.
If you want to enable/disable dropping based on the sender, you'll have to provide it on a per-drag basis: a drag starts in exportAsDrag and ends in exportDone, so you can set/null the sender in those.
#Override
protected void exportDone(JComponent component,
Transferable transferable, int action) {
table = null;
}
#Override
public void exportAsDrag(JComponent comp, InputEvent e, int action) {
table = (JTable) comp;
super.exportAsDrag(comp, e, action);
}
Now you can re-use the same instance of the handler across several instances of table:
TableTransferHandler handler = new TableTransferHandler();
tableA.setTransferHandler(handler);
tableB.setTransferHandler(handler);
As an aside: I wouldn't fiddle with the cursors, they are supporsed to be under complete control of the dnd subsystem.
I'm trying to get a jtable to contain combo boxes for one of it's columns but it doesn't work, it just appears as a normal table cells. at the moment i'm following oracle's example: http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/components/TableRenderDemoProject/src/components/TableRenderDemo.java
I tried all the topics posted here about this and various methods as well, i got it to work once but lost it after i tried a different method.
What am i doing wrong?
I'm not including all the code, it's way too long, just the relevant part.
clientsTable has been declared before as a jTable.
// Define Table model for clients table
class ClientsTableModel extends DefaultTableModel {
public ClientsTableModel(Vector<Vector<String>> clientsDataVector,
Vector<String> clientColumNamesVector) {
super(clientsDataVector, clientColumNamesVector);
}
#Override
public int getColumnCount() {
return clientColumNames.length;
}
#Override
public int getRowCount() {
return clientsDataVector.size();
}
#Override
public String getValueAt(int row, int column) {
return clientsDataVector.get(row).get(column);
}
#Override
public void setValueAt(Object aValue, int row, int column) {
clientsDataVector.get(row).set(column, (String) aValue);
}
#Override
public Class<?> getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
}
// create table model and add to clients table
clientColumNames = new String[] { "ID", "Name", "Type", "Address",
"Email", "Phone", "Comment" };
clientColumNamesVector = new Vector<String>(
Arrays.asList(clientColumNames));
clientsDataVector = new Vector<Vector<String>>(1, 1);
clientsTableModel = new ClientsTableModel(clientsDataVector,
clientColumNamesVector);
clientsTableModelEvent = new TableModelEvent(clientsTableModel);
clientsTableModel.addTableModelListener(new TableModelListener() {
#Override
public void tableChanged(TableModelEvent arg0) {
}
});
// create clients table and set type column to be combo box
String[] clientTypes = { "REGULAR", "GOLD", "PLATINUM" };
clientsTable = new JTable(clientsTableModel);
clientsTable.setAutoCreateRowSorter(true);
clientsTable.setFillsViewportHeight(true);
JComboBox clientsTypeComboBox = new JComboBox(clientTypes);
TableColumn clientsTypeColumn = clientsTable.getColumnModel().getColumn(2);
clientsTypeColumn.setCellEditor(new DefaultCellEditor(clientsTypeComboBox));
DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer();
// create client scroll pane
JScrollPane clientsScrollPane = new JScrollPane(clientsTable);
GridBagConstraints gbc_clientsScrollPane = new GridBagConstraints();
gbc_clientsScrollPane.insets = new Insets(0, 0, 5, 0);
gbc_clientsScrollPane.fill = GridBagConstraints.BOTH;
gbc_clientsScrollPane.gridx = 0;
gbc_clientsScrollPane.gridy = 0;
viewClientsPanel.add(clientsScrollPane, gbc_clientsScrollPane);
it just appears as a normal table cells.
It occures, because you have default renderer for your column. When you start to edit, column shows as JComboBox, because you set DefaultCellEditor with JComboBox. If you want to render cells as JComboBox always, you can implement a TableCellRenderer for custom view of cell, read tutorial for that. Here is simple example for you:
import java.awt.Component;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
public class Example extends JFrame {
public Example() {
DefaultTableModel m = new DefaultTableModel(new Object[][]{{"2",2,3},{"1",4,5}},new Object[]{1,2,3});
JTable t = new JTable(m);
t.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(new JComboBox(new Object[]{"1","2"})));
t.getColumnModel().getColumn(0).setCellRenderer(getCellRenderer());
t.setRowHeight(25);
getContentPane().add(new JScrollPane(t));
pack();
}
private TableCellRenderer getCellRenderer() {
return new TableCellRenderer() {
JComboBox box = new JComboBox(new Object[]{"1","2"});
#Override
public Component getTableCellRendererComponent(JTable arg0, Object arg1,boolean arg2, boolean arg3, int arg4, int arg5) {
box.setSelectedItem(arg1);
return box;
}
};
}
public static void main(String[] args) throws InterruptedException {
Example ex = new Example();
ex.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ex.setVisible(true);
}
}
and its look like next:
thank you for your answers, i actually managed to find what was wrong.
i endded up using tableCellEditor and u made my combobox to implement tablecellrenderer, which i tried before but the main thing that i didn't do is to override jtable getcellrendere/editor methods:
clientsTable = new JTable(clientsTableModel){
#Override
public TableCellEditor getCellEditor(int row, int col) {
if (col==2) return clientsTypeCellEditor;
return super.getCellEditor(row, col);
}
#Override
public TableCellRenderer getCellRenderer(int arg0, int arg1) {
// TODO Auto-generated method stub
return super.getCellRenderer(arg0, arg1);
}
};
I need help at adding a empty row to my JTable. I use a AbstractTableModel for my JTable! I have here a small executable program for you so it is easier to help me.
Main Class - TestClass.java
package testproject;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JTable;
public class TestClass {
String[] header = {"Name", "Quantity"};
ArrayList<Object[]> data = new ArrayList<Object[]>();
public TestClass() {
data.add(new Object[]{"Apple", "234"});
data.add(new Object[]{"Banana", "123"});
data.add(new Object[]{"Cranberry", "346"});
JFrame frame = new JFrame();
JTable table = new JTable(new Model(data, header));
JMenuBar menubar = new JMenuBar();
JMenu editmenu = new JMenu("Edit");
Action addrowaction = new AbstractAction("Add Row") {
private static final long serialVersionUID = 1433684360133156145L;
#Override
public void actionPerformed(ActionEvent e) {
data.add(new Object[9]);
}
};
frame.add(table);
frame.setJMenuBar(menubar);
menubar.add(editmenu);
editmenu.add(addrowaction);
frame.setLocationByPlatform(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.pack();
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TestClass();
}
});
}
}
Table Model - Model.java
package testproject;
import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
public class Model extends AbstractTableModel{
private static final long serialVersionUID = 6889542282067432083L;
private String[] header;
private ArrayList<Object[]> data;
public Model(ArrayList<Object[]> data, String[] header) {
this.header = header;
this.data = data;
}
#Override
public int getColumnCount() {
return header.length;
}
#Override
public String getColumnName(int column) {
return header[column];
}
#Override
public int getRowCount() {
return data.size();
}
#Override
public Object getValueAt(int row, int column) {
return data.get(row)[column];
}
#Override
public void setValueAt(Object value, int row, int column) {
data.get(row)[column] = value;
fireTableCellUpdated(row, column);
}
}
Basically I want to use a Action in the edit menu to add a empty row. Please do not answer with other links! I searched for it but don't understand it or it isnt suitable for my program!
EDIT:
Updated the source as suggested by MadProgrammer! There is only one problem left. How I update the JTable so the new Row is displayed at the moment I have to resize the Window and the Table is updating!
Thank you for help
As #MadProgrammer comments, arrays are conceptually easy to understand but hard to expand & contract. Instead, use a Collection. In this example, MyModel manages a List<Row> that is implemented as an ArrayList<Row>. Each Row is a Plain Old Java Object (POJO) having an attribute for each column. Try adding a method to insert new rows using the constructor as an example, then try adding a column to Row. The example uses a static nested class to avoid clutter.
I have a JTable with a column containing a JComboBox.
I have an ItemListener attached to the JComboBox which acts upon any changes.
However, ItemListener does not have a method for obtaining the Row that the changed ComboBox is within.
I need to Row number in order to act upon another column in the same row when the ComboBox has a change.
Any help would be appreciated.
This is my Short and Concise code. What I am trying to accomplish, is obtaining the Table Row of the ComboBox when a the itemlistener picks up a change.
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.IOException;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
public class Example extends JFrame {
private static final long serialVersionUID = 1L;
public static int maxX, maxY;
public static final String[] columnHeads = {"Col 1", "Col 2", "Col 3"};
public static void main(String args[]) throws IOException {
Example example = new Example();
}
public Example() {
//Create Table Model
DefaultTableModel model = new DefaultTableModel();
for (int index = 0; index < columnHeads.length; index++) {
model.addColumn(columnHeads[index]);
}
//Create Table
JTable table = new JTable(model);
JScrollPane scrollPane = new JScrollPane(table);
//List for ComboBox
String[] list = {"Item1", "Item2", "Item3"};
//Create ComboBox
JComboBox itemTypes = attachComboBoxRenderer(table, 2, list);
//Attach Item Listener
itemTypes.addItemListener(new ComboBoxListener());
((DefaultTableModel) table.getModel()).insertRow(
table.getRowCount(), new Object[]{"C1", "C2", ""});
this.setTitle("Example");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container container = getContentPane();
//MAIN Panel
final JPanel main = new JPanel();
main.setLayout(new GridBagLayout());
main.add(scrollPane);
container.add(main);
this.pack();
this.setVisible(true);
}
public static JComboBox attachComboBoxRenderer(
JTable table, int column, Object[] values) {
JComboBox combo = new JComboBox(values);
TableColumn col = table.getColumnModel().getColumn(column);
col.setCellRenderer(new ComboBoxRenderer(values));
col.setCellEditor(new DefaultCellEditor(combo));
return combo;
}
}
class ComboBoxListener implements ItemListener {
private static final int SELECTED = 1;
#Override
public void itemStateChanged(ItemEvent e) {
// Get the affected item
Object item = e.getItem();
if (item.toString() != null
&& !"".equals(item.toString())
&& e.getStateChange() == SELECTED) {
System.out.println(item.toString() + " selected");
//How do I get Row in the Table of the ComboBox that was changed?
}
}
}
class ComboBoxRenderer extends JComboBox implements TableCellRenderer {
private static final long serialVersionUID = 1L;
public ComboBoxRenderer(Object[] items) {
super(items);
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setForeground(table.getSelectionForeground());
super.setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
}
// Select the current value
setSelectedItem(value);
return this;
}
}
It sounds like you are Using a Combo Box as an Editor. If so, the TableCellEditor method, getTableCellEditorComponent(), includes the row as a parameter. There's a related example here.
Addendum: To change a value in the same row you've edited, just have the model return the correct value for the "other column" based on the related values in that row. Alternatively, update the related value in your model's setValueAt() method before firing the update, as shown in the example.
Addendum: Based on your example, the code below overrides the model's getValueAt() method to keep the dependent column synchronized with the item column.
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.IOException;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
/** #see http://stackoverflow.com/questions/7350445 */
public class DependentColumn extends JFrame {
private static final int DEPENDENT_COL = 1;
private static final int ITEM_COL = 2;
private static final String[] columnNames = {"Col 1", "Col 2", "Col 3"};
public static void main(String args[]) throws IOException {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
DependentColumn dc = new DependentColumn();
}
});
}
public DependentColumn() {
this.setTitle("Example");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create Model & Table
DefaultTableModel model = new DefaultTableModel(columnNames, 0) {
#Override
public Object getValueAt(int row, int col) {
if (col == DEPENDENT_COL) {
return "C2:" + this.getValueAt(row, ITEM_COL);
} else {
return super.getValueAt(row, col);
}
}
};
for (int i = 0; i < 16; i++) {
model.addRow(new Object[]{"C1", "C2", "Item1"});
}
JTable table = new JTable(model);
table.setPreferredScrollableViewportSize(new Dimension(320, 120));
//Create ComboBox
String[] items = {"Item1", "Item2", "Item3"};
JComboBox combo = new JComboBox(items);
TableColumn col = table.getColumnModel().getColumn(ITEM_COL);
col.setCellEditor(new DefaultCellEditor(combo));
combo.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
System.out.println(e.getItem() + " selected");
}
}
});
this.add(new JScrollPane(table));
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
}
I'm working on a program for a little store. When I click the button "Report", it must show a Table, like this one:
Column names "A", "B"..."N", must be the names of the employees. But I can't figure out how.
Here is my code:
public void Inform()
{
String[] employee;
String[] product[];
this.setLayout(null);
Inform=new JTable(nulo, employee.length);
model = new DefaultTableModel() {
private static final long serialVersionUID = 1L;
#Override
public int getColumnCount() {
return 1;
}
#Override
public boolean isCellEditable(int row, int col) {
return false;
}
#Override
public int getRowCount() {
return Inform.getRowCount();
}
};
headerTable = new JTable(model);
for (int i = 0; i < Inform.getRowCount(); i++)
headerTable.setValueAt(product[i], i, 0);
headerTable.setShowGrid(false);
headerTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
headerTable.setPreferredScrollableViewportSize(new Dimension(50, 0));
headerTable.getColumnModel().getColumn(0).setPreferredWidth(50);
scrollPane = new JScrollPane(Inform);
scrollPane.setRowHeaderView(headerTable);
scrollPane.setBounds(5,5,500,500);
scrollPane.setEnabled(false);
this.add(scrollPane);
}
Employee and product variates depending how many are entered. nulo is how many products are ready to sell.
You should add getColumnName() in your TableModel:
String[] employee = {"Employee 1", "Employee 2"};
#Override
public String getColumnName(int index) {
return employee[index];
}
In your case this could be:
model = new DefaultTableModel() {
private static final long serialVersionUID = 1L;
String[] employee = {"Employee 1", "Employee 2"};
#Override
public int getColumnCount() {
return employee.length;
}
#Override
public boolean isCellEditable(int row, int col) {
return false;
}
#Override
public int getRowCount() {
return Inform.getRowCount();
}
#Override
public String getColumnName(int index) {
return employee[index];
}
};
And here is a fully working example:
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
public class TableNamesTest extends JFrame {
public TableNamesTest() {
DefaultTableModel model = new DefaultTableModel() {
String[] employee = {"emp 1", "emp 2"};
#Override
public int getColumnCount() {
return employee.length;
}
#Override
public String getColumnName(int index) {
return employee[index];
}
};
JTable table = new JTable(model);
add(new JScrollPane(table));
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
new TableNamesTest();
}
}
Here is the example from the oracle website, you can load the names you want for your columns into an array, then pass the array to the JTable
String[] columnNames = {"First Name",
"Last Name",
"Sport",
"# of Years",
"Vegetarian"};
//Then the Table is constructed using these data and columnNames:
JTable table = new JTable(data, columnNames);
The resulting table looks like this:
Link to tutorial on JTables: http://docs.oracle.com/javase/tutorial/uiswing/components/table.html#data
Try this:
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
public class Class1 extends JFrame{
static JTable table;
static String[] Employees = {"Employee1","Employee2","Employee3","Employee4"};
static int NumberOfRows=4;
static int NumberOfColumns=4;
public static void main(String[] args){
table = new JTable(NumberOfRows,NumberOfColumns);
for(int i=0;i<Employees.length;i++){
TableColumn tc = table.getColumnModel().getColumn(i);
tc.setHeaderValue(Employees[i]);
DefaultTableCellRenderer dtcr = new DefaultTableCellRenderer();
dtcr.setHorizontalAlignment(SwingConstants.CENTER); //For Aligning the Elements of all columns to CENTER
tc.setCellRenderer(dtcr);
}
JFrame frame = new JFrame();
frame.add(new JScrollPane(table));
frame.setSize(300,300);
frame.setVisible(true);
}
}`
This is more of a manual approach but it works for me.
JTabel TABLE = new JTable();
JTableHeader HEADER = TABLE.getTableHeader();
TableColumnModel TMC = HEADER.getColumnModel();
TableColumn TC = TMC.getColumn(0);
TC.setHeaderValue("Person 1");
TableColumn TC1 = TMC.getColumn(1);
TC1.setHeaderValue("Person 2");
HEADER.repaint();
TABLE.getTableHeader().repaint();