JScrollPane not displaying - java

I'm trying to display a JscrollPane using this code. but it's displaying a blank frame with just the "close" button displayed. Can't figure out why it wouldn't display. Any help would be greatly appreciated! :)
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.SQLException;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JButton;
import javax.swing.table.DefaultTableModel;
import edu.pitt.bank.Account;
import edu.pitt.bank.Transaction;
import edu.pitt.utilities.DbUtilities;
import edu.pitt.utilities.MySqlUtilities;
public class TransactionUI {
private JFrame frame;
private JScrollPane transactionPane;
private JTable tblTransactions;
public TransactionUI(Account userAccount) {
frame = new JFrame();
frame.setTitle("Account Transactions");
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
transactionPane = new JScrollPane();
frame.getContentPane().add(transactionPane);
DbUtilities db = new MySqlUtilities();
String [] cols = {"Type", "Amount", "Date"};
String sql = "SELECT type, amount, transactionDate FROM srp63_bank1017.transaction;";
try {
System.out.println("use getDataTable()");
DefaultTableModel transactionList = db.getDataTable(sql, cols);
System.out.println("getDataTable() used");
tblTransactions = new JTable(transactionList);
tblTransactions.setFillsViewportHeight(true);
tblTransactions.setShowGrid(true);
tblTransactions.setGridColor(Color.BLACK);
transactionPane.getViewport().add(tblTransactions);
} catch (SQLException e) {
e.printStackTrace();
}
JButton btnClose = new JButton("Close");
btnClose.setBounds(323, 212, 89, 23);
btnClose.setBounds(284, 214, 73, 23);
frame.getContentPane().add(btnClose);
}
public JFrame getFrame() {
return frame;
}
}
I use this to call the above frame from another class:
public void actionPerformed(ActionEvent arg0) {
if(userAccount.getAccountID() != null){
TransactionUI tUI = new TransactionUI(userAccount);
tUI.getFrame().setVisible(true);
} else {
System.out.println("Account object must not be null");
}
}
});
Here is the getDataTable method...
public DefaultTableModel getDataTable(String sqlQuery, String[] customColumnNames) throws SQLException{
ResultSet rs = getResultSet(sqlQuery);
/* Metadata object contains additional information about a ResulSet,
* such as database column names, data types, etc...
*/
ResultSetMetaData metaData = rs.getMetaData();
// Get column names from the metadata object and store them in a Vector variable
Vector<String> columnNames = new Vector<String>();
for(int column = 0; column < customColumnNames.length; column++){
columnNames.add(customColumnNames[column]);
}
// Create a nested Vector containing an entire table from the ResultSet
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
while(rs.next()){
Vector<Object> vector = new Vector<Object>();
for(int columnIndex = 1; columnIndex <= metaData.getColumnCount(); columnIndex++){
vector.add(rs.getObject(columnIndex));
}
data.add(vector);
}
return new DefaultTableModel(data, columnNames);
}
I received no errors

