问题
i have been wondering for a long time, whilst creating several stupid solutions for this Problem, how the following should be done properly:
DataTable: ID | givenname | lastname | address | data ...
I want to show all givennames + lastnames in a listbox and uppon selection of one item, i want to retrieve the rest of the corresponding dataset and display is in some textboxes.
So i basically do:
1) Query: SELECT ID, givenname, lastname FROM DataTable;
2) Create and ArrayList of "Contact Objects" (just a class that has the same members as the DataTable has columns), I iterate over the resultset and so create several of these Objects with ID, givenname and lastname.
!3) i want the listbox to display givenname + " " + lastname, but on selection of "John Doe" i want the programm to know what element of the arraylist this "john Doe" was (in case there is more than one of them), retireve the ID from the object and retireve his address and "data"
What i often did was something like "the 3rd John Doe on the listbox was selected, lets look for the 3rd john doe in the arraylist and hope to god that this is right" which seems highly unnecessary to me.
What is a usable solution for this in Java + Swing
i hope i could somehow make clear what i need^^
regards Billdoor
回答1:
To display an Object, Swing components will use the toString() method the Object placed in it. A common approach is to create a Data class that holds the name, ID, etc., implement toString() to display what you want, and then put a list of these objects in your JList. Then on selection, get the selected item, cast it to the data class, and then call getID().
回答2:
You should create a table model to hold your data and create renderers, if needed, to present it correctly. See How to Use Tables for details. Then in the selection listener for the table you can retrieve the relevant row. You can use TableModel.getValueAt()
or add helper methods to retrieve the selected data. Below is a simple example of user model. The app prints a selected user including the id that is not visible in the table. There is a convenience method getUser()
in the model to get the user at specific row. Note that you can also use DefaultTableModel
for simple scenarios as this.
import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.AbstractTableModel;
public class UserTableDemo {
public UserTableDemo() {
JFrame frame = new JFrame("UserTable");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final UserModel model = new UserModel();
final JTable table = new JTable();
table.setModel(model);
JScrollPane scrollPane = new JScrollPane(table);
JPanel content = new JPanel(new BorderLayout());
content.add(scrollPane, BorderLayout.CENTER);
final JTextArea output = new JTextArea(5, 30);
content.add(output, BorderLayout.SOUTH);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
UserEntry entry = model.getUser(table
.getSelectedRow());
if (entry != null) {
output.setText("Selected row:"
+ table.getSelectedRow() + " "
+ entry.toString());
} else {
output.setText("");
}
}
}
});
frame.add(content);
frame.setLocationByPlatform(true);
frame.pack();
frame.setVisible(true);
}
public class UserModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private List<UserEntry> users = new ArrayList<UserEntry>();
public UserModel() {
//TODO - load users
users.add(new UserEntry(3, "John", "Doe"));
users.add(new UserEntry(2, "John", "Doe"));
users.add(new UserEntry(1, "John", "Doe"));
}
public UserEntry getUser(int row) {
if(row >= 0 && row < users.size())
return users.get(row);
return null;
}
@Override
public int getRowCount() {
return users.size();
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
UserEntry entry = users.get(rowIndex);
switch (columnIndex) {
case 0:
return entry.getFirstName();
case 1:
return entry.getLastName();
}
return null;
}
@Override
public String getColumnName(int column) {
switch (column) {
case 0:
return "First Name";
case 1:
return "Last Name";
}
return null;
}
}
public class UserEntry {
private int id;
private String firstName;
private String lastName;
public UserEntry(int id, String firstName, String lastName) {
super();
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
public int getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
@Override
public String toString() {
return "UserEntry [id=" + id + ", firstName=" + firstName
+ ", lastName=" + lastName + "]";
}
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new UserTableDemo();
}
});
}
}
Same process would be if you're using JList
instead of JTable
.
EDIT:
Here is a similar example that uses JList
with DefaultListModel
and a custom renderer to display list of users.
import java.awt.BorderLayout;
import java.awt.Component;
import javax.swing.*;
import javax.swing.event.*;
public class UserListDemo {
public UserListDemo() {
JFrame frame = new JFrame("User List");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JList list = new JList();
JScrollPane scrollPane = new JScrollPane(list);
JPanel content = new JPanel(new BorderLayout());
content.add(scrollPane, BorderLayout.CENTER);
final JTextArea output = new JTextArea(5, 40);
content.add(output, BorderLayout.SOUTH);
final DefaultListModel model = new DefaultListModel();
model.addElement(new UserEntry(3, "John", "Doe"));
model.addElement(new UserEntry(1, "John", "Doe"));
model.addElement(new UserEntry(3, "John", "Doe"));
list.setModel(model);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setCellRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list,
Object value, int index, boolean isSelected,
boolean hasFocus) {
if (value instanceof UserEntry) {
return super.getListCellRendererComponent(list,
((UserEntry) value).getFirstName() + " "
+ ((UserEntry) value).getLastName(), index,
isSelected, hasFocus);
}
return super.getListCellRendererComponent(list, value, index,
isSelected, hasFocus);
}
});
list.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
UserEntry entry = (UserEntry) list
.getSelectedValue();
if (entry != null) {
output.setText("Selected row:"
+ list.getSelectedIndex() + " "
+ entry.toString());
} else {
output.setText("");
}
}
}
});
frame.add(content);
frame.setLocationByPlatform(true);
frame.pack();
frame.setVisible(true);
}
public class UserEntry {
private int id;
private String firstName;
private String lastName;
public UserEntry(int id, String firstName, String lastName) {
super();
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
public int getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
@Override
public String toString() {
return "UserEntry [id=" + id + ", firstName=" + firstName
+ ", lastName=" + lastName + "]";
}
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new UserListDemo();
}
});
}
}
回答3:
I think that you can store your id
somewhere aside. Like in HTML
take the tag <option>
, I would do :
<option value="id">Jonh Doe</option>
The value inside the attribute value
would be the actual Id from the database, and the text would be givenname + " " + lastname
.
This way, I'm keeping what is related to identify the person and I'm showing the name. After that, when the user would choose an item, I will retrieve the information base on the id
from the value
attribute.
来源:https://stackoverflow.com/questions/15573972/best-practice-database-access-list-of-contacts