Tar*_*ity 0 java jtable jlist defaultlistmodel defaulttablemodel
我正在尝试以这样的方式显示患者数据列表,即名称位于我的JList的左侧,并且标识号全部整齐地排列在右侧.我已经查看过甚至为此任务实现了JTable的使用,因为它提供了我希望在这个项目中实现的整洁的列结构,但是有一些功能我要么不知道如何实现,要么我觉得缺乏JTable.
无法根据字母数字键转换我的列表.这是最终用户快速搜索列表的主要方式,因为填充时它可以超过800行.(例如:输入's'转换到以's开头的列表部分)
在视觉上我不喜欢JTables的行选择; 使用两列结构显然两列之间存在中断,与JList不同,这是一个很好的平滑无缝突出显示选择.所有网格线都已关闭,以及使用单元格编辑作为FYI.
我已经包含了我认为的相关代码.我希望能有一些方向,如果我要求的是用JList完成的,还是有办法更好地操作JTable?我没有在JTable API和JList API中找到任何内容,我觉得我在这个问题上回答了我的问题.
package mosaiqToCTWorklist;
import java.awt.Font;
import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.ButtonGroup;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;
public class PatientSelectionWindow extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private JRadioButton rdbtnActivePatients;
private JRadioButton rdbtnInactivePatients;
private JRadioButton rdbtnAllPatients;
private JButton btnSendSelection;
private JList<String> patients;
private JScrollPane scrollBar;
private ButtonGroup btngroup;
private DefaultListModel<String> model = new DefaultListModel<String>();
private List<PatientData> ptList;
// private HashMap<String,PatientData> ptRecords;
private Label lblPatientTotal;
private Label lblDOB;
private Label lblAge;
private Label lblGender;
private Label label_4;
public PatientSelectionWindow(List<PatientData> ptList) {
this.ptList = ptList;
activePatients();
createWindow();
}
public void createWindow() {
setResizable(false);
setTitle("Mosaiq to CT Worklist");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setBounds(100, 100, 534, 378);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
patients = new JList<String>(model);
scrollBar = new JScrollPane(patients);
scrollBar.setBounds(10, 11, 376, 328);
scrollBar.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
contentPane.add(scrollBar);
rdbtnActivePatients = new JRadioButton("Active Patients");
rdbtnActivePatients.addActionListener(this);
rdbtnActivePatients.setSelected(true);
rdbtnActivePatients.setFont(new Font("Tahoma", Font.PLAIN, 13));
rdbtnActivePatients.setBounds(392, 35, 130, 23);
contentPane.add(rdbtnActivePatients);
rdbtnInactivePatients = new JRadioButton("Inactive Patients");
rdbtnInactivePatients.addActionListener(this);
rdbtnInactivePatients.setFont(new Font("Tahoma", Font.PLAIN, 13));
rdbtnInactivePatients.setBounds(392, 61, 130, 23);
contentPane.add(rdbtnInactivePatients);
rdbtnAllPatients = new JRadioButton("All Patients");
rdbtnAllPatients.addActionListener(this);
rdbtnAllPatients.setFont(new Font("Tahoma", Font.PLAIN, 13));
rdbtnAllPatients.setBounds(392, 86, 130, 23);
contentPane.add(rdbtnAllPatients);
btngroup = new ButtonGroup();
btngroup.add(rdbtnActivePatients);
btngroup.add(rdbtnInactivePatients);
btngroup.add(rdbtnAllPatients);
btnSendSelection = new JButton("Send Selected");
btnSendSelection.addActionListener(new DicomTransfer());
btnSendSelection.setFont(new Font("Tahoma", Font.PLAIN, 13));
btnSendSelection.setBounds(396, 154, 126, 38);
contentPane.add(btnSendSelection);
Label label = new Label("Show");
label.setFont(new Font("Dialog", Font.BOLD, 11));
label.setBounds(392, 10, 62, 22);
contentPane.add(label);
lblPatientTotal = new Label("");
setPatientCount();
lblPatientTotal.setBounds(392, 115, 130, 29);
contentPane.add(lblPatientTotal);
Label label_1 = new Label("D.O.B:");
label_1.setBounds(396, 252, 38, 22);
contentPane.add(label_1);
Label label_2 = new Label("Age:");
label_2.setBounds(396, 226, 30, 22);
contentPane.add(label_2);
Label label_3 = new Label("Gender:");
label_3.setBounds(396, 280, 46, 22);
contentPane.add(label_3);
lblDOB = new Label("1984-10-10");
lblDOB.setBounds(434, 252, 88, 22);
contentPane.add(lblDOB);
lblAge = new Label("64");
lblAge.setBounds(426, 226, 38, 22);
contentPane.add(lblAge);
lblGender = new Label("male");
lblGender.setBounds(444, 280, 62, 22);
contentPane.add(lblGender);
label_4 = new Label("Currently Selected Pt.");
label_4.setFont(new Font("Dialog", Font.BOLD, 11));
label_4.setBounds(392, 198, 130, 22);
contentPane.add(label_4);
}
private void setPatientCount() {
Integer patientTotal = model.size();
lblPatientTotal.setText("Total Patients: " + patientTotal.toString());
}
private void activePatients() {
model.clear();
for(PatientData pt : ptList){
if (pt.getActiveStatus() == 1) {
model.addElement(pt.getLastName() + ", " + pt.getFirstName() + " "
+ pt.getMiddleName() + " " + pt.getMHN() );
}
}
}
private void inActivePatients() {
model.clear();
for(PatientData pt : ptList){
if (pt.getActiveStatus() == 0) {
model.addElement(pt.getLastName() + ", " + pt.getFirstName() + " "
+ pt.getMiddleName() + " " + pt.getMHN() );
}
}
}
public void allPatients() {
model.clear();
for(PatientData pt : ptList){
model.addElement(pt.getLastName() + ", " + pt.getFirstName() + " "
+ pt.getMiddleName() + " " + pt.getMHN() );
}
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == rdbtnActivePatients) {
activePatients();
}
if (e.getSource() == rdbtnAllPatients) {
allPatients();
}
if (e.getSource() == rdbtnInactivePatients) {
inActivePatients();
}
patients.setModel(model);
setPatientCount();
}
}
Run Code Online (Sandbox Code Playgroud)
(是的,我知道我正在使用水果......我很饿)我得到的例子与我希望的更多内容.它只是让最终用户更容易阅读我的感受.