Problem #1
frame.getContentPane().setLayout(null);
Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify
See Laying Out Components Within a Container for more details
Problem #2
transactionPane.getViewport().add(tblTransactions);
Don't use ad with JScrollPane or JViewport, use
transactionPane.getViewport().setView(tblTransactions);
or
transactionPane.setViewportView(tblTransactions);
instead
See
How to Use Scroll Panes for more details
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JTable table = new JTable(new DefaultTableModel(100, 100));
table.setGridColor(Color.LIGHT_GRAY);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setViewportView(table);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scrollPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Problem #3
The use of multiple windows, see The Use of Multiple JFrames, Good/Bad Practice? for a more in-depth discussion
I think what you really want is some kind of modal dialog. See How to Make Dialogs for more details
Your code without modifications
(Except removing the database code)
This is how your code looks on my PC, take a good hard look at the button...
Your code modified to use layout managers...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
TransactionUI ui = new TransactionUI();
JFrame frame = ui.getFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TransactionUI {
private JFrame frame;
private JScrollPane transactionPane;
private JTable tblTransactions;
public TransactionUI() {
frame = new JFrame();
frame.setTitle("Account Transactions");
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout());
transactionPane = new JScrollPane();
frame.getContentPane().add(transactionPane);
String[] cols = {"Type", "Amount", "Date"};
String sql = "SELECT type, amount, transactionDate FROM srp63_bank1017.transaction;";
System.out.println("use getDataTable()");
DefaultTableModel transactionList = new DefaultTableModel(100, 100);
System.out.println("getDataTable() used");
tblTransactions = new JTable(transactionList);
tblTransactions.setFillsViewportHeight(true);
tblTransactions.setShowGrid(true);
tblTransactions.setGridColor(Color.BLACK);
transactionPane.setViewportView(tblTransactions);
JPanel buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT));
JButton btnClose = new JButton("Close");
buttons.add(btnClose);
frame.getContentPane().add(buttons, BorderLayout.SOUTH);
}
public JFrame getFrame() {
return frame;
}
}
}

Related

JTable header not showing still

I have looked and found that many people weren't putting their table into a scrollPane. Even though I nest my table into a scrollPane then into the frame it still fails to show the header. Is there something else I'm missing ? Thanks
public class Gui extends JFrame {
AbstractTableModel model;
JTable table;
public void start(AbstractTableModel model) {
this.model = model;
table=new JTable(model){
#Override
public boolean isCellEditable(int arg0, int arg1) {
return false;
}
};
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
TableColumn column = null;
for (int i = 0; i < model.getColumnCount(); i++) {
column = table.getColumnModel().getColumn(i);
column.setPreferredWidth(120);
column.setMaxWidth(300);
column.setMinWidth(50);
}
JScrollPane pane = new JScrollPane(table);
pane.setPreferredSize(new Dimension(900,900));
add(pane);
setLayout(new FlowLayout());
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
}
Based on your code and then having to add the missing functionality, you code works...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
public class Gui extends JFrame {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
Gui frame = new Gui();
frame.start(new DefaultTableModel(new Object[]{"A", "B", "C"}, 10));
}
});
}
AbstractTableModel model;
JTable table;
public void start(AbstractTableModel model) {
this.model = model;
table = new JTable(model) {
#Override
public boolean isCellEditable(int arg0, int arg1) {
return false;
}
};
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
TableColumn column = null;
for (int i = 0; i < model.getColumnCount(); i++) {
column = table.getColumnModel().getColumn(i);
column.setPreferredWidth(120);
column.setMaxWidth(300);
column.setMinWidth(50);
}
JScrollPane pane = new JScrollPane(table);
pane.setPreferredSize(new Dimension(900, 900));
add(pane);
setLayout(new FlowLayout());
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
}
}
This then leads to two broad assumptions...
You're TableModel doesn't have any columns
You're TableModel doesn't have any column names...
For example, a TableModel with no column names...
Personally...
I wouldn't use FlowLayout for this, BorderLayout will give better results
pack the frame before you make it visible
Set the layout before you add components as sometimes, things can get messed up...
For example...
setLayout(new FlowLayout()); // But I'd use a `BorderLayout`
add(pane);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setVisible(true);

how to insert more than one jComponents into a cell in a jTable

