MacOS: как заставить NSPanel противостоять ключевому фокусу (с становится hasKeyOnlyIfNeeded?) - PullRequest
0 голосов
/ 04 марта 2019

В MacOS / Cocoa / Swift 4.2 / Xcode 10.1 я пытаюсь создать NSPanel, которая перемещается по окну моего документа в виде облегченной палитры разметки, которая взаимодействует с сеансом редактирования (главным образом на основе клавиатуры), происходящим в окне документа.

У меня в основном есть кнопочные элементы управления на панели, но есть одно поле со списком, которое заслуживает того, чтобы сфокусироваться, когда пользователь нажимает на него.Кроме того, я бы хотел не становиться ключевым окном (избегать как захвата будущих ключевых событий, так и подсветки строки заголовка), когда нажимаются какие-либо другие элементы управления, или когда панель перемещается перетаскиванием или щелчками на панели вмертвый космос.Это звучит для меня так же, как то, что в документации описывается как поведение, которое я должен иметь, если моя панель помечена как становилась становящейся ключом, но я не могу заставить ее работать.

В Интерфейсном Разработчике я указываю свою панель как (мойсобственный) подкласс InspectorPanel со стилем «Обычная панель», «Строка заголовка», «Тень», «Закрыть», «Восстановить» и «Скрыть при деактивации» (все остальное понятно).В подклассе я указываю getsKeyOnlyIfNeeded:

class InspectorPanel : NSPanel {
     override var becomesKeyOnlyIfNeeded: SwiftBool {
        get {
            return true
        }
        set {
        }
    }    
}

(я также пытался установить его в awakeFromNib контроллера, в окне контроллера как? NSPanel.)

Эта настройка, кажется, не имеетвидимый эффект.Панель корректно всплывает над окном документа, но в то время как поле со списком успешно захватывает фокус ключа от окна документа, то же самое можно сделать, нажав любой элемент управления , щелкнув пробел на панели или перетащив строку заголовка панели,а также, возможно, другие манипуляции.Хотя я могу написать обработчики для каждого из этих случаев, которые вручную находят активное окно документа и makeKeyWindow (thatWindow) для передачи фокуса туда, где он принадлежит, это выглядит не элегантно с точки зрения дизайна инспектора;вынуждает меня писать некоторые обработчики, в которых я в данный момент не нуждаюсь (например, перетаскивание строки заголовка);и заставляет меня беспокоиться о подобных случаях, которые я пропускаю.

Вместо этого есть какой-то способ добиться успеха, чтобы стать ключом, только когда это нужно моему единственному комбинированному списку?Если да, то как?

Другие усилия:

  1. Я осведомлен о необходимостиPanelToBecomeKey и несколько смущен его документацией.Предполагается, что после того, как я установлю на панели становится ключ KEYOnlyIfNeeded, НИЧТО не позволит панели захватывать фокус, пока я не включу needsPanelToBecomeKey в определенных подпредставлениях (например, в моем комбинированном ящике).По правде говоря, так как установка getsKeyOnlyIfNeeded не влияет на то, чтобы окно не становилось ключом, я не вижу разницы в ответе, установил я comboBox.needsPanelToBecomeKey для подпредставления или нет.)

  2. IЯ также осведомлен о RefsesFirstResponder и пытался установить его на различных элементах управления (например, NSButtons) на панели, чтобы увидеть, не мешает ли это перенести фокусировку клавиш на окно.Не повезло.)

  3. Если я установлю canBecomeKeyWindow = false, тогда я НИКОГДА не получу фокусировку ключа, даже в моем comboBox.(Это кажется разумным и неожиданным; я просто перечисляю его как исчерпывающий.)

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

Ответы [ 2 ]

0 голосов
/ 05 марта 2019

Я обнаружил причину своей проблемы.По-видимому, я не понимаю значения инициализаторов Swift, которые я использую для переопределения, как приведено выше, становится ключом KEYOnlyIfNeeded (хотя я успешно использую тот же синтаксис для других свойств в другом месте!).Если я удаляю попытку определить getsKeyOnlyIfNeeded как всегда true, и вместо этого динамически устанавливаю его (унаследованное свойство) в значение true по пути инициализации окна, панель ведет себя именно так, как я хочу, сопротивляясь фокусу ключа, за исключением того, чтону, «если нужно» (при нажатии в поле со списком).

Другими словами,

class InspectorPanel : NSPanel {

  override func awakeFromNib() {
    super.awakeFromNib()
    becomesKeyOnlyIfNeeded = true // REPLACES THE BELOW
  }

  /* REPLACED BY ABOVE
  override var becomesKeyOnlyIfNeeded: SwiftBool {
    get {
        return true
    }
    set {

    }
  }
  */
}

работает отлично.Если кто-то поймет, что я сделал не так с моим (закомментированным) инициализатором, я был бы признателен за понимание, но с помощью этого обходного пути я могу закрыть открытый вопрос о поведении панели.

0 голосов
/ 04 марта 2019

Либо используйте маску стиля NSWindowStyleMaskUtilityWindow при программном создании NSPanel (подкласс NSWindow), либо укажите стиль «Панель утилит» в IB.

Этот стиль определяет внешний види поведение плавающего окна палитры.

...