让我们从模型和视图与其职责之间的差异开始.
模型的责任是以某种方式"建模"数据.这通常意味着提供有关模型大小(包含在其中的项目数)和以某种方式访问数据(getter)的信息.
视图的责任是决定如何最好地显示此数据.
这一切对你的问题有什么影响?事实上,每件事.模型不应该尝试预先格式化数据,而应该包含原始数据.决定如何显示数据是视图的责任.
例如,您可能有一个JList显示患者数据的形式{mhn} {first name} {last name},但另一个JList想要{lastname}, {first name} {givenname}......
您不希望每次都创建新模型,而是需要一个仅包含原始数据的简单模型,这些模型可以传递给这些视图中的任何一个,并允许它们决定如何显示此信息.在你告诉我"这不会发生"之前......只是知道,它会,因为那是用户的方式......
所以,而不是......
private DefaultListModel<String> model = new DefaultListModel<String>();
private List<String> ptList;
Run Code Online (Sandbox Code Playgroud)
你想要使用更像......的东西
private DefaultListModel<PatientData> model = new DefaultListModel<PatientData>();
private List<PatientData> ptList;
Run Code Online (Sandbox Code Playgroud)
现在,这将引发下一个问题"如何格式化原始数据?".Swing提供渲染器(并且在一些情况下,编辑器),其提供可伸展的和可插入的API,其提供你通过它可以提供"格式化器"来象类的装置的概念JList,JTable和JTree.这是一个重要的概念,因为它在Swing中被广泛使用.
首先看一下如何使用列表,编写自定义单元格渲染器
现在,因为我们正在处理结构化数据,所以事情变得有点困难,因为JList它不是为处理这种性质的结构化数据而设计的.请记住,每个单元格/行都是单独渲染的,没有任何其他单元格或行的上下文,这使得复杂的结构非常困难JList,例如......
一种方法是ListCellRenderer从头开始创建我们自己的.这是有问题的,因为单元格的大部分格式都来自于DefaultListCellRenderer,因此我们需要自己提供所有格式,并且因为我们使用多个组件,这会使问题更加复杂.
以下渲染器将产生以下输出...

