Запуск NSColorPanel в Objective C

Я пишу библиотеку для запуска диалоговых окон операционной системы, таких как открытие/сохранение файлов, диалоги сообщений и подсказки от приложений C. Я не могу понять, как запустить выбор цвета на Mac для выбора значения цвета RGB(A).

Это то, что я получил в реализации моей библиотеки для Mac в Objective C. Я предполагаю, что мне нужно запустить NSColorPanel, но я не могу найти пример того, как это сделать в Интернете.

int launchColorPicker(float* r, float* g, float* b, float* a) {
    @autoreleasepool {
        NSColorPanel* panel = [NSColorPanel sharedColorPanel];

        // ???

        *r = ...;
        *g = ...;
        *b = ...;
        *a = ...;
        return succeeded;
    } // @autoreleasepool
}

person Vortico    schedule 13.12.2020    source источник
comment
NSColorPanel *panel = [NSColorPanel sharedColorPanel];[порядок панелиFront: self];   -  person El Tomato    schedule 13.12.2020
comment
@ElTomato Выглядит интересно, но что такое colorManager? Я не вижу типа с таким именем в документации Apple.   -  person Vortico    schedule 13.12.2020
comment
Общедоступного API для использования модальной цветной панели с кнопками «Отмена» и «ОК» не существует.   -  person Willeke    schedule 13.12.2020
comment
@Willeke К сожалению. У Windows есть ChooseColor(), у GTK есть gtk_color_chooser_dialog_new(), а у Qt есть QColorDialog::getColor(). Но у Mac нет простой цветовой подсказки! Мне придется заставить пользователя ввести шестнадцатеричную строку, например #ffffff, в текстовое поле.   -  person Vortico    schedule 13.12.2020
comment
Возможно, я мог бы запустить osascript -e "choose color" и проанализировать стандартный вывод в функции C. Хаково, но работает.   -  person Vortico    schedule 13.12.2020


Ответы (2)


Ниже приведен пример программного NSColorPanel в objc. Его можно запустить в Xcode, заменив main.m следующим кодом и удалив существующий AppDelegate, чтобы избежать дублирования символов.

#import <Cocoa/Cocoa.h>

@interface CustomView : NSView {
 NSTextField *redFld;
 NSTextField *greenFld;
 NSTextField *blueFld;
 NSColor *myColor;
}
 @property (strong) NSTextField *redFld;
 @property (strong) NSTextField *greenFld;
 @property (strong) NSTextField *blueFld;
@end

 @implementation CustomView
 @synthesize redFld;
 @synthesize greenFld;
 @synthesize blueFld;
 
 - (id)initWithFrame:(NSRect)frameRect {
 if ((self = [super initWithFrame:frameRect]) != nil) {
  myColor = [NSColor whiteColor];
 }
 return self;
 }
 
 - (void)changeColor:(id)sender {
 myColor = [sender color];
 [redFld setStringValue:[NSString stringWithFormat:@"r = %f",[[sender color] redComponent]]];
 [greenFld setStringValue:[NSString stringWithFormat:@"g = %f",[[sender color] greenComponent]]];
 [blueFld setStringValue:[NSString stringWithFormat:@"b = %f",[[sender color] blueComponent]]];
 [self setNeedsDisplay:YES];
}
 
 -(void)drawRect:(NSRect)rect {
 // **** Background **** //
 [myColor set];
 [NSBezierPath fillRect:rect];
}

 // ----- Use this if you want 0,0 (origin) to be top, left ---- //
 // ----- Otherwise origin will be at bottom, left (Unflipped) ----- //
-(BOOL)isFlipped {
 return YES;
}
@end

@interface AppDelegate : NSObject <NSApplicationDelegate> {
 NSWindow *window;
 NSColorPanel *colorPanel;
 NSTextField *redFld;
 NSTextField *greenFld;
 NSTextField *blueFld;
 CustomView *customView;
}
 @end

 @implementation AppDelegate
  
-(void) buildMenu{
 NSMenu *menubar = [NSMenu new];
 [NSApp setMainMenu:menubar];
 NSMenuItem *menuBarItem = [NSMenuItem new];
 [menubar addItem:menuBarItem];
 NSMenu *appMenu = [NSMenu new];
 [menuBarItem setSubmenu:appMenu];
 [appMenu addItemWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"q"];
}
 
-(void) buildWindow {
 #define _wndW  500
 #define _wndH  550
 
 window = [[NSWindow alloc] initWithContentRect: NSMakeRect( 0, 0, _wndW, _wndH ) styleMask: NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskClosable backing: NSBackingStoreBuffered defer: NO];
 [window center];
 [window setTitle: @"Test window"];
 [window makeKeyAndOrderFront: nil];
 
// **** Create an instance of CustomView **** //
 customView = [[CustomView alloc]initWithFrame:NSMakeRect( 20, 60, _wndW - 40, _wndH - 120 )];
 [[window contentView] addSubview:customView];

// **** NSColorPanel **** //
 colorPanel = [NSColorPanel sharedColorPanel];
 [NSColorPanel setPickerMode:NSColorPanelModeWheel];
 [NSApp orderFrontColorPanel:colorPanel];
 [colorPanel setTarget:customView];
 [colorPanel setAction:@selector(changeColor:)];
 
// **** Display Fields **** //
 redFld = [[NSTextField alloc] initWithFrame:NSMakeRect( 20, _wndH - 40, 110, 22 )];
 [[window contentView] addSubview:redFld];
 [redFld setStringValue:@"red"];
 [customView setRedFld:redFld];
 
 greenFld = [[NSTextField alloc] initWithFrame:NSMakeRect( 140, _wndH - 40, 110, 22 )];
 [[window contentView] addSubview:greenFld];
 [greenFld setStringValue:@"green"];
 [customView setGreenFld:greenFld];
 
 blueFld = [[NSTextField alloc] initWithFrame:NSMakeRect( 260, _wndH - 40, 110, 22 )];
 [[window contentView] addSubview:blueFld];
 [blueFld setStringValue:@"blue"];
 [customView setBlueFld:blueFld];
 
 // **** Quit btn **** //
 NSButton *quitBtn = [[NSButton alloc]initWithFrame:NSMakeRect( _wndW - 50, 10, 40, 40 )];
 [quitBtn setBezelStyle:NSBezelStyleCircular ];
 [quitBtn setTitle: @"Q" ];
 [quitBtn setAction:@selector(terminate:)];
 [[window contentView] addSubview: quitBtn];
 }
 
 -(void) applicationWillFinishLaunching: (NSNotification *)notification
 {
 [self buildMenu];
 [self buildWindow];
 }
 
 @end

