滚动窗格是否可以在Java中具有多个选项卡?

问题描述

所以我认为我需要拆分滚动窗格列表,因为它要显示100多个项目。我当时在想我可以有一个带有选项卡的滚动窗格,而每个选项卡都具有列表的不同部分。有点像选项卡式窗格,但仅对于滚动窗格而言,它只是一个组件。问题是我不知道该怎么做或是否可能。

解决方法

这里是显示JTable中所有库的MIDI乐器的示例。在其上方提供三个组合框(JComboBox)和一个JTextField

文本字段可以搜索(不区分大小写)用户输入的任何字符串。

组合可以用于过滤:

  1. 乐器的类别。
  2. 乐器类型。
  3. 乐器名称中的公用字符串。

enter image description here

哦,我投入了JList个类别。它什么也没做,但是如果我再做完,我将以LINE_START位置开始并且只有列表。

import java.awt.*;
import java.awt.event.*;
import javax.sound.midi.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.border.EmptyBorder;

public class MidiInstrumentSearch {

    private JComponent ui = null;
    Instrument[] instruments;
    JLabel messageLabel = new JLabel("Message Label");
    JTable table;
    MidiInstrumentTableModel tm;
    TableRowSorter sorter;
    InstrumentCategory[] instrumentCategories = {
        new InstrumentCategory("All",1,10000),new InstrumentCategory("Piano",8),new InstrumentCategory("Chromatic Percussion",9,16),new InstrumentCategory("Organ",17,24),new InstrumentCategory("Guitar",25,32),new InstrumentCategory("Bass",33,40),new InstrumentCategory("Strings",41,48),new InstrumentCategory("Ensemble",49,56),new InstrumentCategory("Brass",57,64),new InstrumentCategory("Reed",65,72),new InstrumentCategory("Pipe",73,80),new InstrumentCategory("Synth Lead",81,88),new InstrumentCategory("Synth Pad",89,96),new InstrumentCategory("Synth Effects",97,104),new InstrumentCategory("Ethnic",105,112),new InstrumentCategory("Percussive",113,120),new InstrumentCategory("Sound Effects",121,128)
    };

    MidiInstrumentSearch() {
        try {
            initUI();
        } catch (MidiUnavailableException ex) {
            ex.printStackTrace();
        }
    }

    public final void initUI() throws MidiUnavailableException {
        if (ui != null) {
            return;
        }
        ui = new JPanel(new BorderLayout(4,4));
        ui.setBorder(new EmptyBorder(4,4,4));
        ui.add(messageLabel,BorderLayout.PAGE_END);
        
        ui.add(new JScrollPane(new JList(instrumentCategories)),BorderLayout.LINE_START);

        Synthesizer synthesizer = MidiSystem.getSynthesizer();
        synthesizer.open();
        instruments = synthesizer.getAvailableInstruments();
        InstrumentPOJO[] inst = new InstrumentPOJO[instruments.length];
        for (int ii = 0; ii < inst.length; ii++) {
            inst[ii] = new InstrumentPOJO(instruments[ii]);
        }
        tm = new MidiInstrumentTableModel(inst);
        sorter = new TableRowSorter<>(tm);
        table = new JTable(tm);
        table.setRowSorter(sorter);
        ui.add(new JScrollPane(table));

        JToolBar toolBar = new JToolBar();
        toolBar.setLayout(new FlowLayout());
        ui.add(toolBar,BorderLayout.PAGE_START);

        final JComboBox categoryBox = new JComboBox<>(instrumentCategories);
        ActionListener categoryListener = (ActionEvent e) -> {
            InstrumentCategory ic = (InstrumentCategory) categoryBox.getSelectedItem();
            CategoryFilter categoryFilter = new CategoryFilter(ic);
            sorter.setRowFilter(categoryFilter);
            setNumber();
        };
        categoryBox.addActionListener(categoryListener);
        toolBar.add(new JLabel("Category"));
        toolBar.add(categoryBox);

        toolBar.add(new JLabel("Type"));
        String[] types = {"","Instrument","Drumkit"};
        final JComboBox typeBox = new JComboBox<>(types);
        toolBar.add(typeBox);
        ActionListener typeSearchListener = (ActionEvent e) -> {
            String s = typeBox.getSelectedItem().toString();
            SearchFilter sf = new SearchFilter(0,s);
            sorter.setRowFilter(sf);
            setNumber();
        };
        typeBox.addActionListener(typeSearchListener);

        String[] nameCommon = {
            "","bass","bell","brass","bs","drum","flute","gt","harp","horn","org","orch","pad","piano","sax","str","syn","vox","wave"
        };
        final JComboBox nameBox = new JComboBox(nameCommon);
        ActionListener nameListener = (ActionEvent e) -> {
            SearchFilter sf = new SearchFilter(1,nameBox.getSelectedItem().toString());
            sorter.setRowFilter(sf);
            setNumber();
        };
        nameBox.addActionListener(nameListener);
        toolBar.add(new JLabel("Name"));
        toolBar.add(nameBox);

        JTextField searchField = new JTextField("Enter to Search",12);
        toolBar.add(searchField);
        ActionListener textSearchListener = (ActionEvent e) -> {
            SearchFilter sf = new SearchFilter(1,e.getActionCommand());
            sorter.setRowFilter(sf);
            setNumber();
        };
        searchField.addActionListener(textSearchListener);
    }

