I'm using sortable columns for my JTable:
table.setAutoCreateRowSorter(true);
The issue is that after the user click on a column header there's no way to remove the arrow. Even If I delete all the rows in the table.
I tried to do the opposite but it didn't work:
table.setAutoCreateRowSorter(false);
The fact the arrow is not removed seem to be a painting issue. Calling table.getTableHeader().repaint() seems to make the arrow go away.
Full example:
public class JTableSortRestore {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
runGui();
});
}
private static void runGui() {
JFrame frame = new JFrame("");
frame.setLayout(new BorderLayout());
DefaultTableModel model = new DefaultTableModel();
model.addColumn("Col");
model.addRow(new String[] { "BBB" });
model.addRow(new String[] { "AAA" });
model.addRow(new String[] { "CCC" });
JTable table = new JTable(model);
table.setAutoCreateRowSorter(true);
frame.add(new JScrollPane(table));
JButton restoreButton = new JButton("Restore sorting");
restoreButton.addActionListener(e -> {
table.setAutoCreateRowSorter(false);
table.setAutoCreateRowSorter(true);
table.getTableHeader().repaint();
});
frame.add(restoreButton, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
Related
I have a database with tables. I passed the name of the tables into the buttons. When you click, you need a table with fields and filling to appear. The problem is that I have a new table added every time I click on the button.
Can someone please say me how to do it? Thanks in advance!
public class App extends JPanel {
static List<FieldElement> fields = new ArrayList<>();
static List<Map<String, Object>> data = new ArrayList<>();
static JTable jTable = new JTable();
public static void createGUI() throws SQLException {
TableContent tableContent = new TableContent();
JFrame frame = new JFrame();
MetadataHelper databaseMetadata = new MetadataHelper();
List<ButtonElement> elements = databaseMetadata.showTables();
JPanel panel = new JPanel();
JPanel buttons = new JPanel(new GridLayout(0, 1));
for (ButtonElement buttonElements : elements) {
JButton jButton = new JButton(buttonElements.getTablesInMigrateSchema());
buttons.add(jButton);
jButton.addActionListener(new ActionListener() {
#SneakyThrows
#Override
public void actionPerformed(ActionEvent e) {
fields = tableContent.getDatabaseMetadata().showFields(buttonElements.getTablesInMigrateSchema());
data = tableContent.getDatabaseMetadata().selectAll(buttonElements.getTablesInMigrateSchema());
Object[][] objectRows = data.stream().map(m -> m.values().toArray()).toArray(Object[][]::new);
jTable = new JTable(objectRows, fields.toArray());
panel.add(new JScrollPane(jTable));
frame.revalidate();
frame.repaint();
}
});
}
panel.add(buttons, BorderLayout.EAST);
frame.add(panel);
frame.setTitle("SwingSandbox");
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#SneakyThrows
public void run() {
JFrame.setDefaultLookAndFeelDecorated(true);
createGUI();
}
});
}
}
One easy possibility is to store the JScrollPane in a variable (which holds your table that you want to remove):
static JTable jTable = new JTable();
static JScrollPane jScrollPane;
And then in your actionPerformed method:
public void actionPerformed(ActionEvent e) {
...
if (jScrollPane != null) {
panel.remove(jScrollPane);
}
jTable = new JTable(objectRows, fields.toArray());
jScrollPane = new JScrollPane(jTable);
panel.add(jScrollPane);
frame.revalidate();
frame.repaint();
}
How to add a Back button on top of JTable ? I tried but no luck.
public class viewMovie extends JPanel{
static JFrame frame = new JFrame("View Movie");
JTable table;
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
createAndShowGui();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
});
}
static void createAndShowGui() throws Exception {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new viewMovie());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public viewMovie() throws Exception
{
String sql="Select * from movie";
DatabaseConnection db = new DatabaseConnection();
Connection conn =db.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
ResultSetMetaData rsmt= rs.getMetaData();
int c= rsmt.getColumnCount();
Vector column= new Vector(c);
for(int i=1;i<=c;i++)
{
column.add(rsmt.getColumnName(i));
}
Vector data = new Vector();
Vector row=new Vector();
while(rs.next())
{
row=new Vector(c);
for(int i=1;i<=c;i++)
{
row.add(rs.getString(i));
}
data.add(row);
}
JButton back= new JButton("Back");
JPanel topPanel = new JPanel(new GridLayout(1, 0, 3, 3));
topPanel.add(back);
JPanel panel= new JPanel();
table=new JTable(data,column);
JScrollPane jsp = new JScrollPane(table);
panel.setLayout(new BorderLayout());
panel.add(jsp,BorderLayout.CENTER);
frame.setContentPane(panel);
frame.setVisible(true);
}
}
This is the output I get.
You're forgetting one line of code, the line that adds the topPanel to the panel JPanel:
panel.add(topPanel, BorderLayout.PAGE_START);
Side note: for future questions, you will want to make your code compilable and runnable by us, meaning get rid of unnecessary dependencies, such as database. For your code above, the database stuff could be replaced by:
JPanel panel = new JPanel();
Integer[][] data = { { 1, 2, 3 }, { 4, 5, 6 } };
String[] column = { "A", "B", "C" };
table = new JTable(data, column);
But actually since it is just a simple layout question, even the JTable is not necessary.
I have a problem to update JXTable's rows height. I have tested an example from this post (Setting the height of a row in a JTable in java) :
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class DemoTable {
private static void createAndShowGUI() {
JFrame frame = new JFrame("DemoTable");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DefaultTableModel model = new DefaultTableModel();
model.setColumnIdentifiers(new Object[] {
"Column 1", "Column 2", "Column 3" });
JTable table = new JTable(model);
for (int count = 0; count < 3; count++){
model.insertRow(count, new Object[] { count, "name", "age"});
}
table.setRowHeight(1, 30);
frame.add(new JScrollPane(table));
frame.setLocationByPlatform(true);
frame.pack();
frame.setVisible(true);
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
This demo works perfectly, but if I change JTable to JXTable (and I need it for my project), the second row is not updated, the size is 15 for all. If I use setRowHeight(30) instead of setRowHeight(1, 30) with JXTable, it works but all the rows are updated.
Is this a bug ? How can I solve this problem ?
I'm using the library swingx-0.9.2.jar
Thanks
JTable table = new JTable(data,columnNames);
JScrollPane pane = new JScrollPane(table);
this.add(pane);
this.add(table);
My data is showing but column name is not showing on top.
A component can only have a single parent.
JScrollPane pane = new JScrollPane(table);
this.add(pane);
this.add(table);
First you add the table to the viewport of the scrollpane, which is good as this will cause the table header to automatically be displayed when the GUI is made visible.
But then you add the table directly to the frame, which is bad because it can no longer be displayed in the scrollpane.
Get rid of:
//this.add(table);
and then the scrollpane containing the table will be displayed properly on the frame.
Have a look at this example
import java.awt.Color;
import javax.swing.*;
public class table extends JFrame{
public table() {
setSize(600, 300);
String[] columnNames = {"A", "B", "C"};
Object[][] data = {
{"Moni", "adsad", 2},
{"Jhon", "ewrewr", 4},
{"Max", "zxczxc", 6}
};
JTable table = new JTable(data, columnNames);
JScrollPane tableSP = new JScrollPane(table);
JPanel tablePanel = new JPanel();
tablePanel.add(tableSP);
tablePanel.setBackground(Color.red);
add(tablePanel);
setTitle("Marks");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
table ex = new table();
ex.setVisible(true);
}
});
}
}
For example I have a Table that I want to get text that's in the first column and store it in an ArrayList.
Java Tables often use the TableModel interface for storage.
You can get the a particular value via:
myJTable.getModel().getValueAt(rowIndex, columnIndex);
More on that: Sun's Swing Table Tutorial
public static void main(String[] args)
{
try
{
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container cp = frame.getContentPane();
cp.setLayout(new FlowLayout());
final JTable tbl = new JTable(new String[][]{{"c1r1", "c2r1"}, {"c1r2", "c2r2"}}, new String[]{"col 1", "col 2"});
cp.add(tbl);
cp.add(new JButton(new AbstractAction("click")
{
#Override
public void actionPerformed(ActionEvent e)
{
List<String> colValues = new ArrayList<String>();
for (int i = 0; i < tbl.getRowCount(); i++)
colValues.add((String) tbl.getValueAt(0, i));
JOptionPane.showMessageDialog(frame, colValues.toString());
}
}));
frame.pack();
frame.setVisible(true);
}
catch (Throwable e)
{
e.printStackTrace();
}
}
You need to go through the JTable's TableModel, accessible through the getModel() method. That has all the information you need.