Please have a look at the following code
import java.awt.*;
import javax.swing.JTable;
import javax.swing.*;
public class Table extends JFrame
{
private JTable table;
public Table()
{
String[] columnNames = {"first name","last name","address"};
Object[][]data = {{"John","Kane","NY"},{"Nayomi","Writz","NY"}};
table = new JTable(data, columnNames);
getContentPane().add(table);
this.pack();
this.setVisible(true);
}
public static void main(String[]args)
{
new Table();
}
}
I haven't used JTable before, so this is my first attempt. In here, it is not showing the column names, just showing the data. Why is that? Please help!
You need to put it in a JScrollPane or similar.
See the top of the API docs for JTable, and JScrollPane.
Related
I'm trying to create a frame with multiple tabs, each with a different list. I've used the Swing UI designer with Intellij to create the "assets" and then modified them in my main class file. I've looked up some examples of creating a JTable using the designer, but these don't use multiple tabs, which I think is the main problem for me right now as I am not able to figure out how to do it.
This is the code for now.
package client;
import javax.swing.*;
import javax.swing.table.TableModel;
import java.awt.event.*;
public class ATCGUI extends GUI {
private JPanel mainPanel;
private JTabbedPane tabbedPanel;
private JPanel tabbedAirportInfo;
private JScrollPane scrollPane;
private JButton addButtonOut;
private JButton deleteButtonOut;
private JButton addButtonIn;
private JButton deleteButtonIn;
private JTable tableOut;
private JTable tableIn;
private JPanel panelOut;
private JScrollPane tabbedPaneOut;
public ATCGUI(String AirportCode) {
this.add(mainPanel);
String airportID = getID(AirportCode);
TableOut(airportID);
pack();
setVisible(true);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
private void TableOut(String airportID){
String[] columnNames = {"Airline", "Destination", "Aircraft"};
Object[][] dataTest = {{"Iberia", "London", "737"}, {"AirEuropa", "Paris", "320"}, {"BritishAirways", "Berlin", "330"}};
JTable TableOut = new JTable(dataTest, columnNames);
setContentPane(panelOut);
}
public static void main(String[] args) {
new ATCGUI("MAD");
}
}
For now it shows the different tabs, but the JTable doesn't appear in any of the tabs. And I did make sure to put the JTable inside a JScrollPane.
I'm pretty new to this so maybe there's something I've missed out or just simply don't know.
Without your JTabbedPane code it will be difficult to suggest what you can "fix" in your own code.
This is a good reference for using a JTabbedPane with multiple tabs:
https://docs.oracle.com/javase/tutorial/uiswing/components/tabbedpane.html
An example of how JTabbedPane might be used with your data:
package whatever;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
public class MyGui extends JFrame {
private JTabbedPane tPane;
MyGui(String t){
super(t);
this.tPane = new JTabbedPane();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
tPane.addTab("Tab 1", createTab());
tPane.addTab("Tab 2", createTab());
tPane.addTab("Tab 3", createTab());
tPane.addTab("Tab 4", createTab());
this.setContentPane(this.tPane);
this.setSize(400, 400);
this.setVisible(true);
}
public static void main(String[] args) {
new MyGui("My Tabbed App");
}
private JScrollPane createTab(){
String[] columnNames = {"Airline", "Destination", "Aircraft"};
Object[][] dataTest = {{"Iberia", "London", "737"}, {"AirEuropa", "Paris", "320"}, {"BritishAirways", "Berlin", "330"}};
JTable tableOut = new JTable(dataTest, columnNames);
return new JScrollPane(tableOut);
}
}
I am new to Java and need to make a blank table with column header only, but I am stuck at the column header, it won't appear, I have tried the answer in this link JTable won't show column headers (adding JScrollPane) but it won't work. This is my code:
void panelTabel(){
JPanel panelTabel = new JPanel();
panelTabel.setBackground(Color.white);
panelTabel.setLayout(null);
panelTabel.setBounds(0, 260, 1000, 455);
JScrollPane scrollTabel = new JScrollPane();
scrollTabel.setBackground(Color.white);
scrollTabel.setLayout(null);
scrollTabel.setBounds(5,5,990,340);
Vector headerTabel = new Vector(2);
headerTabel.addElement(new String("No."));
headerTabel.addElement(new String("Kode Barang"));
DefaultTableModel modelTabel = new DefaultTableModel(1, headerTabel.size());
modelTabel.setColumnIdentifiers(headerTabel);
JTable tabelBarang = new JTable();
tabelBarang.setModel(modelTabel);
tabelBarang.setBackground(Color.gray);
tabelBarang.setBounds(5,5, 980, 330);
scrollTabel.add(tabelBarang);
panelTabel.add(scrollTabel);
halaman.add(panelTabel);
}
And this is the output :
Blank table with no column header
I know my question may be duplicate, but I am really new to java and don't know what I did wrong, can someone please tell me what am I missing ? Thank you so much.
Here's a simple JTable GUI I created using your method.
Here are the changes I made.
I used a border layout on the JPanel that holds the JTable.
I got rid of all null layouts and positioning statements. I did ask for a preferred size for the JPanel. After you actually add some data to the JTable, you can define the size of the JTable and remove the preferred size hint.
I defined the JTable first, then the JScrollPane. Thanks to Andrew Thompson for his comment.
Here's the minimal, runnable example #38,593,729 of a JTable in a JPanel in a JFrame. I hope this example helps you, unlike the first 38,593,728 examples on the Internet.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
public class JTableSimpleExample implements Runnable {
private JFrame frame;
#Override
public void run() {
frame = new JFrame("JTable Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panelTabel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel panelTabel() {
JPanel panelTabel = new JPanel();
panelTabel.setLayout(new BorderLayout());
panelTabel.setPreferredSize(new Dimension(400, 100));
Vector<String> headerTabel = new Vector<>(2);
headerTabel.addElement(new String("No."));
headerTabel.addElement(new String("Kode Barang"));
DefaultTableModel modelTabel = new DefaultTableModel(1, headerTabel.size());
modelTabel.setColumnIdentifiers(headerTabel);
JTable tabelBarang = new JTable(modelTabel);
JScrollPane scrollTabel = new JScrollPane(tabelBarang);
panelTabel.add(scrollTabel, BorderLayout.CENTER);
return panelTabel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new JTableSimpleExample());
}
}
I am using JComboBox in Jtable cell. When I click on the JComboBox and select a value from it, it calls the ActionPerformed fuction. Till here it is working fine but as soon as I click on the JComboBox again, it calls the ActionPerformed function, which it should not. What I want is, to call the ActionPerformed function when the item is selected in the JComboBox. In other words it should work as it worked for the first time when the item was selected from the JComboBox and then the ActionPerformed function was called. I cannot figure out why this problem is occurring. Here are the links that I have looked into and I did some other searches also but still could not find any relative answer to the above mentioned problem.
Adding JComboBox to a JTable cell
How to use ActionListener on a ComboBox to give a variable a value
https://coderanch.com/t/339842/java/ComboBox-ItemListener-calling
Here is the code, you can copy paste it and check it.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.TableColumn;
public class TableExample implements ActionListener{
JFrame frame;
JComboBox skuNameComboBoxTable;
TableExample() {
frame = new JFrame();
String data[][] = {{"101", "Amit", "Choose"},
{"102", "Jai", "Choose"},
{"101", "Sachin", "Choose"}};
String column[] = {"ID", "Name", "Degree"};
JTable table = new JTable(data, column);
table.setBounds(30, 40, 200, 300);
JScrollPane scrollPane = new JScrollPane(table);
frame.add(scrollPane);
frame.setSize(300, 400);
frame.setVisible(true);
String[] array = {"BS(SE)", "BS(CS)", "BS(IT)"};
skuNameComboBoxTable = new JComboBox(array);
skuNameComboBoxTable.addActionListener(this);
TableColumn col = table.getColumnModel().getColumn(2);
col.setCellEditor(new DefaultCellEditor(skuNameComboBoxTable));
}
public static void main(String[] args) {
new TableExample();
}
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "actionPerformed called");
}
}
Kindly tell me why this problem is occurring and how should I solve it.
Unfortunately, you can't do much when using the DefaultCellEditor - that is how it behaves. Within your code you can add a check to ensure that a change in value occured before handling the event. Something like below:
public void actionPerformed(ActionEvent e) {
if (skuNameSelected == null || skuNameComboBoxTable.getSelectedItem() != skuNameSelected)
JOptionPane.showMessageDialog(null, "actionPerformed called: ");
skuNameSelected = (String) skuNameComboBoxTable.getSelectedItem();
}
You can try using ItemListener and filter your action according to the ItemEvent.
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
public class JComboBoxTest {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] items = {"One", "Two", "Three"};
JComboBox cb = new JComboBox(items);
cb.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
System.out.println("Selected " + e.getItem());
} else {
System.out.println("Deselected " + e.getItem());
}
}
});
frame.add(cb);
frame.pack();
frame.setVisible(true);
}
}
This is happening because you are using the same JComboBox as the DefaultCellEditor for column 2.
Whenever you click a cell from column 2 the ComboBox will change to the value that is on the cell at the moment and that triggers the DESELECT (from the old value) and the SELECT (for the new value). This will only happen if the old value and the new value are not the same.
One way to avoid this is to add a CellEditorListener on the DefaultCellEditor that you are using, like below:
TableColumn col = table.getColumnModel().getColumn(2);
DefaultCellEditor cellEditor = new DefaultCellEditor(skuNameComboBoxTable);
col.setCellEditor(cellEditor);
cellEditor.addCellEditorListener(new CellEditorListener() {
#Override
public void editingStopped(ChangeEvent e) {
System.out.println("Value of combo box defined!");
}
#Override
public void editingCanceled(ChangeEvent e) {
System.out.println("Edition canceled, set the old value");
}
});
This way you will be able to only act when the value has been defined by the ComboBox.
I hope this helps.
You should not be using an ActionListener for this. The combo box uses its own ActionListener to update the TableModel when an item is selected.
So instead you should be listening for changes in the TableModel in order to do your custom code. So you should be using a TableModelListener to listen for changes in the data. However, a TableModelListener can fire an event even if just start and stop editing of the cell which might be a problem for you.
In this case you can use the Table Cell Listener. It will only generate an event when the value in the TableModel has changed.
I am using a JScrollPane to wrap a JTable. Depending on the configuration, there is some space that is not occupied by the table. It is drawn gray (it looks like it is transparent and you can just see the component in the back). How can I set this area to be a certain color?
Here is a SSCCE to illustrate.
import java.awt.Color;
import java.util.Vector;
import javax.swing.JDialog;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class DialogDemo extends JDialog {
public static void main(final String[] args) {
final DialogDemo diag = new DialogDemo();
diag.setVisible(true);
}
public DialogDemo() {
super();
setTitle("SSCCE");
final Vector<Vector<String>> rowData = new Vector<Vector<String>>();
final Vector<String> columnNames = new VectorBuilder<String>().addCont("Property").addCont("Value");
rowData.addElement(new VectorBuilder<String>().addCont("lorem").addCont("ipsum"));
rowData.addElement(new VectorBuilder<String>().addCont("dolor").addCont("sit amet"));
rowData.addElement(new VectorBuilder<String>().addCont("consectetur").addCont("adipiscing elit."));
rowData.addElement(new VectorBuilder<String>().addCont("Praesent").addCont("posuere..."));
final JTable table = new JTable(rowData, columnNames);
JScrollPane pane = new JScrollPane(table);
// ************* make that stuff white! *******************
table.setBackground(Color.white);
table.setOpaque(true);
pane.setBackground(Color.white);
pane.setOpaque(true);
// ************* make that stuff white! *******************
add(pane);
pack();
setLocationRelativeTo(null);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
}
class VectorBuilder<T> extends Vector<T> {
public VectorBuilder<T> addCont(final T elem) {
addElement(elem);
return this;
}
}
}
And here you can see the area, which I want to "colorize". In the SSCCE, I try to do that by using setOpaque(boolean) and setBackgroundColor(Color) of the table and scroll pane, with no success.
Can you tell me, what I am doing wrong?
Instead of this:
table.setBackground(Color.white);
table.setOpaque(true);
pane.setBackground(Color.white);
pane.setOpaque(true);
call:
pane.getViewport().setBackground(Color.WHITE);
I have read through the majority of the JTable/JComboBox responses to other questions of this ilk, but haven't yet found a solution to my problem.
I have created a table that has JComboBox TableHeader elements. None of the JComboBox elements will open to display a list of items. How do I get the item lists for the individual JComboBox elements to display?
Please note that a distinguishing element of this question is that the JComboBox is in the TableHeader, not embedded within a JTable cell.
Any help is appreciated.
SSCE
import java.awt.Component;
import java.awt.Dimension;
import java.util.Enumeration;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
public class ComboHeaderTest extends JScrollPane {
private static final Dimension DEFAULT_SIZE = new Dimension(200, 200);
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ComboHeaderTest().initComponents();
}
});
}
private ComboHeaderTest() {
final String[][] data = { {"Header 1", "Header 2", "Header 3"},
{"A", "B", "C"},
{"D", "E", "F"},
{"G", "H", "I"}};
setViewportView(getTable(data));
setPreferredSize(DEFAULT_SIZE);
}
private void initComponents() {
JFrame frame = new JFrame("ComboHeaderTest");
frame.add(this);
frame.pack();
frame.setVisible(true);
}
private JTable getTable(final String[][] data) {
final String[] items = data[0];
final ComboHeaderRenderer[] columnHeaders = new ComboHeaderRenderer[items.length];
for(int i = 0; items.length > i; ++i) {
columnHeaders[i] = new ComboHeaderRenderer(items);
}
final JTable table = new JTable(data, columnHeaders);
final Enumeration<TableColumn> tableEnum = table.getColumnModel().getColumns();
for (int columnIndex = 0; tableEnum.hasMoreElements(); ++columnIndex) {
final TableColumn column = tableEnum.nextElement();
final ComboHeaderRenderer combo = columnHeaders[columnIndex];
column.setHeaderValue(combo.getItemAt(columnIndex));
column.setHeaderRenderer(combo);
}
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setRowSelectionAllowed(true);
table.setColumnSelectionAllowed(false);
table.setCellSelectionEnabled(false);
table.setFillsViewportHeight(true);
table.setSize(DEFAULT_SIZE);
table.validate();
return table;
}
private static class ComboHeaderRenderer extends JComboBox implements TableCellRenderer{
public ComboHeaderRenderer(final String[] entries) {
for (int i = 0; entries.length > i; ++i) {
addItem(entries[i]);
}
}
#Override
public Component getTableCellRendererComponent(final JTable table, final Object value,
final boolean isSelected, final boolean hasFocus, final int row, final int column) {
setSelectedItem(value);
return this;
}
}
}
This actually works exactly as expected. I think the clue is TableCellRenderer.
Renderer's are typically non-interactive components. They are usually just a "snap-shot" of the component painted on to a surface and there is typically no way for a user to interact with them.
This is the expected behavior.
In order to supply editable functionality to the table header, you're going to need to supply your implementation of a JTableHeader
Have a look at this example for some ideas
Here is an example that uses a JComboBox in a JTable TableHeader.
For other types of components is easier, have a look here.