I have a jTable which is populating according to my requirement . I want to add two comboboxes into all the cells in one column. So can anyone help me on this... ![here is my table ][1]
[1]: http://i.stack.imgur.com/nC9RL.jpg I need to add two comboboxes into all the rows of 1 st column. I did my coding into CREATE TABLE button which u can see in the image. here is my code so far : | |
int row=0;
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
{
row=Integer.parseInt(jTextField2.getText());
row=row-1;
DefaultTableModel dtm =(DefaultTableModel) jTable1.getModel();
TableColumn sportColumn = jTable1.getColumnModel().getColumn(1);
JComboBox subject= new JComboBox();
box.addItem("DDD");
box.addItem("CCC");
JComboBox teacher= new JComboBox();
box1.addItem("AAA");
box1.addItem("FFF");
JPanel jPanel = new JPanel();
GroupLayout gl= new GroupLayout(jPanel);
jPanel.setLayout(gl);
jPanel.add(box);
jPanel.add(box1);
dtm.setRowCount(0);
dtm.setRowCount(Integer.parseInt(jTextField1.getText()));
for (int i = 0; i < dtm.getRowCount(); i++) {
row++;
dtm.setValueAt(String.valueOf(row), i, 0);
sportColumn.setCellRenderer(
(TableCellRenderer) new DefaultTableCellRenderer()
.getTableCellRendererComponent(
jTable1, jPanel, true, true, i, 1));
}
}
jButton1===> create table Button / jTextField2===> number starts with / jTextField1===>number of rows
Caverts:
I think this is a crazy idea, personally. If your cell represents a compound object, then I'd be thinking about using a dialog or some other means, but that's me.
Personally, I think this is going to blow up in your face...
Example
The concepts presented are all based on the information from How to use Tables
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import javax.swing.AbstractCellEditor;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumnModel;
public class Enrolement {
public static void main(String[] args) {
new Enrolement();
}
public Enrolement() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
DefaultTableModel model = new DefaultTableModel(new Object[]{"Subject"}, 10);
JTable tbl = new JTable(model);
TableColumnModel columnModel = tbl.getColumnModel();
columnModel.getColumn(0).setCellEditor(new SubjectTableCellEditor());
tbl.setRowHeight(columnModel.getColumn(0).getCellEditor().getTableCellEditorComponent(tbl, "Astronomy/Aurora Sinistra", true, 0, 0).getPreferredSize().height);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(tbl));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class SubjectTableCellEditor extends AbstractCellEditor implements TableCellEditor {
private JComboBox subject;
private JComboBox teacher;
private JPanel editor;
private Map<String, String[]> subjectTeachers = new HashMap<>(25);
public SubjectTableCellEditor() {
subjectTeachers.put("Astronomy", new String[]{"Aurora Sinistra"});
subjectTeachers.put("Charms", new String[]{"Filius Flitwick"});
subjectTeachers.put("Dark Arts", new String[]{"Igor Karkaroff", "Amycus Carrow"});
subjectTeachers.put("Defence Against the Dark Arts", new String[]{"Defence Against the Dark Arts",
"Quirinus Quirrell",
"Gilderoy Lockhart",
"Remus Lupin",
"Bartemius Crouch Jr.",
"Dolores Umbridge",
"Severus Snape",
"Amycus Carrow"});
subjectTeachers.put("Flying", new String[]{"Rolanda Hooch"});
subjectTeachers.put("Herbology", new String[]{"Herbert Beery",
"Pomona Sprout",
"Neville Longbottom"});
subjectTeachers.put("History of Magic", new String[]{"Professor Cuthbert Binns"});
subjectTeachers.put("Potions", new String[]{"Severus Snape",
"Horace Slughorn"});
subjectTeachers.put("Transfiguration", new String[]{"Minerva McGonagall",
"Albus Dumbledore"});
subject = new JComboBox(new String[]{
"Astronomy",
"Charms",
"Dark Arts",
"Defence Against the Dark Arts",
"Flying",
"Herbology",
"History of Magic",
"Potions",
"Transfiguration"
});
teacher = new JComboBox();
editor = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
editor.add(subject, gbc);
editor.add(teacher, gbc);
subject.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
teacher.setModel(new DefaultComboBoxModel(subjectTeachers.get(subject.getSelectedItem())));
}
});
}
#Override
public Object getCellEditorValue() {
return subject.getSelectedItem() + "/" + teacher.getSelectedItem();
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
if (value instanceof String) {
String parts[] = value.toString().split("/");
subject.setSelectedItem(parts[0]);
teacher.setSelectedItem(parts[1]);
}
editor.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
return editor;
}
}
}

