📄 midikeyboard.java
字号:
int key;
for (key = 0; key < numKeys - 1; key++) {
// draw a normal key
if ((keyState[key] & KEY_ACCIDENTAL) == 0) {
// signal a non-functioning keyboard by making the keys yellow
// instead of white
if (numDevices <= 0) {
g.setColor((keyState[key] & KEY_DOWN) != 0 ? Color.orange : Color.yellow);
} else {
g.setColor((keyState[key] & KEY_DOWN) != 0 ? Color.pink : Color.white);
}
// normal keys have two parts: the skinny part between accidentals and the wide
// part below the accidentals
// calculate and draw the skinny part
dxSkinny = dxNormal - (xp - xn);
if ((keyState[key + 1] & KEY_ACCIDENTAL) != 0) { // next key is an accidental
dxSkinny -= dxAccidental / 2;
}
g.fillRect(xp+1, 1, dxSkinny-1, dyAccidental-1);
// draw the fat part
g.fillRect(xn+1, dyAccidental, dxNormal-1, dyFat);
// draw the border between this key and the next
xn += dxNormal;
g.setColor(Color.black);
g.drawLine(xn, 0, xn, dyNormal);
// remember the trailing edge of this key
xp = xn;
// x coordinate for accidentals goes up with normal keys
xa += dxNormal;
// draw an accidental key
} else {
g.setColor((keyState[key] & KEY_DOWN) != 0 ? Color.red : Color.black);
g.fillRect(xa, 1, dxAccidental, dyAccidental-1);
xp = xa + dxAccidental - 1; // for use by next key
}
}
// do the last key, which is always normal but doesn't need a border
// signal a non-functioning keyboard by making the keys yellow
// instead of white
if (numDevices <= 0) {
g.setColor((keyState[key] & KEY_DOWN) != 0 ? Color.orange : Color.yellow);
} else {
g.setColor((keyState[key] & KEY_DOWN) != 0 ? Color.pink : Color.white);
}
dxSkinny = dxNormal - (xp - xn);
g.fillRect(xp+1, 1, dxSkinny-1, dyAccidental-1); // skinny part
g.fillRect(xn+1, dyAccidental, dxNormal-1, dyFat); // fat part
}
/** handle mouse up event */
public boolean mouseUp(Event evt, int x, int y) {
// release the last key hit
if (keyDown >= 0) {
hitKey(keyDown, false);
keyDown = -1;
}
return true;
}
/** handle mouse drag event */
public boolean mouseDrag(Event evt, int x, int y) {
int key = getKey(x, y);
if (key != keyDown) {
if (keyDown >= 0) {
hitKey(keyDown, false);
}
keyDown = key;
if (keyDown >= 0){
hitKey(keyDown, true);
}
}
return true;
}
/** handle mouse down event */
public boolean mouseDown(Event evt, int x, int y) {
keyDown = getKey(x, y);
if (keyDown >= 0) {
hitKey(keyDown, true);
}
return true;
}
/** determine which key is at a location, return index or -1 if out of bounds */
int getKey(int x, int y) {
// which normal key is it on?
int normal = x / dxNormal;
// convert from normal key index to absolute index
int key;
for (key = 0; key < numKeys; key++) {
if (((keyState[key] & KEY_ACCIDENTAL) == 0) && ((keyState[key] & KEY_INDEX_BY_TYPE) == normal)) {
break;
}
}
// didn't find it? we must be past the edge
if (key == numKeys) {
return -1;
}
// now see if the mouse is actually on an accidental
if (y < dyAccidental) { // test the y cordinate to see if it's possible
// hit test x for the previous key
if ((x - (normal * dxNormal)) < (dxAccidental / 2)) {
// is there an accidental there?
if ((key > 0) && ((keyState[key - 1] & KEY_ACCIDENTAL) != 0)) {
// we hit it
key--;
}
// hit test x for the following key
} else if ((((normal + 1) * dxNormal) - x) < (dxAccidental / 2)) {
// is there an accidental there?
if ((key < numKeys - 1) && ((keyState[key + 1] & KEY_ACCIDENTAL) != 0)) {
// we hit it
key++;
}
}
}
return key;
}
/** handle a key hit */
void hitKey(int key, boolean down) {
// play the key
int message;
if (down) {
// build a note on message
message = MidiDevice.MidiNoteOn | channel | ((key + startKey) << 8) | (velocity << 16);
keyState[key] |= KEY_DOWN;
} else {
// build a note off message
message = MidiDevice.MidiNoteOff | channel | ((key + startKey) << 8);
keyState[key] &= ~KEY_DOWN;
}
if (midiOut != null) {
try {
midiOut.Out(message);
} catch (MidiException e) {
System.err.println("MIDI error on Note " + (down ? "On" : "Off"));
}
}
// repaint the key
repaintKey(key);
}
/** request repaint for the bounding rectangle of a key */
void repaintKey(int key) {
int x, dx, dy;
// accidentals require a little calculation
if ((keyState[key] & KEY_ACCIDENTAL) != 0) {
// it's an accidental; begin by calculating the index-by-type of the next key, which is
// certain to be normal
int normal = keyState[key + 1] & KEY_INDEX_BY_TYPE; // don't worry, this can't be the last key
// calculate the x coordinate based on the normal key's x coordinate
x = (normal * dxNormal) - (dxAccidental / 2);
// the rest is straightforward
dx = dxAccidental;
dy = dyAccidental;
// normal keys are easy
} else {
x = (keyState[key] & KEY_INDEX_BY_TYPE) * dxNormal;
dx = dxNormal;
dy = dyNormal;
}
repaint(x, 0, dx, dy);
}
/** handle a resize event */
public synchronized void reshape(int x, int y, int width, int height) {
if (numNormals == 0) {
// init() hasn't been called yet; we can't do our calculations
return;
}
super.reshape(x, y, width, height);
// recalculate the dimensions of the keyboard
calcDimensions(width, height);
}
/** calculate various dimensions that depend on the applet width and height */
protected void calcDimensions(int width, int height)
{
// The division is safe because the logic in init() ensures that
// not every key is an accidental.
//
// Subtract 1 from overall width because the normal key width does
// not include the right border
dxNormal = (width - 1) / numNormals;
if (dxNormal < 4) { // reasonable minimum
dxNormal = 4;
}
dyNormal = height;
// Accidentals are two thirds the width of normal keys
dxAccidental = (2 * dxNormal) / 3;
// Make sure the width is odd so it can straddle the border equally
// between normal keys
dxAccidental |= 1;
if (dxAccidental < 3) { // reasonable minimum
dxAccidental = 3;
}
// ...and 60% as tall
dyAccidental = (3 * height) / 5;
// calculate overall keyboard width from normal keys (plus one
// for right border)
dxKeyboard = (numNormals * dxNormal) + 1;
dyKeyboard = height;
}
/** return true if key is an accidental, else false */
boolean IsAccidental(int key) {
int test = key % 12;
if (test == 1 || test == 3 || test == 6 || test == 8 || test == 10) {
return true;
} else {
return false;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -