Question

Background: I am creating a music app that gets data from my piano keyboard through CoreMIDI. When a note is played, it relays this to the GUI by showing the onscreen keyboard key as being pressed. The onscreen keyboard is represented by UIButtons for now. Each "key" (UIButton) has an identifier that corresponds to the MIDI value from my physical piano keyboard. For instance, middle C's UIButton will have a value of 60, since that is the value returned in MIDI data. C# is 61, D is 62, etc.

Question: How can I access all of the UIButtons from my window programatically? I need to access them by their "identifier" field, unless there's a more elegant way to do so. I haven't been programming for OSX for very long (actually only a few days) and I've literally watched about 100 videos on YouTube so I'm still learning. I have read a few posts that have said each UIButton is a subview of the main view. I couldn't figure out how to access the buttons via code though. Whatever suggestions you have will be very helpful! Thanks in advance.

Was it helpful?

Solution

Assuming you have all the buttons declared as outlets in your controller and connected them with your view.

Beware: Lots of untested pseudo-code will follow ;-)

@property IBOutlet UIButton *firstPianoKeyButton;
@property IBOutlet UIButton *secondPianoKeyButton;
@property IBOutlet UIButton *thirdPianoKeyButton;
... and so on ...

What you can do now is, to put the buttons one after the other into an array.

Let's say you have a controller with 12 keys, starting with what would usually be the middle C.

NSArray *pianoKeys = [NSArray arrayWithObjects:firstButton, secondButton, thirdButton, ..., nil];

Not nice, and there are more elegant and efficient ways to do this, but that should give the picture.

More on arrays in general: NSArray.

Check out this video here for a "better" way: Create Multiple UIButtons Programmatically. It's for iOS though, but again, it should give the picture :-D

Although check out this one: How do I create a basic UIButton programmatically?

Okay. Now, your controller will receive for example the NoteOn-Event of the D#, that corresponds to the MIDI note number of 63. Assuming this is an integer, we can use that one to access the corresponding element in our pianoKeys-array.

So we need an offset to get the right index, the offset will be 60. Why? Our array starts with index 0, but our note numbers of the 12 key piano start with 60.

On a full 88-key piano, the first MIDI note number starts with 21, so that would be the index in that case.

Now, that we can calculate the array index with the MIDI note number of the pressed key and can therefore display the corresponding button in the view as pressed.

[pianoKeys objectAtIndex:(63-60)];

Hope this is helpful.

OTHER TIPS

This is the answer for my second problem where the button could only be clicked in the middle:

Here was the code (in awakeFromNib):

WhitePianoKey *button = [[WhitePianoKey alloc] initWithFrame:NSMakeRect(20, 20, 40, 300)]; 
[[window contentView] addSubview: button];
[button setButtonType:NSMomentaryPushInButton]; //I removed this line

changed to

WhitePianoKey *button = [[WhitePianoKey alloc] initWithFrame:NSMakeRect(20, 20, 40, 300)];
[[window contentView] addSubview: button];

It seems that setting the button type overrides my subclass and sets the size of the button back to the default size of whatever the style of the button is that I changed it to.

Thanks a lot again man!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top