    private void setNumber() {
        int i = table.getRowCount();
        setNumber(i);
    }

    private void setNumber(int n) {
        messageLabel.setText(n + " presets");
    }

    public JComponent getUI() {
        return ui;
    }

    public static void main(String[] args) {
        Runnable r = () -> {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception useDefault) {
            }
            MidiInstrumentSearch o = new MidiInstrumentSearch();

            JFrame f = new JFrame(o.getClass().getSimpleName());
            f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            f.setLocationByPlatform(true);

            f.setContentPane(o.getUI());
            f.pack();
            f.setMinimumSize(f.getSize());

            f.setVisible(true);
        };
        SwingUtilities.invokeLater(r);
    }
}

class InstrumentPOJO {

    private final Instrument instrument;
    private final String category;
    private final String name;
    private final int bank;
    private final int preset;

    InstrumentPOJO(Instrument instrument) {
        this.instrument = instrument;
        String s = instrument.toString();
        category = getTextBetween(s,"",":");
        name = getTextBetween(s,":","bank");
        bank = Integer.parseInt(getTextBetween(s,"bank #"," preset"));
        String pre = "preset #";
        int index = s.indexOf(pre);
        s = s.substring(index + pre.length());
        preset = Integer.parseInt(s);
    }

    private String getTextBetween(String s,String s1,String s2) {
        int i1 = s.indexOf(s1);
        int c1 = i1 + s1.length();
        int i2 = s.indexOf(s2);
        return s.substring(c1,i2).trim();
    }

    @Override
    public String toString() {
        return getCategory() + " \t"
                + getName() + " \t"
                + getBank() + " \t"
                + getPreset() + " \t";
    }

    public Instrument getInstrument() {
        return instrument;
    }

    public String getCategory() {
        return category;
    }

    public String getName() {
        return name;
    }

    public int getBank() {
        return bank;
    }

    public int getPreset() {
        return preset;
    }
}

class MidiInstrumentTableModel extends AbstractTableModel {

    final static String[] colNames = {"Category","Name","Bank","Preset"};
    InstrumentPOJO[] orchestra;

    MidiInstrumentTableModel(InstrumentPOJO[] orchestra) {
        this.orchestra = orchestra;
    }

    @Override
    public int getRowCount() {
        return orchestra.length;
    }

    @Override
    public int getColumnCount() {
        return 4;
    }

    @Override
    public Object getValueAt(int rowIndex,int columnIndex) {
        final InstrumentPOJO ip = orchestra[rowIndex];
        switch (columnIndex) {
            case 0:
                return ip.getCategory();
            case 1:
                return ip.getName();
            case 2:
                return ip.getBank();
            case 3:
                return ip.getPreset();
            default:
                return null;
        }
    }

    @Override
    public String getColumnName(int columnIndex) {
        return colNames[columnIndex];
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        switch (columnIndex) {
            case 0:
                return String.class;
            case 1:
                return String.class;
            case 2:
                return Integer.class;
            case 3:
                return Integer.class;
            default:
                return Integer.class;
        }
    }

    @Override
    public boolean isCellEditable(int rowIndex,int columnIndex) {
        return false;
    }
}

class SearchFilter extends RowFilter {

    int col;
    String target;

    SearchFilter(int col,String target) {
        this.col = col;
        this.target = target;
    }

    @Override
    public boolean include(Entry entry) {
        String s = entry.getValue(col).toString();
        return s.toLowerCase().contains(target.toLowerCase());
    }
}

class CategoryFilter extends RowFilter {

    InstrumentCategory cat;

    CategoryFilter(InstrumentCategory cat) {
        this.cat = cat;
    }

    @Override
    public boolean include(Entry entry) {
        int i = (Integer) entry.getValue(3) + 1;
        return (i >= cat.getFirst() && i <= cat.getLast());
    }
}

class InstrumentCategory {

    private final String name;
    private final int first;
    private final int last;

    public InstrumentCategory(String name,int first,int last) {
        this.name = name;
        this.first = first;
        this.last = last;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @return the first
     */
    public int getFirst() {
        return first;
    }

    /**
     * @return the last
     */
    public int getLast() {
        return last;
    }

    @Override
    public String toString() {
        return name;
    }
}