By running the example (neglected but functional to demonstrate my problem) you can see the steps in the console in the focustraversalpolicy
Test1: simply press TAB or ShiftTab
In console you see the steps in the getComponentAfter and getComponentBefore methods; in particular it is seen that, since the cells are not in edit, in the case of the second component, the JScrollPane component is returned. so it's ok
Test2: click on a JTable cell, write something (to enter edit) and press TAB
In console you see the passage in the getComponentAfter method; in particular it is seen that, having the focus the JTable, the JTable component is returned. so it's ok
Test3: click on a JTable cell, write something (to enter edit) and press ShiftTAB
Nothing happens at least in terms of focustraversalpolicy
If you press ShiftTab again
In console you see the passage in the getComponentBefore method; in particular we see that the JTextField component used for editing the cell is returned
Why shift TAB first time have no effect on on focustraversalpolicy policy?
Why TAB in focustraversalpolicy return a JTable component and Shift TAB return a JTextField component?
public class Prova2
{
public static final Double VideoDefaultFontIncrementWidth = 0.92;
public static final Double VideoDefaultFontIncrementHeight = 1.5;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new Prova2();
}
});
}
public Prova2()
{
JFrame frame = new JFrame("Prova");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//
Object[] columnHeaders = {"Codice", "Nome", "Prezzo", "Data", "Noedit"};
Object rows[][] = {
{ "A", "About", 44.36, null, "aa" },
{ "B", "Boy", 44.84, null, "aa" },
{ "C", "Cat", 463.63, null, "aa" },
{ "D", "Day", 27.14, null, "aa" },
{ "E", "Eat", 44.57, null, "aa" },
{ "F", "Fail", 23.15, null, "aa" },
{ "G", "Good", 4.40, null, "aa" },
{ "H", "Hot", 24.96, null, "aa" },
{ "I", "Ivey", 5.45, null, "aa" },
{ "J", "Jack", 49.54, null, "aa" },
{ "K", "Kids", 280.00, null, "aa" },
{ "2A", "About", 44.36, null, "aa" },
{ "2B", "Boy", 44.84, null, "aa" },
{ "2C", "Cat", 463.63, null, "aa" },
{ "2D", "Day", 27.14, null, "aa"},
{ "2E", "Eat", 44.57, null, "aa" },
{ "2F", "Fail", 23.15, null, "aa" },
{ "2G", "Good", 4.40, null, "aa" },
{ "2H", "Hot", 24.96, null, "aa" },
{ "2I", "Ivey", 5.45, null, "aa" },
{ "2J", "Jack", 49.54, null, "aa" },
{ "2K", "Kids", 280.00, null, "aa" } };
//
// text 1
JTextField Text1 = new JTextField("");
Text1.setName("Text1");
frame.add(Text1, BorderLayout.NORTH);
//
// JTable soluzione 2
JTable myTable = new JTable(rows, columnHeaders);
myTable.setName("Table");
myTable.setFillsViewportHeight(true);
myTable.putClientProperty("autoStartsEdit", true);
myTable.putClientProperty("terminateEditOnFocusLost", true);
ActionMap myTableActionMap = myTable.getActionMap();
myTableActionMap.put("selectPreviousColumnCell", new myPreviousFocusHandler());
myTableActionMap.put("selectNextColumnCell", new myNextFocusHandler());
for (int i = 0; i < myTable.getColumnCount()-1; i++)
{
JTextField myTextField = new JTextField();
myTable.getColumn(columnHeaders[i]).setCellEditor(new DefaultCellEditor(myTextField));
}
JScrollPane pane = new JScrollPane(myTable);
frame.add(pane, BorderLayout.CENTER);
//
// text2
JTextField Text2 = new JTextField("");
Text2.setName("Text2");
frame.add(Text2, BorderLayout.SOUTH);
//
// frame
frame.setFocusTraversalPolicy(new MyFocusTraversalPolicy());
frame.setSize(800, 400);
frame.setVisible(true);
}
public static class MyFocusTraversalPolicy extends FocusTraversalPolicy
{
#Override
public Component getComponentAfter(Container arg0, Component arg1)
{
System.out.println("getComponentAfter1: "+arg1.toString());
JRootPane myRootPane=(JRootPane)arg0.getComponent(0);
JPanel myPanel = (JPanel) myRootPane.getLayeredPane().getComponent(0);
if (arg1 instanceof JPanel == true)
{
return getFirstComponent(arg0);
}
int myNewPosition = 0;
myNewPosition = myComponentPosition(myPanel, arg1);
myNewPosition = myComponentNext(myPanel, myNewPosition, 1);
if (myNewPosition > -1)
{
System.out.println("getComponentAfter2: "+myComponent(myPanel, myNewPosition));
return myComponent(myPanel, myNewPosition);
}
else
{
return getFirstComponent(arg0);
}
}
#Override
public Component getComponentBefore(Container arg0, Component arg1)
{
System.out.println("getComponentBefore1: "+arg1.toString());
JRootPane myRootPane=(JRootPane)arg0.getComponent(0);
JPanel myPanel = (JPanel) myRootPane.getLayeredPane().getComponent(0);
if (arg1 instanceof JPanel == true)
{
return getFirstComponent(arg0);
}
int myNewPosition = 0;
myNewPosition = myComponentPosition(myPanel, arg1);
myNewPosition = myComponentNext(myPanel, myNewPosition, -1);
if (myNewPosition > -1)
{
System.out.println("getComponentBefore2: "+myComponent(myPanel, myNewPosition));
return myComponent(myPanel, myNewPosition);
}
else
{
return getLastComponent(arg0);
}
}
#Override
public Component getDefaultComponent(Container arg0)
{
System.out.println("getDefaultComponent1: ");
JRootPane myRootPane=(JRootPane)arg0.getComponent(0);
JPanel myPanel = (JPanel) myRootPane.getLayeredPane().getComponent(0);
System.out.println("getDefaultComponent2: "+myPanel.getComponent(0));
return myPanel.getComponent(0);
}
#Override
public Component getFirstComponent(Container arg0)
{
System.out.println("getFirstComponent1: ");
JRootPane myRootPane=(JRootPane)arg0.getComponent(0);
JPanel myPanel = (JPanel) myRootPane.getLayeredPane().getComponent(0);
System.out.println("getFirstComponent2: "+myPanel.getComponent(0));
return myPanel.getComponent(0);
}
#Override
public Component getLastComponent(Container arg0)
{
System.out.println("getLastComponent1: ");
JRootPane myRootPane=(JRootPane)arg0.getComponent(0);
JPanel myPanel = (JPanel) myRootPane.getLayeredPane().getComponent(0);
System.out.println("getLastComponent2: "+myPanel.getComponent(myPanel.getComponentCount()-1));
return myPanel.getComponent(myPanel.getComponentCount()-1);
}
private int myComponentPosition(Container parm_Container, Component parm_Component)
{
for (int i = 0; i < parm_Container.getComponentCount(); i++)
{
if (parm_Container.getComponent(i) == parm_Component)
{
return i;
}
if (parm_Container.getComponent(i).getClass() == JScrollPane.class)
{
if (parm_Component.getClass() == JTable.class)
{
return i;
}
}
}
return -1;
}
private int myComponentNext(Container parm_Container, int parm_Position, int parm_Increment)
{
for (int i = parm_Position + parm_Increment; i > -1 && i < parm_Container.getComponentCount(); i = i + parm_Increment)
{
if (parm_Container.getComponent(i).isEnabled() && parm_Container.getComponent(i).isFocusable())
{
return i;
}
}
return -1;
}
private Component myComponent(Container parm_Container, int parm_Position)
{
return parm_Container.getComponent(parm_Position);
}
}
public class myPreviousFocusHandler extends AbstractAction
{
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent arg0)
{
KeyboardFocusManager myManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
myManager.focusPreviousComponent();
}
}
public class myNextFocusHandler extends AbstractAction
{
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent arg0)
{
KeyboardFocusManager myManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
myManager.focusNextComponent();
}
}
}
Related
I made simple project in Java using swing. Below is code, I would like to get selected value from combobox placed in table, how I can do this? Good to be if thats data were placed in array. Thx for all answers.
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.JFormattedTextField;
public class SWD_GUI implements ActionListener {
JButton button;
public JFrame frame;
private JTable table;
private JTable table_1;
private JTable table_2;
private JTable table_3;
private JFormattedTextField formattedTextField;
JComboBox<ComboItem> comboBox;
TableColumn column_1;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
SWD_GUI window = new SWD_GUI();
window.frame.setVisible(true);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public SWD_GUI() {
initialize();
}
public void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 846, 546);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.pack();
frame.getContentPane().setLayout(null);
JLabel lblSwdTelephone = new JLabel("SWD TELEPHONE");
lblSwdTelephone.setHorizontalAlignment(SwingConstants.CENTER);
lblSwdTelephone.setFont(new Font("Tahoma", Font.BOLD, 16));
lblSwdTelephone.setBounds(10, 11, 810, 20);
frame.getContentPane().add(lblSwdTelephone);
button = new JButton("DO IT!");
button.setBounds(379, 432, 89, 23);
frame.getContentPane().add(button);
button.addActionListener(this);
createTables();
}
private void createTables() {
createFirstTable();
createSecondTable();
createThirdTable();
createFourthTable();
}
private void createFourthTable() {
TableModel tableModel_3 = new DefaultTableModel(new Object[][] {
{ "BATTERY", "Samsung", "HTC", "LG" },
{ "Samsung", new Double(1.0), null, null },
{ "HTC", null, new Double(1.0), null },
{ "LG", null, null, new Double(1.0) }, }, new String[] {
"New column", "Price", "Specification", "Baterry" }) {
private static final long serialVersionUID = 1L;
boolean[] columnEditables = new boolean[] { false, true, true, true };
boolean[] rowEditables = new boolean[] { false, true, true, true };
public boolean isCellEditable(int row, int column) {
return columnEditables[column] && rowEditables[row];
}
};
createTable(table_3, tableModel_3, 304);
}
private void createThirdTable() {
TableModel tableModel_2 = new DefaultTableModel(new Object[][] {
{ "SPECIFICATION", "Samsung", "HTC", "LG" },
{ "Samsung", new Double(1.0), null, null },
{ "HTC", null, new Double(1.0), null },
{ "LG", null, null, new Double(1.0) }, }, new String[] {
"New column", "Price", "Specification", "Baterry" }) {
private static final long serialVersionUID = 1L;
boolean[] columnEditables = new boolean[] { false, true, true, true };
boolean[] rowEditables = new boolean[] { false, true, true, true };
public boolean isCellEditable(int row, int column) {
return columnEditables[column] && rowEditables[row];
}
};
createTable(table_2, tableModel_2, 214);
}
private void createSecondTable() {
TableModel tableModel_1 = new DefaultTableModel(new Object[][] {
{ "PRICE", "Samsung", "HTC", "LG" },
{ "Samsung", new Double(1.0), null, null },
{ "HTC", null, new Double(1.0), null },
{ "LG", null, null, new Double(1.0) }, }, new String[] {
"New column", "Price", "Specification", "Baterry" }) {
private static final long serialVersionUID = 1L;
boolean[] columnEditables = new boolean[] { false, true, true, true };
boolean[] rowEditables = new boolean[] { false, true, true, true };
public boolean isCellEditable(int row, int column) {
return columnEditables[column] && rowEditables[row];
}
};
createTable(table_1, tableModel_1, 124);
}
private void createFirstTable() {
TableModel tableModel = new DefaultTableModel(new Object[][] {
{ null, "Price", "Specification", "Baterry" },
{ "Price", new Double(1.0), null, null },
{ "Specification", null, new Double(1.0), null },
{ "Baterry", null, null, new Double(1.0) }, }, new String[] {
"New column", "Price", "Specification", "Baterry" }) {
private static final long serialVersionUID = 1L;
boolean[] columnEditables = new boolean[] { false, true, true, true };
boolean[] rowEditables = new boolean[] { false, true, true, true };
public boolean isCellEditable(int row, int column) {
return columnEditables[column] && rowEditables[row];
}
};
createTable(table, tableModel, 39);
}
private void createTable(JTable table, TableModel tableModel, int y) {
table = new JTable();
table.setColumnSelectionAllowed(true);
table.setCellSelectionEnabled(true);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setFillsViewportHeight(true);
table.setBounds(10, y, 424, 64);
frame.getContentPane().add(table);
table.setModel(tableModel);
addColumn(table, 1);
addColumn(table, 2);
addColumn(table, 3);
}
class ComboItem
{
public String key;
public String value;
public ComboItem(String key, String value)
{
this.key = key;
this.value = value;
}
//#Override
public String toString()
{
return key;
}
public String getKey()
{
return key;
}
public String getValue()
{
return value;
}
}
public void addColumn(JTable table, int columnIndex) {
{
TableColumn column_1 = table.getColumnModel()
.getColumn(columnIndex);
JComboBox<Object> comboBox = new JComboBox<Object>();
comboBox.addItem(new ComboItem("1", "1.0"));
comboBox.addItem(new ComboItem("3", "3.0"));
comboBox.addItem(new ComboItem("5", "5.0"));
comboBox.addItem(new ComboItem("7", "7.0"));
comboBox.addItem(new ComboItem("1/3", "0.333333333"));
comboBox.addItem(new ComboItem("1/5", "0.2"));
comboBox.addItem(new ComboItem("1/7", "0,1428571428571429"));
//comboBox.addItem((double) 1);
//comboBox.addItem((double) 3);
//comboBox.addItem((double) 5);
//comboBox.addItem((double) 7);
//comboBox.addItem((double) 9);
//comboBox.addItem((double) (1.0/3.0));
//comboBox.addItem((double) (1.0/5.0));
//comboBox.addItem((double) (1.0/7.0));
//comboBox.addItem((double) (1.0/9.0));
column_1.setCellEditor(new DefaultCellEditor(comboBox));
Object item = comboBox.getSelectedItem();
String value = ((ComboItem)item).getValue();
System.out.println(value);
}
formattedTextField = new JFormattedTextField();
formattedTextField.setBounds(462, 36, 358, 333);
frame.getContentPane().add(formattedTextField);
}
//public void getContents() {
// TODO Auto-generated method stub
//}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stud
Object source = e.getSource();
if (source == button) {
}
//for(int i = 0; i<7; i++){
//System.out.println(anArrays[i]);
//}
// getContents();
//int row = table.getSelectedRow();
//String idS = table.getValueAt(row, 0).toString();
//String al = column_1.getMaxWidth().toString();
//System.out.println(al);
// System.out.println(item);
// formattedTextField.add(table);
//formattedTextField.setValue(table);
}
}
You get the data from the table, not the combo box.
ComboItem item = (ComboItem)table.getValueAt(...);
System.out.println( item.getValue() );
I have an object A that instance another object B.
I was wondering whether or not is possible to modify A with instructions in B.
In my circumstance, I have a Timetable (its code is under "Object A") that open (by InsertLesson.setVisible(true);) a Window to let the user compile its cells with lesson. At this time, the Window (InsertLesson, code under "object B") get the lesson selection by user but it is not able to write in the table that selection. How can I do?
Here the code
Object A:
public class TablePanel extends JPanel
{
private JTable table;
public Tabella()
{
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
table = new JTable(new MyTableModel());
table.setFillsViewportHeight(true);
table.setPreferredScrollableViewportSize(new Dimension(500, 100));
JScrollPane jps = new JScrollPane(table);
add(jps);
add(new JScrollPane(table));
table.setCellSelectionEnabled(true);
table.addMouseListener(
new MouseAdapter(){
public void mouseClicked(MouseEvent e) {
int row = table.rowAtPoint(new Point(e.getX(), e.getY()));
int col = table.columnAtPoint(new Point(e.getX(), e.getY()));
if (col>0) {
if (e.getClickCount() > 1) {
if (row == 5 | row == 6)
{
JOptionPane.showMessageDialog(null, "Impossible to set lesson.");
return;
}
else {
table.getColumnName(col);
String day = table.getColumnName(col);
String hour = (String) table.getValueAt(row, 0);
InsertLesson cell = new InsertLesson(day, hour);
cel.setVisible(true);
}
}
}
}
}
);
}
private class MyTableModel extends AbstractTableModel {
private String[] columns = {"","Monday","Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
private String[][] data = {{"8:30 - 9:30","","","","","",""},
{"9:30 - 10:30","","","","","",""},
{"10:30 - 11:30","","","","","",""},
{"11:30 - 12:30","","","","","",""},
{"12:30 - 13:30","","","","","",""},
{"13:30 - 14:30","","","","","",""},
{"14:30 - 15:30","","","","","",""},
{"15:30 - 16:30","","","","","",""},
{"16:30 - 17:30","","","","","",""}};
public int getColumnCount() {
return columns.length;
}
public int getRowCount() {
return data.length;
}
public String getColumnName(int col) {
return columns[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
}
Object B (which has to modify A):
public InsertLesson (String day, String hour)
{
initialize(day, hour);
}
private void initialize(String day, String hour) {
this.setSize(600,200);
this.setTitle("Insert Lesson");
this.setLocationRelativeTo(null);
String[] lessons = {"math", "english", "art"};
String [] classrooms = {"class1", "class2"};
JPanel centralPnl = new JPanel();
this.getContentPane().add(centralPnl, BorderLayout.CENTER);
final JComboBox classBox = new JComboBox(classrooms );
centralPnl.add(classBox);
final JComboBox lessonsBox = new JComboBox(lessons);
centralPnl.add(lessonsBox);
JPanel southPnl = new JPanel();
this.getContentPane().add(southPnl, BorderLayout.SOUTH);
JButton insLessonBtn = new JButton("Insert Lesson");
southPnl.add(insLessonBtn);
lessonsBox.addItemListener(new ItemListener()
{
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED)
{
selectedLesson = lessonsBox.getSelectedItem().toString();
}
}
});
classBox.addItemListener(new ItemListener(){
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED)
{
selectedClass = classBox.getSelectedItem().toString();
}
}
});
class MouseSpy implements MouseListener
{
public void mouseClicked(MouseEvent e)
{
JOptionPane.showMessageDialog(null,"Do something for modify table with\n"
+ "values of selectedLesson and selectedClass");
}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
MouseListener listener = new MouseSpy();
insLessonBtn.addMouseListener(listener);
}
}
}
To update the table in A, B must invoke the method setValueAt() on the TableModel of A. Alternatively, add a method to your TableModel that does the update. A typical implementation of setValueAt() is seen here. If that doesn't help, please edit your question to include an sscce that exhibits the problem you encounter.
Addendum: I want to update the table … after the user press the … button.
As a concrete example using your TableModel, the Update button below updates the table's model with each press. Compare the implmentation of setValueAt () to the one cited above. The button's actionPerformed() method accesses a final reference to the TableModel in the enclosing scope, but you can pass a reference to your TableModel as a parameter to the constructor of InsertLesson.
Addendum: Would you write [it for] me?
No, but I will outline the approach, assuming a class InsertLesson,
TableModel model = new MyTableModel();
JTable table = new JTable(model);
InsertLesson cell = new InsertLesson(day, hour, model);
…
class InsertLesson {
TableModel model;
public InsertLesson(String day, String hour, TableModel model) {
this.model = model;
…
}
…
}
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
/**
* #see http://stackoverflow.com/a/18764073/230513
*/
public class Test {
private static class MyTableModel extends AbstractTableModel {
private String[] columns = {
"Time", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};
private String[][] data = {
{"8:30 - 9:30", "", "", "", "", ""},
{"9:30 - 10:30", "", "", "", "", ""},
{"10:30 - 11:30", "", "", "", "", ""},
{"11:30 - 12:30", "", "", "", "", ""},
{"12:30 - 13:30", "", "", "", "", ""},
{"13:30 - 14:30", "", "", "", "", ""},
{"14:30 - 15:30", "", "", "", "", ""},
{"15:30 - 16:30", "", "", "", "", ""},
{"16:30 - 17:30", "", "", "", "", ""}};
#Override
public int getColumnCount() {
return columns.length;
}
#Override
public int getRowCount() {
return data.length;
}
#Override
public String getColumnName(int col) {
return columns[col];
}
#Override
public Object getValueAt(int row, int col) {
return data[row][col];
}
#Override
public void setValueAt(Object aValue, int row, int col) {
data[row][col] = (String) aValue;
fireTableCellUpdated(row, col);
}
}
private void display() {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final TableModel model = new MyTableModel();
f.add(new JScrollPane(new JTable(model) {
#Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(600, 128);
}
}));
f.add(new JButton(new AbstractAction("Update") {
#Override
public void actionPerformed(ActionEvent e) {
model.setValueAt(String.valueOf(e.getWhen() % 1000000), 1, 1);
}
}), BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Test().display();
}
});
}
}
I have implemented JTable frozen columns as below.When scrolling on a large dataset using vertical scrollbar, the columns in the frozen table are not aligned with the main table.Please help
JTable table,fixedTable
JScrollPane _scrl_table;
table = new JTable();
table.setName("MAIN_TABLE");
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setVisibleRowCount(8);
fixedTable = new JTable();
fixedTable.setName("FIXED_TABLE");
fixedTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
fixedTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
_scrl_table = new JScrollPane(table,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
fixedTable.setPreferredScrollableViewportSize(fixedTable.getPreferredSize());
_scrl_table.setRowHeaderView( fixedTable );
_scrl_table.setCorner(JScrollPane.UPPER_LEFT_CORNER, fixedTable.getTableHeader());
maybe there no reason to use two JTables
use proper RowNumberTable by camickr or RowHeader
you can to share AdjustmentListener, with or without BoundedRangeModel
example scrolling horizontal directions, have to change to the vertical
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class FixedRowExample extends JFrame {
private static final long serialVersionUID = 1L;
private Object[][] data;
private Object[] column;
private JTable fixedTable, table;
private int FIXED_NUM = 2;
public FixedRowExample() {
super("Fixed Row Example");
data = new Object[][]{
{"a", "", "", "", "", ""},
{"", "b", "", "", "", ""},
{"", "", "c", "", "", ""},
{"", "", "", "d", "", ""},
{"", "", "", "", "e", ""},
{"", "", "", "", "", "f"},
{"fixed1", "", "", "", "", "", "", ""},
{"fixed2", "", "", "", "", "", "", ""}};
column = new Object[]{"A", "B", "C", "D", "E", "F"};
AbstractTableModel model = new AbstractTableModel() {
private static final long serialVersionUID = 1L;
#Override
public int getColumnCount() {
return column.length;
}
#Override
public int getRowCount() {
return data.length - FIXED_NUM;
}
#Override
public String getColumnName(int col) {
return (String) column[col];
}
#Override
public Object getValueAt(int row, int col) {
return data[row][col];
}
#Override
public void setValueAt(Object obj, int row, int col) {
data[row][col] = obj;
}
public boolean CellEditable(int row, int col) {
return true;
}
};
AbstractTableModel fixedModel = new AbstractTableModel() {
private static final long serialVersionUID = 1L;
#Override
public int getColumnCount() {
return column.length;
}
#Override
public int getRowCount() {
return FIXED_NUM;
}
#Override
public Object getValueAt(int row, int col) {
return data[row + (data.length - FIXED_NUM)][col];
}
};
table = new JTable(model);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
fixedTable = new JTable(fixedModel);
fixedTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
fixedTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JScrollPane scroll = new JScrollPane(table);
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
JScrollPane fixedScroll = new JScrollPane(fixedTable) {
private static final long serialVersionUID = 1L;
#Override
public void setColumnHeaderView(Component view) {
} // work around
}; // fixedScroll.setColumnHeader(null);
fixedScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JScrollBar bar = fixedScroll.getVerticalScrollBar();
JScrollBar dummyBar = new JScrollBar() {
private static final long serialVersionUID = 1L;
#Override
public void paint(Graphics g) {
}
};
dummyBar.setPreferredSize(bar.getPreferredSize());
fixedScroll.setVerticalScrollBar(dummyBar);
final JScrollBar bar1 = scroll.getHorizontalScrollBar();
JScrollBar bar2 = fixedScroll.getHorizontalScrollBar();
bar2.addAdjustmentListener(new AdjustmentListener() {
#Override
public void adjustmentValueChanged(AdjustmentEvent e) {
bar1.setValue(e.getValue());
}
});
scroll.setPreferredSize(new Dimension(400, 100));
fixedScroll.setPreferredSize(new Dimension(400, 52));
getContentPane().add(scroll, BorderLayout.CENTER);
getContentPane().add(fixedScroll, BorderLayout.SOUTH);
}
public static void main(String[] args) {
FixedRowExample frame = new FixedRowExample();
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.pack();
frame.setVisible(true);
}
}
I'm currently implementing a program that uses a JTable to display some information. The table contains no more than 10 rows (so it's small).
While developing, I usually run the programs with the -verbose:gc option.
If I click on the line between 2 columns and keep moving it to the left, then to the right and so on, I notice that a lot of garbage is generated. The program does absolutely nothing while I'm doing this, so there is no other potential source of this garbage. Also, If I stop, the garbage collector also stops collecting.
If I keep resizing these columns for a minute or so, about 100MB+ of garbage is generated, which seems a lot.
This is not affecting how my program runs, but it just seems very weird. Why does it behave this way ?
EDIT
Here is an SSCCE:
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class JTableTest
{
public static void main (String[] args)
{
SwingUtilities.invokeLater (new Runnable ()
{
#Override public void run ()
{
JFrame frame = new JFrame ();
frame.setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE);
frame.setLayout (null);
frame.setSize (700, 300);
frame.setResizable (false);
JTable table = new JTable ();
table.setAutoResizeMode (JTable.AUTO_RESIZE_ALL_COLUMNS);
String[] titles = { "Title 1", "Title 2", "Title 3", "Title 4", "Title 5" };
String[][] data = {
{ "Row 1, Column 1", "Row 1, Column 2", "Row 1, Column 3", "Row 1, Column 4", "Row 1, Column 5"},
{ "Row 2, Column 1", "Row 2, Column 2", "Row 2, Column 3", "Row 2, Column 4", "Row 2, Column 5"},
{ "Row 3, Column 1", "Row 3, Column 2", "Row 3, Column 3", "Row 3, Column 4", "Row 3, Column 5"},
{ "Row 4, Column 1", "Row 4, Column 2", "Row 4, Column 3", "Row 4, Column 4", "Row 4, Column 5"},
{ "Row 5, Column 1", "Row 5, Column 2", "Row 5, Column 3", "Row 5, Column 4", "Row 5, Column 5"}
};
table.setModel (new DefaultTableModel (data, titles)
{
#Override public boolean isCellEditable (int row, int column)
{
return false;
}
});
JScrollPane scrollpane = new JScrollPane (table);
scrollpane.setHorizontalScrollBarPolicy (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollpane.setVerticalScrollBarPolicy (ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollpane.setBounds (20, 20, 650, 250);
frame.add (scrollpane);
frame.setVisible (true);
}
});
}
}
Run the program with the -verbose:gc option. When running, click between "Title x" and "Title y" (x != y) and resize those columns. Keep the mouse clicked and keep moving it left and right. You'll see on stdout that the garbage collector is collecting garbage while you do this. (on my system it's doing this about 10 times / minute). If/when you stop, no more garbage is collected.
It generates garbage simply because it can. Java is a Garbage Collected language, essentially everything it does creates garbage.
While you are holding down and dragging that button, java is taking primitive activity (i.e. mouse button status, cursor position status, time, etc.) and creating events. It then compares that stream of events to things like old cursor position etc. to detect if the program actually wants to do anything with that information. When you do move it, Java needs to draw lines, file rectangles, draw text, etc.
All of those activity leave behind something, garbage, and eventually it needs to be collected.
Just sitting idle, your program is creating garbage, most likely very slowly, as internal timers and such die and are recycled. Try using the jconsole program to watch the heap and you'll see it creep up over time.
This is normal, and nothing to worry about. It's a feature, not a bug.
please
some changes in code
added JTextArea
do you confirm us that your output is the same as the output printed into JTextArea
(WinXP, Java6 --> looks like as forever)
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.text.DefaultCaret;
public class JTableTest {
private javax.swing.Timer timer = null;
private JTextArea text = new JTextArea();
public JTableTest() {
String[] titles = {"Title 1", "Title 2", "Title 3", "Title 4", "Title 5"};
String[][] data = {
{"Row 1, Column 1", "Row 1, Column 2", "Row 1, Column 3", "Row 1, Column 4", "Row 1, Column 5"},
{"Row 2, Column 1", "Row 2, Column 2", "Row 2, Column 3", "Row 2, Column 4", "Row 2, Column 5"},
{"Row 3, Column 1", "Row 3, Column 2", "Row 3, Column 3", "Row 3, Column 4", "Row 3, Column 5"},
{"Row 4, Column 1", "Row 4, Column 2", "Row 4, Column 3", "Row 4, Column 4", "Row 4, Column 5"},
{"Row 5, Column 1", "Row 5, Column 2", "Row 5, Column 3", "Row 5, Column 4", "Row 5, Column 5"}
};
JTable table = new JTable();
table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
table.setModel(new DefaultTableModel(data, titles) {
private static final long serialVersionUID = 1L;
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
});
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollpane = new JScrollPane(table);
scrollpane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollpane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
DefaultCaret caret = (DefaultCaret) text.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
JScrollPane scroll = new JScrollPane(text);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLocation(150, 150);
frame.setSize(700, 300);
frame.setResizable(false);
frame.add(scrollpane, BorderLayout.NORTH);
frame.add(scroll, BorderLayout.CENTER);
frame.setVisible(true);
start();
}
private void start() {
timer = new javax.swing.Timer(1000, updateCol());
timer.start();
}
public Action updateCol() {
return new AbstractAction("text load action") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
text.append("FreeMemory in Kb " + Runtime.getRuntime().freeMemory() / 1000 + "\n");
text.append("MaxMemory in Kb " + Runtime.getRuntime().maxMemory() / 1000 + "\n");
text.append("TotalMemory in Kb " + Runtime.getRuntime().totalMemory() / 1000 + "\n");
text.append("UsedMemory in Kb " + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1000) + "\n");
text.append("\n");
}
};
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JTableTest jTableTest = new JTableTest();
}
});
}
}
EDIT JTable and GC a few columns with 75k rows (82 -85Mb)
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeListener;
import java.text.DecimalFormat;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
public class TriState extends JPanel {
private static final long K = 1024;
private static final long M = K * K;
private static final long G = M * K;
private static final long T = G * K;
protected static int ctr = 1;
private static final long serialVersionUID = 1L;
private JButton btnShow = new JButton("Show Form");
private JLabel lblMem = new JLabel();
private static final DecimalFormat df = new DecimalFormat("#,##0.#");
protected Timer updateTimer = new Timer();
public TriState() {
this.setLayout(new GridLayout());
add(btnShow);
add(lblMem);
updateTimer.scheduleAtFixedRate(new UpdateTimerTask(), 1000, 1000);
btnShow.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
FrmReferrals fr = new FrmReferrals();
fr.setVisible(true);
}
});
}
class UpdateTimerTask extends TimerTask {
public void run() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
dumpMemoryUsage();
}
});
}
}
protected void dumpMemoryUsage() {
System.gc();
Long t = Runtime.getRuntime().totalMemory();
long f = Runtime.getRuntime().freeMemory();
String st = convertToStringRepresentation(t);
String sf = convertToStringRepresentation(f);
String su = convertToStringRepresentation(t - f);
System.out.println("Total:" + st + "(" + t + ") Free:" + sf + "(" + f + ") Used:" + su + "(" + (t - f) + ")");
lblMem.setText(su + "/" + st);
}
public static String convertToStringRepresentation(final long value) {
final long[] dividers = new long[]{T, G, M, K, 1};
final String[] units = new String[]{"TB", "GB", "MB", "KB", "B"};
if (value < 1) {
throw new IllegalArgumentException("Invalid file size: " + value);
}
String result = null;
for (int i = 0; i < dividers.length; i++) {
final long divider = dividers[i];
if (value >= divider) {
final double dr = divider > 1 ? (double) value / (double) divider : (double) value;
result = df.format(dr) + units[i];
break;
}
}
return result;
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("SimpleTableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create and set up the content pane.
TriState newContentPane = new TriState();
newContentPane.setOpaque(true); // content panes must be opaque
frame.setContentPane(newContentPane);
// Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
protected class PopupMenu extends JPopupMenu {
public PopupMenu() {
JRadioButtonMenuItem item1 = new JRadioButtonMenuItem(new AbstractAction("Insert Item") {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.getActionCommand());
}
});
item1.setActionCommand("Insert");
add(item1);
JRadioButtonMenuItem item2 = new JRadioButtonMenuItem(new AbstractAction("Delete Item") {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.getActionCommand());
}
});
item2.setActionCommand("Delete");
add(item2);
}
}
public class FrmReferrals extends JFrame {
public FrmReferrals() {
super();
init();
}
protected void init() {
jbInit();
}
protected void closeIt() {
uninit();
}
// variables here
final Dimension dimPreferred = new Dimension(1270, 995);
final JTabbedPane tabbedPane = new JTabbedPane();
private JTable tblReferrals = null;
private PopupMenu popMenu = new PopupMenu();
protected void jbInit() {
setPreferredSize(dimPreferred);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setTitle("Referrals");
JPanel pnl = new JPanel();
pnl.setOpaque(false);
pnl.setLayout(new BorderLayout());
pnl.add(tabbedPane, BorderLayout.CENTER);
// put it all in the frame
add(pnl);
pack();
setLocationRelativeTo(null);
// init the table and model
ReferralsTableModel ctm = new ReferralsTableModel(buildDummyVector());
tblReferrals = new JTable(ctm);
tblReferrals.setComponentPopupMenu(popMenu);
tblReferrals.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
tabbedPane.add(new JScrollPane(tblReferrals, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
addWindowListener(new WindowListener() {
#Override
public void windowActivated(WindowEvent e) {
}
#Override
public void windowClosed(WindowEvent e) {
}
#Override
public void windowClosing(WindowEvent e) {
closeIt();
}
#Override
public void windowDeactivated(WindowEvent e) {
}
#Override
public void windowDeiconified(WindowEvent e) {
}
#Override
public void windowIconified(WindowEvent e) {
}
#Override
public void windowOpened(WindowEvent e) {
}
});
}
protected Vector<DBO_Referrals> buildDummyVector() {
Vector<DBO_Referrals> vr = new Vector<DBO_Referrals>();
for (int x = 0; x < 75000; x++) {
DBO_Referrals r = new DBO_Referrals(x + (5000 * ctr));
vr.add(r);
}
return vr;
}
protected void uninit() {
tblReferrals.setComponentPopupMenu(null);
for (Component c : popMenu.getComponents()) {
PropertyChangeListener[] pl = c.getPropertyChangeListeners();
for (PropertyChangeListener l : pl) {
c.removePropertyChangeListener(l);
}
if (c instanceof JMenuItem) {
ActionListener[] al = ((JMenuItem) c).getActionListeners();
for (ActionListener l : al) {
((JMenuItem) c).removeActionListener(l);
}
}
}
popMenu = null;
}
protected class DBO_Referrals {
private long id;
private String Employee;
private String Rep;
private String Asst;
private String Client;
private String Dates;
private String Status;
private String Home;
public DBO_Referrals(long id) {
this.id = id;
Employee = "Employee" + id;
Rep = "Rep" + id;
Asst = "Asst" + id;
Client = "Client" + id;
Dates = "Dates" + id;
Status = "Status" + id;
Home = "Home" + id;
}
public long getId() {
return id;
}
public String getEmployee() {
return Employee;
}
public String getRep() {
return Rep;
}
public String getAsst() {
return Asst;
}
public String getClient() {
return Client;
}
public String getDates() {
return Dates;
}
public String getStatus() {
return Status;
}
public String getHome() {
return Home;
}
}
public class ReferralsTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private Vector<DBO_Referrals> data = new Vector<DBO_Referrals>();
final String[] sColumns = {"id", "Employee", "Rep", "Assistant", "Client", "Date", "Status", "Home", "R"};
public ReferralsTableModel() {
super();
}
public ReferralsTableModel(Vector<DBO_Referrals> data) {
this();
this.data = data;
}
#SuppressWarnings("unchecked")
#Override
public Class<?> getColumnClass(int col) {
switch (col) {
case 0:
return Long.class;
default:
return String.class;
}
}
#Override
public int getColumnCount() {
return sColumns.length;
}
#Override
public int getRowCount() {
return data.size();
}
#Override
public Object getValueAt(int row, int col) {
if (row > data.size()) {
return null;
}
DBO_Referrals a = data.get(row);
switch (col) {
case 0:
return a.getId();
case 1:
return a.getEmployee();
case 2:
return a.getRep();
case 3:
return a.getAsst();
case 4:
return a.getClient();
case 5:
return a.getDates();
case 6:
return a.getStatus();
case 7:
return a.getHome();
case 8:
return "+";
default:
return null;
}
}
}
}
}
I develop a simple MVC Calculator app. I decided to add some functionality by implementing KeyListener in CalculatorView. But this KeyListener only responds when there is no input in JTextField (before any input was made by pushing GUI buttons) or it responds when I press "ESC". I know some people here advice to use KeyBindings instead of KeyListener, but then I need to have 12 KeyBindings in my code (10 for numbers, 1 for ESC and 1 for "." character). Is there any way to make KeyListener to work properly in my app?
And here is the code:
/**
*
* #author Kate Nezdoly
*/
public class CalculatorView implements ActionListener, KeyListener {
private JButton[] operButtons = new JButton[13];
private JButton[] numberButtons = new JButton[12];
private String[] operators = {"C", "(", ")", "+", "-", "*", "/", "^", "cos", "sin",
"tan", "sqrt"};
private String[] numbers = {"1", "2", "3", "4", "5", "6", "7", "8",
"9", "0", ".", "="};
public CalculatorView() {
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
} catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
System.err.println(e.getMessage());
}
createAndShowGUI();
}
private JTextField input;
private boolean decimal = true;
private JPanel createContentPane() {
JPanel totalGUI = new JPanel(new BorderLayout(12, 8));
input = new JTextField("0.0", 18);
input.addKeyListener(this);
input.setEditable(false);
input.setBackground(Color.white);
input.setHorizontalAlignment(JTextField.RIGHT);
JPanel action_buttons = new JPanel(new GridLayout(5, 2));
operButtons[0] = new JButton(operators[0]);
action_buttons.add(operButtons[0]);
for (int i = 1; i < operators.length; i++) {
operButtons[i] = new JButton(operators[i]);
operButtons[i].addActionListener(this);
operButtons[i].setActionCommand(operators[i]);
action_buttons.add(operButtons[i]);
}
JPanel number_buttons = new JPanel(new GridLayout(5, 2));
for (int i = 0; i < numbers.length - 1; i++) {
numberButtons[i] = new JButton(numbers[i]);
numberButtons[i].addActionListener(this);
numberButtons[i].setBackground(Color.lightGray);
numberButtons[i].setActionCommand(numbers[i]);
number_buttons.add(numberButtons[i]);
}
numberButtons[11] = new JButton(numbers[11]);
number_buttons.add(numberButtons[11]);
totalGUI.add(input, BorderLayout.PAGE_START);
totalGUI.add(number_buttons, BorderLayout.CENTER);
totalGUI.add(action_buttons, BorderLayout.LINE_END);
totalGUI.setOpaque(true);
return totalGUI;
}
private void createAndShowGUI() {
JFrame frame = new JFrame("Calculator");
frame.setContentPane(createContentPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
frame.setSize(300, 190);
frame.setResizable(false);
}
public void actionPerformed(ActionEvent ae) {
String temp = ae.getActionCommand();
if (input.getText().equals("0.0")) {
input.setText("");
}
if (temp.equals(".")) {
if (decimal) {
decimal = false;
input.setText(input.getText() + "" + temp);
}
}
else {
input.setText(input.getText() + "" + temp);
}
}
public void buttonActionListeners(ActionListener al) {
//add "=" action listener
numberButtons[11].setActionCommand(numbers[11]);
numberButtons[11].addActionListener(al);
//add "C" action listener
operButtons[0].setActionCommand(operators[0]);
operButtons[0].addActionListener(al);
}
// Gets the text from the Text Box and converts it into a Double.
public String getFieldText() {
return input.getText();
}
// Sets the text displayed on the Text Box.
public void setFieldText(String message) {
input.setText("" + message);
decimal = true;
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 27) {
System.exit(0);
} else if (e.getKeyCode() >= 48 && e.getKeyCode() <= 57) {
if (input.getText().equals("0.0")) {
setFieldText(String.valueOf(e.getKeyChar()));
} else {
setFieldText(input.getText() + e.getKeyChar());
}
}
}
#Override
public void keyReleased(KeyEvent e) {
}
}
Controller class:
public class CalculatorController implements ActionListener {
private CalculatorView view;
public CalculatorController( CalculatorView view) {
this.view = view;
view.buttonActionListeners(this);
}
#Override
public void actionPerformed(ActionEvent e) {
String action = e.getActionCommand();
switch (action) {
case "=":
view.setFieldText(Parser.parse(view.getFieldText()));
break;
case "C":
view.setFieldText("0.0");
break;
}
}
public static void main(String args[]){
CalculatorView calc = new CalculatorView();
CalculatorController contr = new CalculatorController(calc);
}
}
I think that there isn't any reason for implement KeyListener/KeyBinding,
1) add as ActionCommand to the JButtons example here
private String[] numbers = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", ".", "="};
2) change JTextField to the JFormattedTextField with NumberInstance/Formatter, then there are alowed only Numbers and decimal separator, and no longer there reason for listening from KeyBoard by implement KeyListener/KeyBindings nor parsing/testing for NumberInstance
3) if is there more than one that one JFormattedTextField (value could be imputed or pasted from ClipBoard) or for example JFormattedTextField and JTextArea (for showing previous calculations) then chaining these fiedls by using DocumentListener