Java - Load JTabbedPane one tab after another

I have a JTabbedPane with 4 tabs. I would like to load 1 tab 1 after another as the tabs uses, refers and retrieves from the same database. And this is causing an issue of "Database is locked" in my application.
Thanks in advance for the help and suggestions :)
This is how I create the JTabbedPane
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.setBounds(0, 0, 450, 300);
tabbedPane.addTab("tab1", new class1UseDb());
tabbedPane.setMnemonicAt(0, KeyEvent.VK_1);
tabbedPane.addTab("tab2", new class2UseDb());
tabbedPane.setMnemonicAt(1, KeyEvent.VK_2);
tabbedPane.addTab("tab3", new class3UseDb());
tabbedPane.setMnemonicAt(2, KeyEvent.VK_3);
tabbedPane.addTab("tab4", new class());
tabbedPane.setMnemonicAt(3, KeyEvent.VK_4);
Based on this example, the sscce below simply creates a new panel for each click on the Add button and fills in the result. In a real program, you may want to use a SwingWorker to manage latency and resources.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import org.h2.jdbcx.JdbcDataSource;
/**
* #see https://stackoverflow.com/a/19860170/230513
* #see https://stackoverflow.com/a/15715096/230513
* #see https://stackoverflow.com/a/11949899/230513
*/
public class TabData {
private int n = 1;
private void display() {
JFrame f = new JFrame("TabData");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JTabbedPane jtp = new JTabbedPane();
jtp.add(String.valueOf(n), createPane());
f.add(jtp, BorderLayout.CENTER);
JPanel p = new JPanel(new FlowLayout(FlowLayout.RIGHT));
p.add(new JButton(new AbstractAction("Add") {
#Override
public void actionPerformed(ActionEvent e) {
jtp.add(String.valueOf(++n), createPane());
jtp.setSelectedIndex(n - 1);
}
}));
f.add(p, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private JPanel createPane() {
JPanel p = new JPanel();
JLabel l = new JLabel();
p.add(new JLabel("Result: "));
p.add(l);
JdbcDataSource ds = new JdbcDataSource();
ds.setURL("jdbc:h2:file:~/src/java/jdbc/test;IFEXISTS=TRUE");
ds.setUser("sa");
ds.setPassword("");
try {
Connection conn = ds.getConnection();
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery("SELECT RAND() FROM DUAL");
rs.next();
l.setText(rs.getString(1));
} catch (SQLException ex) {
ex.printStackTrace(System.err);
}
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new TabData().display();
}
});
}
}

How to update JComboBox instances in Swing?

I've 3 comboboxes, upon selecting first combobox, the rest should be updated but my code doesn't seems to be working. Please help in this guys. Here is my code(since my code very long so I'll write error part only).
// example code
public class GuiComponents {
JComboBox<String> comboBox1, comboBox2, comboBox3;
public GuiComponents() {
.........
.........
String[] element1 = {"item1", "item2", "item3"};
String[] element2 = {"item1", "item2", item3};
String[] element3 = {"item1", "item2", "item3"};
comboBox1.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent event) {
if(event.getStateChange() == ItemEvent.SELECTED) {
// how do I update 2 comboboxes, upon selecting combobox1.
// combox2 should update as(element2) and
// combox3 should update as element3.
}
}
});
}
}
Thanks in advance....
If you intention is to change the combo box values when the user makes a selection, then you are better off using a ActionListener.
If you want to the combo boxes to update each time the user selects a different item in the drop down list (and, yes, this is a different event), then you should use an ItemListener
But in either case, the process is the same...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ComboBoxUpdates {
public static void main(String[] args) {
new ComboBoxUpdates();
}
public ComboBoxUpdates() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JComboBox<String> cb1, cb2, cb3;
public TestPane() {
cb1 = new JComboBox<>(new String[]{"Click me", "Click me", "Click them"});
cb2 = new JComboBox<>();
cb3 = new JComboBox<>();
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(cb1, gbc);
add(cb2, gbc);
add(cb3, gbc);
cb1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
cb2.setModel(new DefaultComboBoxModel<String>(new String[]{"item1", "item2", "item3"}));
cb3.setModel(new DefaultComboBoxModel<String>(new String[]{"item4", "item5", "item6"}));
}
});
}
}
}