int main() {
 NSApplication *application = [NSApplication sharedApplication];
 AppDelegate *appDelegate = [[AppDelegate alloc] init];
 [application setDelegate:appDelegate];
 [application run];
return 0;
}


person apodidae    schedule 13.12.2020
comment
Спасибо! Это может быть мой розовый камень, но я пытаюсь переварить это, и это происходит медленно. Это включает в себя создание целого приложения с отдельным окном, но что, если я просто хочу запустить цветовую панель внутри функции C и заблокировать, пока пользователь не выберет цвет? NSAlert позволяет вам сделать это с [alert runModal];, поэтому я пытаюсь изменить ваш код, чтобы открыть только NSColorPanel, а затем вернуть функцию, когда она закрыта. - person Vortico; 13.12.2020

Просто для вашего сведения есть несколько типов цветных панелей, показанных одним нажатием кнопки в следующей демонстрации. Вам все равно придется выяснить, как получить значения из выбора пользователя.

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate> {
 NSWindow *window;
}
@end

@implementation AppDelegate
 
-(void) myBtnAction:(id)sender {
 [NSColorPanel setPickerMode:[sender tag]];
 [NSApp orderFrontColorPanel:nil];
}
 
-(void) buildMenu {
 NSMenu *menubar = [NSMenu new];
 [NSApp setMainMenu:menubar];
 NSMenuItem *menuBarItem = [NSMenuItem new];
 [menubar addItem:menuBarItem];
 NSMenu *appMenu = [NSMenu new];
 [menuBarItem setSubmenu:appMenu];
 [appMenu addItemWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"q"];
}
 
-(void) buildWindow {
 #define _wndW  380
 #define _wndH  420
 
 window = [[NSWindow alloc] initWithContentRect: NSMakeRect( 0, 0, _wndW, _wndH )styleMask: NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskClosable backing: NSBackingStoreBuffered defer: NO];
 [window center];
 [window setTitle: @"NSColorPanel Types"];
 [window makeKeyAndOrderFront: nil];
 
 // ***** NSBox ***** //
 #define _boxW 265
 #define _boxH 340
 NSBox *boxBtn = [[NSBox alloc]initWithFrame:NSMakeRect( 60, 60, _boxW, _boxH )];
 [boxBtn setTitle:@""];
 [boxBtn setBorderType:NSBezelBorder];
 [[window contentView] addSubview: boxBtn];
 
 // **** Radio Group **** //
 NSArray *colorPanelTypes = [NSArray arrayWithObjects:
 @"NSNoModeColorPanel",
 @"NSGrayModeColorPanel",
 @"NSRGBModeColorPanel",
 @"NSCMYKModeColorPanel",
 @"NSHSBModeColorPanel",
 @"NSCustomPaletteModeColorPanel",
 @"NSColorListModeColorPanel",
 @"NSWheelModeColorPanel",
 @"NSCrayonModeColorPanel",
 nil];
 
 NSButton *btn[[colorPanelTypes count]];
 int count;
 count = 0;
 #define _btnW  260
 #define _btnH  24
 #define _spacing  10
 #define _left  10
 #define _top  _boxH - 55
 for (unsigned int row = 0; row < [colorPanelTypes count]; row++ ) {
  btn[count] = [[NSButton alloc]initWithFrame:NSMakeRect( _left, _top - row*(_btnH + _spacing), _btnW, _btnH )];
  [btn[count] setButtonType:NSButtonTypeRadio];
 // **** start at minus one **** //
  [btn[count] setTag: count-1];
  [btn[count] setTitle: [colorPanelTypes objectAtIndex:count]];
  [btn[count] setTarget:self];
  [btn[count] setAction:@selector(myBtnAction:)];
  if (count == 0) {[btn[count] setState:NSControlStateValueOn];}
  [boxBtn addSubview: btn[count]];
  count++;
 }
 
 // **** Quit btn **** //
 NSButton *quitBtn = [[NSButton alloc]initWithFrame:NSMakeRect( _wndW - 50, 10, 40, 40 )];
 [quitBtn setBezelStyle:NSBezelStyleCircular ];
 [quitBtn setTitle: @"Q" ];
 [quitBtn setAction:@selector(terminate:)];
 [[window contentView] addSubview: quitBtn];
}
 
-(void) applicationWillFinishLaunching: (NSNotification *)notification {
 [self buildMenu];
 [self buildWindow];
}
 
@end

int main() {
 NSApplication *application = [NSApplication sharedApplication];
 AppDelegate *appDelegate = [[AppDelegate alloc] init];
 [application setDelegate:appDelegate];
 [application run];
 return 0;
}

person apodidae    schedule 13.12.2020