Java JList格式与JTable功能

Java JList格式与JTable功能,java,jtable,jlist,defaulttablemodel,defaultlistmodel,Java,Jtable,Jlist,Defaulttablemodel,Defaultlistmodel,我试图以这样一种方式显示患者数据列表,即姓名位于我的JList左侧,识别号整齐地排列在右侧。 我已经研究并实现了在这个任务中使用JTable,因为它确实提供了我希望在这个项目中实现的整洁的列结构,但是有一些功能我不知道如何实现,或者我觉得JTable中缺少 无法基于字母数字键转换我的列表。这是最终用户快速搜索列表的主要方式,因为当填充列表时,它的长度可能超过800行。示例:键入“s”以转换到列表中以“s”开头的部分 从视觉上看,我不喜欢使用JTables选择行;对于两列结构,很明显,两列之间有一

我试图以这样一种方式显示患者数据列表,即姓名位于我的JList左侧,识别号整齐地排列在右侧。 我已经研究并实现了在这个任务中使用JTable,因为它确实提供了我希望在这个项目中实现的整洁的列结构,但是有一些功能我不知道如何实现,或者我觉得JTable中缺少

无法基于字母数字键转换我的列表。这是最终用户快速搜索列表的主要方式,因为当填充列表时,它的长度可能超过800行。示例:键入“s”以转换到列表中以“s”开头的部分

从视觉上看,我不喜欢使用JTables选择行;对于两列结构,很明显,两列之间有一个断点,这与JList不同,它是一个漂亮的平滑无缝高亮显示的选择。所有网格线都已关闭,并将单元格编辑用作参考

我已经包括了我觉得相关的代码。我希望得到一些指导,看看我所问的问题是否可以通过JList实现,或者是否有更好的方法来操作JTable?我在JTable和JList中都没有找到任何东西,我觉得这回答了我的问题

  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();
    }
    }
是的,我知道我在用水果……我很想知道我得到了什么和我希望得到的更多。它只是让最终用户更容易阅读我的感觉


让我们从模型和视图之间的差异及其职责开始

以某种方式对数据建模是模型的责任。这通常意味着提供有关模型大小的信息、包含在模型中的项目数量以及以某种方式访问数据的信息

视图有责任决定如何最好地显示这些数据

这一切和你的问题有什么关系?事实上,每件事。模型不应该尝试预先格式化数据,而是应该包含原始数据。视图有责任决定如何显示这些数据

例如,您可能有一个JList,它以{mhn}{first name}{last name}的形式显示患者数据,但另一个JList需要{lastname},{first name}{givename}

您不希望每次都创建新模型,相反,您需要一个只包含原始数据的简单模型,这些数据可以传递给这些视图中的任何一个,并允许它们决定如何显示这些信息。在你告诉我这不会发生之前…只要知道,它会发生,因为用户就是这样

所以,不是

private DefaultListModel<String> model = new DefaultListModel<String>();
private List<String> ptList;
现在,在你尖叫着跑出房间之前,这只是一个单一可能解决方案的演示。还有一些其他的方法可以达到同样的效果,虽然不那么复杂,但也会带来各自的问题

总之,JList的设计并不是为了以这种方式支持结构化数据,这就是为什么我们有JTable

另一方面,JTable非常适合显示结构化数据,通过一些简单的调整,可以使其看起来无缝

让我们从TableModel开始

这将设置表格,使其不会显示水平或垂直网格线,并将单元格之间的填充减少到0,使其显示为无缝的数据线

接下来,我们需要准备模型

public PatientSelectionWindow(List<PatientData> ptList) {
    this.ptList = ptList;
    model.add(ptList);
    createWindow();
    activePatients();
}
这三种方法基本上利用了JTable API中提供的RowFilter支持,这意味着您不需要实际接触模型或更改模型,也不需要单独管理数据,这一切都由您自己负责

然后我们得到以下结果

看看:


要了解更多详细信息,请避免使用空布局,像素完美布局在现代ui设计中是一种错觉。影响零部件单个尺寸的因素太多,您无法控制。Swing的设计初衷是与布局管理器一起工作,丢弃它们将导致无休止的问题,您将花费越来越多的时间来纠正这些问题。JTable提供的一个功能是过滤表结果。这意味着您可以提供内置的数据搜索或过滤,而无需从数据库中重新加载数据集(如果您不想验证数据集的有效性),这是我在Swing API中的第一篇介绍。根据你们的评论,我可能会试着玩。我相信这就是您所指出的方向?目前,我的结果集是捕获是传递到这个类中的列表,然后我的模型就建立在这个类的基础上,不需要重新查询数据库,对输入的新数据的担心也不是一个因素。过滤表是否优先于重建模型?我想我不确定什么是adv
优势/劣势。哇,真的很欣赏深思熟虑的回应。我只是想亲自谢谢你。我正在花一些时间来完成你提供的东西。将大胆尝试并提供更新供讨论。谢谢我希望它突出了JList和JTable之间的一些区别……您应该始终关注如何让用户更容易阅读信息,以及如何使用正确的工具来完成工作;
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());

    }
}
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;
    }

}
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);
public PatientSelectionWindow(List<PatientData> ptList) {
    this.ptList = ptList;
    model.add(ptList);
    createWindow();
    activePatients();
}
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();
}