JTable autoscroll methods are one row too high

Here is an example table of what I have been using:
JScrollPane scrollPane = new JScrollPane();
contentPane.add(scrollPane);
table = new JTable();
DefaultTableModel tableModel = new DefaultTableModel(new Object[]{"Row 1","Row 2"},0);
table.setModel(tableModel);
scrollPane.setViewportView(table);
I've attempted to use the following autoscrolling methods both with the same result.
// Method 1
JScrollBar vertical = scrollPane.getVerticalScrollBar();
vertical.setValue(vertical.getMaximum());
// Method 2
table.scrollRectToVisible(table.getCellRect(table.getRowCount(), 0, true));
Both examples go to the near-bottom of the table, up until the last (bottom) row that the user has to scroll down to see, only to happen again when another row is added.
EDIT: Example code to replicate the problem
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JScrollPane;
import javax.swing.table.DefaultTableModel;
public class ScrollTableEx extends JFrame {
private static final long serialVersionUID = 1L;
public int i = 100;
public JScrollPane scrollPane;
public JPanel contentPane;
public JTable table;
public JButton add;
public DefaultTableModel model = new DefaultTableModel(new Object[] { "Int (+)", "Int (-)" }, 0);
public static void main(String[] args) {
ScrollTableEx frame = new ScrollTableEx();
frame.setVisible(true);
}
public ScrollTableEx() {
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
setSize(500,400);
scrollPane = new JScrollPane();
table = new JTable();
table.setCellSelectionEnabled(true);
table.setModel(model);
scrollPane.setViewportView(table);
for (int i = 0; i < 100; i++) {
model.addRow(new Object[] { i, i * -1 });
Rectangle goodRect = table.getCellRect(model.getRowCount() - 1, 0, true);
table.scrollRectToVisible(goodRect);
}
JButton add = new JButton("Add");
add.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Rectangle goodRect = table.getCellRect(model.getRowCount() - 1, 0, true);
table.scrollRectToVisible(goodRect);
model.addRow(new Object[] { i, i * -1 });
i++;
}
});
add(add, BorderLayout.NORTH);
add(scrollPane, BorderLayout.CENTER);
}
}
The problem is, JTable and TableModel are both 0 indexed. That is, the last value is actually rowCount - 1.
So when you use table.getCellRect(table.getRowCount(), 0, true), it's actually returning a Rectangle of the right position, just with a 0 height, because the row doesn't actually exist.
Instead you want to use table.getCellRect(table.getRowCount() - 1, 0, true)
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
public class ScrollTable {
public static void main(String[] args) {
new ScrollTable();
}
public ScrollTable() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
final DefaultTableModel model = new DefaultTableModel(new Object[]{"Test"}, 0);
for (int index = 0; index < 100; index++) {
model.addRow(new Object[]{index});
}
final JTable table = new JTable(model);
JButton add = new JButton("Add");
add.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
model.addRow(new Object[]{model.getRowCount()});
Rectangle badRect = table.getCellRect(model.getRowCount(), 0, true);
Rectangle goodRect = table.getCellRect(model.getRowCount() - 1, 0, true);
System.out.println("bad = " + badRect);
System.out.println("goodRect = " + goodRect);
table.scrollRectToVisible(goodRect);
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(table));
frame.add(add, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
I would avoid using .setBounds where possible. It does not take into consideration the variety of differences that exist between different computers and OS's and while it might look perfectly fine when you are developing, when you move it another system, it could produce undeseriable results - IMHO

Categories

Resources