public class NameFirstWithMNHListCellRenderer extends JPanel implements ListCellRenderer<PatientData> {
private static final Border SAFE_NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 1);
private static final Border DEFAULT_NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 1);
protected static Border noFocusBorder = DEFAULT_NO_FOCUS_BORDER;
private JLabel name;
private JLabel mhn;
public NameFirstWithMNHListCellRenderer() {
name = new JLabel();
mhn = new JLabel();
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.anchor = GridBagConstraints.WEST;
add(name, gbc);
gbc.gridx++;
gbc.weightx = 0;
gbc.anchor = GridBagConstraints.EAST;
add(mhn, gbc);
}
@Override
public Component getListCellRendererComponent(JList<? extends PatientData> list, PatientData value, int index, boolean isSelected, boolean cellHasFocus) {
name.setText(value.getFirstName() + " " + value.getLastName());
mhn.setText(value.getMHN());
formatBackground(name, list, index, isSelected, cellHasFocus);
formatBackground(mhn, list, index, isSelected, cellHasFocus);
formatBackground(this, list, index, isSelected, cellHasFocus);
formatForeground(name, list, index, isSelected, cellHasFocus);
formatForeground(mhn, list, index, isSelected, cellHasFocus);
formatForeground(this, list, index, isSelected, cellHasFocus);
formatBorder(this, list, index, isSelected, cellHasFocus);
return this;
}
private Border getNoFocusBorder() {
Border border = UIManager.getBorder("List.cellNoFocusBorder");
if (System.getSecurityManager() != null) {
if (border != null) return border;
return SAFE_NO_FOCUS_BORDER;
} else {
if (border != null &&
(noFocusBorder == null ||
noFocusBorder == DEFAULT_NO_FOCUS_BORDER)) {
return border;
}
return noFocusBorder;
}
}
protected void formatBorder(JComponent comp, JList<? extends PatientData> list, int index, boolean isSelected, boolean cellHasFocus) {
Border border = null;
if (cellHasFocus) {
if (isSelected) {
border = UIManager.getBorder("List.focusSelectedCellHighlightBorder");
}
if (border == null) {
border = UIManager.getBorder("List.focusCellHighlightBorder");
}
} else {
border = getNoFocusBorder();
}
comp.setBorder(border);
}
protected void formatBackground(JComponent comp, JList<? extends PatientData> list, int index, boolean isSelected, boolean cellHasFocus) {
Color bg = null;
JList.DropLocation dropLocation = list.getDropLocation();
if (dropLocation != null
&& !dropLocation.isInsert()
&& dropLocation.getIndex() == index) {
bg = UIManager.getColor("List.dropCellBackground");
isSelected = true;
}
if (isSelected) {
comp.setBackground(bg == null ? list.getSelectionBackground() : bg);
} else {
comp.setBackground(list.getBackground());
}
comp.setOpaque(isSelected);
setEnabled(list.isEnabled());
}
protected void formatForeground(Component comp, JList<? extends PatientData> list, int index, boolean isSelected, boolean cellHasFocus) {
Color fg = null;
JList.DropLocation dropLocation = list.getDropLocation();
if (dropLocation != null
&& !dropLocation.isInsert()
&& dropLocation.getIndex() == index) {
fg = UIManager.getColor("List.dropCellForeground");
isSelected = true;
}
if (isSelected) {
comp.setForeground(fg == null ? list.getSelectionForeground() : fg);
} else {
comp.setForeground(list.getForeground());
}
comp.setEnabled(list.isEnabled());
comp.setFont(list.getFont());
}
}
Run Code Online (Sandbox Code Playgroud)
现在,在你从房间尖叫着奔跑之前,这只是一个可能的解决方案的演示.还有其他一些方法可以实现相同的结果,这些方法稍微复杂一点,但是会引入自己的问题......
这一切的长短都不是JList设计用于以这种方式支持结构化数据,这就是为什么我们JTable......
JTable另一方面,A 非常适合显示结构化数据,并且通过一些简单的调整,可以使其"显示"无缝...
让我们从TableModel... 开始
public static class PatientTableModel extends AbstractTableModel {
protected static final String[] COLUMN_NAMES = {
"First name",
"Last name",
"MHN"
};
private List<PatientData> rowData;
public PatientTableModel() {
rowData = new ArrayList<>(25);
}
public void add(PatientData... pd) {
add(Arrays.asList(pd));
}
public void add(List<PatientData> pd) {
rowData.addAll(pd);
fireTableDataChanged();
}
@Override
public int getRowCount() {
return rowData.size();
}
@Override
public int getColumnCount() {
return COLUMN_NAMES.length;
}
@Override
public String getColumnName(int column) {
return COLUMN_NAMES[column];
}
public PatientData getPatientDataAt(int row) {
return rowData.get(row);
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
PatientData pd = getPatientDataAt(rowIndex);
Object value = null;
switch (columnIndex) {
case 0:
value = pd.getFirstName();
break;
case 1:
value = pd.getLastName();
break;
case 2:
value = pd.getMHN();
break;
}
return value;
}
}
Run Code Online (Sandbox Code Playgroud)
这是负责定义行和列结构,这里我打破了名字,姓氏和MHN在单独的列上,这是个人选择,如果你愿意,你可以组合名称列...
接下来,我们需要准备JTable......
patients = new JTable(model);
patients.setShowGrid(false);
patients.setShowHorizontalLines(false);
patients.setShowVerticalLines(false);
patients.setRowMargin(0);
patients.setIntercellSpacing(new Dimension(0, 0));
patients.setFillsViewportHeight(true);
TableRowSorter<PatientTableModel> sorter = new TableRowSorter<>(model);
patients.setRowSorter(sorter);
Run Code Online (Sandbox Code Playgroud)
这会设置表格,使其不显示水平或垂直网格线,并减少单元格之间的填充,0使其显示为无缝的数据线...
接下来,我们需要准备模型......
public PatientSelectionWindow(List<PatientData> ptList) {
this.ptList = ptList;
model.add(ptList);
createWindow();
activePatients();
}
Run Code Online (Sandbox Code Playgroud)
你会在一分钟内看到,你不再需要ptList......
接下来,我们需要改变过滤...
private void activePatients() {
RowFilter<PatientTableModel, Integer> rf = new RowFilter<PatientTableModel, Integer>() {
@Override
public boolean include(RowFilter.Entry<? extends PatientTableModel, ? extends Integer> entry) {
int row = entry.getIdentifier();
PatientData pd = entry.getModel().getPatientDataAt(row);
return pd.getActiveStatus() == 1;
}
};
((TableRowSorter) patients.getRowSorter()).setRowFilter(rf);
setPatientCount();
}
private void inActivePatients() {
RowFilter<PatientTableModel, Integer> rf = new RowFilter<PatientTableModel, Integer>() {
@Override
public boolean include(RowFilter.Entry<? extends PatientTableModel, ? extends Integer> entry) {
int row = entry.getIdentifier();
PatientData pd = entry.getModel().getPatientDataAt(row);
return pd.getActiveStatus() != 1;
}
};
((TableRowSorter) patients.getRowSorter()).setRowFilter(rf);
setPatientCount();
}
public void allPatients() {
((TableRowSorter) patients.getRowSorter()).setRowFilter(null);
setPatientCount();
}
Run Code Online (Sandbox Code Playgroud)
这三种方法基本上利用RowFilter了JTableAPI中可用的支持,这意味着您不需要物理接触模型或更改模型或单独管理数据,这一切都由您照顾...
然后我们最终得到以下结果......

看一眼:
更多细节
| 归档时间: |
|
| 查看次数: |
3471 次 |
| 最近记录: |