📄 pianao.java
字号:
//RIGHTS RESERVE WANG ZHEN GANG 2003 6 16
//在226行实现多线程
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;//实现了Swing GUI组件,例如: JButton(JRadioButton),JSlider等
import javax.swing.border.*;
import javax.swing.table.*;
import javax.swing.event.*;
import javax.sound.midi.*;
import java.util.Vector;
import java.net.*; //引入InetAddress类所在的包,从而实现了网络编程
import java.io.File;//实现了文件I/O
import java.io.IOException;//
public class PIANAO extends JPanel implements KeyListener {
final int PROGRAM = 192;
final int NOTEON = 144;
final int NOTEOFF = 128;
final int SUSTAIN = 64;
final int REVERB = 91;
final int ON = 0, OFF = 1;
final Color jfcBlue = new Color(204, 204, 255);
final Color pink = new Color(255, 175, 175);
String keycodes[]={"F2","F4","F7","F9","F11","1","3","6","8","0","Backspace","Home","W","R","Y","O","[","Delete","Page Down","S","G","J",";","Enter","Z","V","N",".","Ctrl","Left","F1","F3","F5","F6","F8","Right","F12","Up","2","4","5","7","9","Minus","=","Insert","Page Up","Q","E","T","U","I", "P","]", "\\", "End", "A","D","F","H","K","L","Quote","Shift","X","C","B","M",",","/","Space","Down"};
Sequencer sequencer;
Sequence sequence;
Synthesizer synthesizer;
Instrument instruments[];
ChannelData channels[];
ChannelData cc;
JCheckBox mouseOverCB = new JCheckBox("鼠标移动发声", true);
JRadioButton multiCBmouse = new JRadioButton("鼠标", true);
JRadioButton multiCBkey = new JRadioButton("键盘弹奏", true);
JRadioButton multiCBn = new JRadioButton("不组播", true);
JRadioButton multiCB = new JRadioButton("我要组播", false);
JRadioButton multiCB1 = new JRadioButton("接受组播", false);
JSlider veloS, presS, bendS, revbS;
JCheckBox soloCB, monoCB, muteCB, sustCB;
Vector keys = new Vector();
Vector whiteKeys = new Vector();
JTable table;
Piano piano;
boolean record;
Track track;
long startTime;
Controls controls;
Key prevKey;
InstrumentsTable Table;
MulticastSocket ms;
InetAddress ia;
int port=4000;
byte []data=new byte[3];
int program1;
public PIANAO() {
setLayout(new BorderLayout());
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p,BoxLayout.Y_AXIS ));
EmptyBorder eb = new EmptyBorder(10,20,30,40);
BevelBorder bb = new BevelBorder(BevelBorder.RAISED,new Color(0,0,255),new Color(0,0,255));
CompoundBorder cb = new CompoundBorder(eb,bb);
p.setBorder(new CompoundBorder(cb,eb));
JPanel pp = new JPanel(new BorderLayout());
pp.setBorder(new EmptyBorder(10,20,30,40));
pp.add(piano = new Piano(this));
p.add(pp);
p.add(controls = new Controls(this));
p.add(Table= new InstrumentsTable(this));
initmulticast();
multiCBkey.addKeyListener(this);
add(p);
addKeyListener(this);
}
public void keyPressed(KeyEvent e) //实现键盘按下
{
int code=e.getKeyCode();
String codestr=e.getKeyText(code);
prevKey=getKeyByKeycode( codestr);
if (prevKey != null) {
int keyi=prevKey.on();
repaint();
if(multiCB.isSelected())
send(keyi,ON,program1);
}
}
public void keyReleased(KeyEvent e) //实现键盘松开
{
int code=e.getKeyCode();
String codestr=e.getKeyText(code);
prevKey=getKeyByKeycode( codestr);
if ( prevKey!= null) {
int keyi=prevKey.off();
repaint();
if(multiCB.isSelected())
send(keyi,OFF,program1);
}
}
public void keyTyped(KeyEvent e){}
public Key getKeyByKeycode(String codestr) {
for (int i = 0; i < keycodes.length; i++) {
if (keycodes[i].equals(codestr)==true) {
return (Key) keys.get(i);
}
}
return null;
}
public boolean isFocusTraversable ()
{
return true;
}
public void open() {
try {
if (synthesizer == null) {
if ((synthesizer = MidiSystem.getSynthesizer()) == null) {
System.out.println("getSynthesizer() failed!");
return;
}
}
synthesizer.open();
sequencer = MidiSystem.getSequencer();
sequence = new Sequence(Sequence.PPQ, 10);
} catch (Exception ex) { ex.printStackTrace(); return; }
Soundbank sb = synthesizer.getDefaultSoundbank();
if ( sb!= null) {
instruments = synthesizer.getDefaultSoundbank().getInstruments();
synthesizer.loadInstrument(instruments[0]);
}
MidiChannel midiChannels[] = synthesizer.getChannels();
channels = new ChannelData[midiChannels.length];
for (int i = 0; i < channels.length; i++) {
channels[i] = new ChannelData(midiChannels[i], i);
}
cc = channels[0];
ListSelectionModel lsm = table.getSelectionModel();
lsm.setSelectionInterval(0,0);
lsm = table.getColumnModel().getSelectionModel();
lsm.setSelectionInterval(0,0);
}
public void close() {
if (synthesizer != null) {
synthesizer.close();
}
if (sequencer != null) {
sequencer.close();
}
sequencer = null;
synthesizer = null;
instruments = null;
channels = null;
}
private void initmulticast(){
try{
ms=new MulticastSocket(port);
ia=InetAddress.getByName("224.0.1.20");
ms.joinGroup(ia);
Receiver rthread=new Receiver();
Thread t=new Thread(rthread);
t.start();
}catch(IOException e){System.err.println(e);}
}
private void programChange(int program) {
if (instruments != null) {
synthesizer.loadInstrument(instruments[program]);
}
cc.channel.programChange(program);
program1=program;
}
public void createShortEvent(int type, int num) {
ShortMessage message = new ShortMessage();
try {
long millis = System.currentTimeMillis() - startTime;
long tick = millis * sequence.getResolution() / 500;
message.setMessage(type+cc.num, num, cc.velocity);
MidiEvent event = new MidiEvent(message, tick);
track.add(event);
} catch (Exception ex) { ex.printStackTrace(); }
}
private void send(int keyi,int state,int program){
data[1] =(byte)keyi;
data[0]=(byte)state;
data[2]=(byte)program;
try{
DatagramPacket dp=new DatagramPacket(data,data.length,ia,port);
ms.send(dp);
}catch(IOException ee){System.err.println(ee);}
}
class Receiver implements Runnable //在用户自己的类中实现Runnable接口,从而实现多线程的应用
{
private byte data[]=new byte[3];
public Receiver(){
}
public void run(){
while(true){
if( multiCB1.isSelected()) {
try{
DatagramPacket dp=new DatagramPacket(data,data.length);
ms.receive(dp);
}
catch(IOException e){System.err.println(e);}
programChange((int)data[2]);
if(data[0]==ON)
((Key) keys.get((int)data[1])).on();
else
((Key) keys.get((int)data[1])).off();
}
}
}
}
class Key extends Rectangle {
int noteState = OFF;
int kNum;
public Key(int x, int y, int width, int height, int num) {
super(x, y, width, height);
kNum = num;
}
public boolean isNoteOn() {
return noteState == ON;
}
public int on() {
setNoteState(ON);
cc.channel.noteOn(kNum, cc.velocity);
return kNum-24;
}
public int off() {
setNoteState(OFF);
cc.channel.noteOff(kNum, cc.velocity);
return kNum-24;
}
public void setNoteState(int state) {
noteState = state;
}
}
class Piano extends JPanel implements MouseListener{
Vector blackKeys = new Vector();
Key prevKey;
final int kw = 19, kh = 200;
PIANAO env;
public Piano(PIANAO env) {
setLayout(new BorderLayout());
setPreferredSize(new Dimension(42*kw, kh+1));
int transpose = 24;
int whiteIDs[] = { 0, 2, 4, 5, 7, 9, 11 };
for (int i = 0, x = 0; i < 6; i++) {
for (int j = 0; j < 7; j++, x += kw) {
int keyNum = i * 12 + whiteIDs[j] + transpose;
whiteKeys.add(new Key(x, 0, kw, kh, keyNum));
}
}
for (int i = 0, x = 0; i < 6; i++, x += kw) {
int keyNum = i * 12 + transpose;
blackKeys.add(new Key((x += kw)-4, 0, kw/2, kh/2, keyNum+1));
blackKeys.add(new Key((x += kw)-4, 0, kw/2, kh/2, keyNum+3));
x += kw;
blackKeys.add(new Key((x += kw)-4, 0, kw/2, kh/2, keyNum+6));
blackKeys.add(new Key((x += kw)-4, 0, kw/2, kh/2, keyNum+8));
blackKeys.add(new Key((x += kw)-4, 0, kw/2, kh/2, keyNum+10));
}
keys.addAll(blackKeys);
keys.addAll(whiteKeys);
setCursor(new Cursor(Cursor.HAND_CURSOR));
setBackground(new Color(160,100,160));
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
if (mouseOverCB.isSelected()) {
Key key = getKey(e.getPoint());
if (prevKey != null && prevKey != key) {
int keyi=prevKey.off();
if( multiCB.isSelected())
send(keyi,OFF,program1);
}
if (key != null && prevKey != key) {
int keyi= key.on();
if( multiCB.isSelected())
send(keyi,ON,program1);
}
prevKey = key;
repaint();
}
}
});
this.env=env;
addKeyListener(env);
addMouseListener(this);
}
public void mousePressed(MouseEvent e) {
prevKey = getKey(e.getPoint());
if (prevKey != null) {
int keyi=prevKey.on();
repaint();
if(multiCB.isSelected())
send(keyi,ON,program1);
}
}
public void mouseReleased(MouseEvent e)
{
if (prevKey != null) {
int keyi=prevKey.off();
repaint();
if(multiCB.isSelected())
send(keyi,OFF,program1);
}
}
public void mouseExited(MouseEvent e)
{
if (prevKey != null) {
int keyi=prevKey.off();
repaint();
if(multiCB.isSelected())
send(keyi,OFF,program1);
prevKey = null;
}
}
public void mouseClicked(MouseEvent e) { }
public void mouseEntered(MouseEvent e) { }
public Key getKey(Point point) {
for (int i = 0; i < keys.size(); i++) {
if (((Key) keys.get(i)).contains(point)) {
return (Key) keys.get(i);
}
}
return null;
}
public void paint(Graphics g) //绘制钢琴键
{
Graphics2D g2 = (Graphics2D) g;
Dimension d = getSize();
g2.setBackground(getBackground());
g2.clearRect(0, 0, d.width, d.height);
g2.setColor(Color.white);
g2.fillRect(0, 0, 42*kw, kh);
for (int i = 0; i < whiteKeys.size(); i++) {
Key key = (Key) whiteKeys.get(i);
if (key.isNoteOn()) {
g2.setColor(record ? pink : jfcBlue);
g2.fill(key);
}
g2.setColor(Color.black);
g2.draw(key);
}
for (int i = 0; i < blackKeys.size(); i++) {
Key key = (Key) blackKeys.get(i);
if (key.isNoteOn()) {
g2.setColor(record ? pink : jfcBlue);
g2.fill(key);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -