【问题标题】:NSAlert: Make second button both the default and cancel buttonNSAlert:将第二个按钮设为默认按钮和取消按钮
【发布时间】:2019-04-20 13:12:42
【问题描述】:

Apple 最初的 HIG(遗憾的是现在从网站上消失了)声明:

对话框中最右边的按钮,即操作按钮,是确认警报消息文本的按钮。操作按钮通常是但不总是默认按钮

就我而言,我有一些破坏性操作(例如擦除磁盘)需要“安全”确认对话框,如下所示:

最糟糕的选择是创建一个对话框,其中最右边的按钮将成为“不擦除”按钮,而最左边的按钮,通常是“取消”按钮,将成为“擦除”按钮,因为这很容易导致灾难(happened to me 有一次微软制造的对话框),因为人们被训练在想要取消操作时单击第二个按钮。

所以,我需要的是左(取消)按钮既成为默认按钮,也对 Return、Esc 和 cmd-句点键作出反应。

要使其成为默认值并响应 Return 键,我只需将第一个按钮的 keyEquivalent 设置为空字符串,将第二个按钮的设置为“\r”。

但是如何在 Esc 或 cmd- 时也取消警报。输入了吗?

【问题讨论】:

  • 一个按钮同时响应↩和⎋当然是违反HIG的。无论如何,您不能为按钮分配两个不同的等效键。您可以设计自定义视图并实现自己的逻辑来处理鼠标和键盘事件
  • 您的“取消”按钮是否真的标题为“取消”?
  • @vadian 我不同意。您能否展示一篇支持您主张的 macOS 的 HIG 文章?
  • @KenThomases 是的,我忘了说它不叫“取消”,而是“不要擦除”或类似的东西。我意识到将其命名为 Cancel 可能是一个简单的解决方案。
  • 在 macOS Catalina 上,保存对话框的文件替换确认警报默认具有取消按钮。 macOS 指南也声明 when a dialog may result in a destructive action, Cancel can be set as the default button.

标签: macos cocoa nsalert


【解决方案1】:

按照您通常的方式设置 NSAlert,并分配默认按钮。创建一个新的 NSView 子类,其边界为空,并将其添加为 NSAlert 的附属视图。在子类的 performKeyEquivalent 中,检查 Esc 以及是否匹配调用 [-NSApplication stopModalWithCode:][-NSWindow endSheet:returnCode:]

#import "AppDelegate.h"

@interface AlertEscHandler : NSView
@end

@implementation AlertEscHandler
-(BOOL)performKeyEquivalent:(NSEvent *)event {
    NSString *typed = event.charactersIgnoringModifiers;
    NSEventModifierFlags mods = (event.modifierFlags & NSEventModifierFlagDeviceIndependentFlagsMask);
    BOOL isCmdDown = (mods & NSEventModifierFlagCommand) != 0;
    if ((mods == 0 && event.keyCode == 53) || (isCmdDown && [typed isEqualToString:@"."])) { // ESC key or cmd-.
        [NSApp stopModalWithCode:1001]; // 1001 is the second button's response code
    }
    return [super performKeyEquivalent:event];
}
@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    [self alertTest];
    [NSApp terminate:0];
}

- (void)alertTest {
    NSAlert *alert = [NSAlert new];
    alert.messageText = @"alert msg";
    [alert addButtonWithTitle:@"OK"];
    NSButton *cancelButton = [alert addButtonWithTitle:@"Cancel"];
    alert.window.defaultButtonCell = cancelButton.cell;
    alert.accessoryView = [AlertEscHandler new];
    NSModalResponse choice = [alert runModal];
    NSLog (@"User chose button %d", (int)choice);
}

【讨论】:

猜你喜欢
  • 2013-05-13
  • 2015-03-08
  • 1970-01-01
  • 2013-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-05
  • 1970-01-01
相关资源
最近更新 更多