cocoa - 自定义 NSButton 无法通过 CoreMIDI 回调函数工作

标签 cocoa nsbutton coremidi

我正在创建一个钢琴应用程序(适用于 OSX),它有一个屏幕键盘,可以显示用户在合成器键盘上弹奏的内容。一切都使用 CoreMIDI 框架连接。我通过在名为 PianoKey 的类中子类化 NSButton 来创建一些自定义按钮。该类如下所示:

#import "PianoKey.h"

@implementation PianoKey

//updates the core animation layer whenever it needs to be changed
- (BOOL)wantsUpdateLayer {
    return YES;
}

- (void)updateLayer {
    //tells you whether or not the button is pressed
    if ([self.cell isHighlighted]) {
        NSLog(@"BUTTON PRESSED");
        self.layer.contents = [NSImage imageNamed:@"buttonpressed.png"];
    }
    else {
        NSLog(@"BUTTON NOT PRESSED");
        self.layer.contents = [NSImage imageNamed:@"button.png"];
    }
}

@end

“钢琴键”是以编程方式创建的。未按下时,钢琴键为蓝色,按下时为粉红色(只是临时颜色)。如果我单击屏幕上的按钮,颜色开关工作正常,但当我尝试通过 MIDI 键盘演奏时,它们不会改变。

一些注意事项: 1)MIDI键盘工作 2) 我成功从键盘获取MIDI数据。

a) 此 MIDI 数据被传递到名为 midiInputCallback 的回调函数,如下所示: [来自 AppController.m 类]

void midiInputCallback(const MIDIPacketList *list, void *procRef, void *srcRef) {
    PianoKey *button = (__bridge PianoKey*)procRef;

    UInt16 nBytes;
    const MIDIPacket *packet = &list->packet[0]; //gets first packet in list

    for(unsigned int i = 0; i < list->numPackets; i++) {
        nBytes = packet->length; //number of bytes in a packet

        handleMIDIStatus(packet, button);
        packet = MIDIPacketNext(packet);
    }
}

对象按钮是对我以编程方式创建的按钮的引用,如AppController.h中定义的:

@property PianoKey *button; //yes, this is synthesized in AppController.m

b) 回调函数调用一堆处理 MIDI 数据的函数。如果检测到正在播放音符,则我将自定义按钮设置为突出显示...这可以在下面的函数中看到:

void updateKeyboardButtonAfterKeyPressed(PianoKey *button, int key, bool keyOn) {
    if(keyOn)
        [button highlight:YES];
    else
        [button highlight:NO];

    [button updateLayer];

}

[按钮 updateLayer] 从 PianoKey 调用我的 updateLayer() 方法,但它不会更改图像。我有什么遗漏的吗?尽管我的按钮说它“突出显示”,但 View 或窗口似乎没有更新。请帮忙!预先感谢:)

最佳答案

只是一个猜测(但是是一个不错的猜测...;-)回调函数是否在主线程上被调用?如果不是,这可能就是问题所在 - 至少这就是它在 iOS 中的工作方式:UI(屏幕绘图)仅在主线程中更新。

在回调中放置一条日志语句或断点以查看它是否被调用。如果是,那么问题是由于该线程问题造成的。

<小时/>

更新:

所以告诉按钮 self 更新 - 但在主线程上(我认为我的语法是正确的 - 至少对于 iOS - OSX 可能会有所不同)

[button performSelectorOnMainThread:@selector(updateLayer) 
                         withObject:nil 
                      waitUntilDone:FALSE];

关于cocoa - 自定义 NSButton 无法通过 CoreMIDI 回调函数工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20986250/

相关文章:

ios - 简单的 MIDI 路由没有音频输出

objective-c - WebViews 不释放内存?

macos - 更改 NSTableView 的边框颜色

macos - NSButton渐变样式

objective-c - 如何创建具有多个显示三角形的调整大小窗口?

cocoa - 让 NSButton 打开字体面板

objective-c - 使用 Swift CFunctionPointer 将回调传递给 CoreMIDI API

cocoa - 最后一个窗口关闭后退出应用程序

iphone - KVC : How do I save UIKit structs in plist?

ios - 如何从 MIDISourceCreate() 中保留虚拟 MIDI 源的唯一性?