Trying to go through the Swing tutorial in NetBeans has always been hard, simply
because the code looks so much different than the code that NetBeans uses. You
can't just copy and paste their code in, because then you wouldn't be able to
see the form in the design view. And of course, the samples don't use Matisse
for layout rules, and really why would you use anything else?
I decided to try and power my way through some of the examples anyway. First
stop: tables.
I'm gonna look at some code, like SimpleTableSelectionDemo.java,
and try to reproduce it in NetBeans.
Warning: I know very little about GUI development so this is a case
of the blind leading the blind. I will most likely do things that will make
real developers grimace. If so, please tell me.
First create a Java Application project with no main class. Create a JFrame
called SimpleTableSelectionDemo and just put a JTable into it, expanded
to all four sides of the JFrame so it resizes correctly.
Now we encounter the first problem - getting the column values and names into
the table and populating it with some data. The example creates two arrays and
uses the arrays to set these:
final String[] columnNames = {"First Name",
"Last Name",
"Sport",
"# of Years",
"Vegetarian"};
final Object[][] data = {
{"Mary", "Campione",
"Snowboarding", new Integer(5), new Boolean(false)},
{"Alison", "Huml",
"Rowing", new Integer(3), new Boolean(true)},
{"Kathy", "Walrath",
"Knitting", new Integer(2), new Boolean(false)},
{"Sharon", "Zakhour",
"Speed reading", new Integer(20), new Boolean(true)},
{"Philip", "Milne",
"Pool", new Integer(10), new Boolean(false)}
};
final JTable table = new JTable(data, columnNames);
But the IDE just the arrays straign into the parameters of DefaultTableModel:
jTable1.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{null, null, null, null},
{null, null, null, null},
{null, null, null, null},
{null, null, null, null}
},
new String [] {
"Title 1", "Title 2", "Title 3", "Title 4"
}
));
Not a big deal, the model property editor can be used to set this. To open
the editor, select the JTable in the Inspector window (not in the Design Area,
because that just selects the JScrollPane that the JTable resides in) and in
the Properties window click the model property. We can do one of the following:
- With Select Mode set to TableModelEditor at the top, just enter the column
names and types in the Table Settings tab and the default values in the Default
Values section.
- Copy the two arrays from the example file and paste them into the field
declarations in your file. Then open the model property editor, set Select
Mode to Form Connection, select User Code, and enter the following:
new DefaultTableModel(data, columnNames)
Notice that the IDE has code completion in this editor. Once you get back
to the source view, make sure to fix your imports to import DefaultTableModel.
One major limitation here is that if you define the model in this way, you
don't get to view it in the Design View. Not sure why that is, but I will
investigate.
I did the latter, just because I'm too lazy to enter all of that stuff into
the GUI when I can just copy and paste the two arrays.
Now where to put the rest of the code, namely the code that defines the selection
model? Most of the examples have a createAndShowGUI method that's called
from the main method to actually initialize and create the form. NetBeans does
something similar in the initComponents method. This method is in a guarded
blue block, which means you can't edit it manually. It is then called by in
the JFrame constructor method, which is editable.
So for this example, the simplest thing is to let the IDE do its thing when
initiating the code in the initComponents section, then add the code to further
tune the component behavior in the constructor (or in a separate method that's
then called by the constructor).
Before you start cutting and pasting, rename the JTable variable name to match
what's in the example code by clicking the jTable1 node in the Inspector window,
pressing F2, and typing table. Then copy the following code in bold
into the constructor.
public SimpleTableSelectionDemo() {
initComponents();
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
if (ALLOW_ROW_SELECTION) { // true by default
ListSelectionModel rowSM = table.getSelectionModel();
rowSM.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
//Ignore extra messages.
if (e.getValueIsAdjusting()) return;
ListSelectionModel lsm = (ListSelectionModel)e.getSource();
if (lsm.isSelectionEmpty()) {
System.out.println("No rows are selected.");
} else {
int selectedRow = lsm.getMinSelectionIndex();
System.out.println("Row " + selectedRow
+ " is now selected.");
}
}
});
} else {
table.setRowSelectionAllowed(false);
}
if (ALLOW_COLUMN_SELECTION) { // false by default
if (ALLOW_ROW_SELECTION) {
//We allow both row and column selection, which
//implies that we *really* want to allow individual
//cell selection.
table.setCellSelectionEnabled(true);
}
table.setColumnSelectionAllowed(true);
ListSelectionModel colSM =
table.getColumnModel().getSelectionModel();
colSM.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
//Ignore extra messages.
if (e.getValueIsAdjusting()) return;
ListSelectionModel lsm = (ListSelectionModel)e.getSource();
if (lsm.isSelectionEmpty()) {
System.out.println("No columns are selected.");
} else {
int selectedCol = lsm.getMinSelectionIndex();
System.out.println("Column " + selectedCol
+ " is now selected.");
}
}
});
}
if (DEBUG) {
table.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
printDebugData(table);
}
});
}
}
Now add the boolean fields at the top of the file:
private boolean DEBUG = false;
private boolean ALLOW_COLUMN_SELECTION = true;
private boolean ALLOW_ROW_SELECTION = true;
And add the printDebugData method somewhere in the file:
private void printDebugData(JTable table) {
int numRows = table.getRowCount();
int numCols = table.getColumnCount();
javax.swing.table.TableModel model = table.getModel();
System.out.println("Value of data: ");
for (int i=0; i < numRows; i++) {
System.out.print(" row " + i + ":");
for (int j=0; j < numCols; j++) {
System.out.print(" " + model.getValueAt(i, j));
}
System.out.println();
}
System.out.println("--------------------------");
}
And run the file. Notice that you can select only rows and the Output Window
says which row you selected. If you change the boolean values in ALLOW_COLUMN_SELECTION
and ALLOW_ROW_SELECTION and run again, you can select cells, rows,
or columns, and the Output Window tells you which one you've selected.
Here's the completed version of my file.