这是一个在JTable 中显示所有库的 MIDI 乐器的示例。它上面提供了三个组合框 (JComboBox) 和一个 JTextField。
文本字段可以搜索(不区分大小写)用户输入的任何字符串。
组合可用于过滤:
- 乐器类别。
- 仪器类型。
- 乐器名称中的常用字符串。
哦,我输入了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", 1, 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, 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;
}
}