NSButton внутри NSViewRepresentable не дает «визуальной обратной связи» при нажатии

#macos #swiftui #appkit #nsbutton

#macos #swiftui #набор приложений #nsbutton

Вопрос:

Я создал NativeButton на основе NSButton с NSViewRepresentable для обнаружения щелчков правой кнопкой мыши.
Он работает нормально, но я не получаю «визуальной обратной связи», как с обычной кнопкой, если она нажата.
Как я могу добиться того, чтобы кнопка стала темной, если на нее нажать (как на любую обычную кнопку)?

 struct TEST_NativeButton: View {
  var body: some View {
    VStack{
      Text("Test Native Button")
      NativeButton(
        rightClickAction: {print("rightclick")},
        leftClickAction: {print("leftclick")}
      )
      { print("standard action")
      }
    }.frame(width: 200, height: 200)
  }
}

struct NativeButton: NSViewRepresentable {
  typealias NSViewType = NativeNSButton

  let rightClickAction: ActionFunction
  let leftClickAction: ActionFunction
  let standardAction: ActionFunction

  init(
        rightClickAction : ActionFunction?  = nil,
        leftClickAction :  ActionFunction?  = nil,
        standardAction:    @escaping ActionFunction
  )
  {
    if let rightClickAction = rightClickAction{
      self.rightClickAction = rightClickAction
    } else {
      self.rightClickAction = {}
    }

    if let  leftClickAction = leftClickAction{
      self.leftClickAction = leftClickAction
    } else {
      self.leftClickAction = standardAction
    }

    self.standardAction = standardAction

  }

  func makeNSView(context: Context) -> NativeNSButton {
    NativeNSButton(
                  rightClickAction: rightClickAction,
                  leftClickAction: leftClickAction,
                  standardAction: standardAction)
  }

  func updateNSView(_ nsView: NativeNSButton, context: Context) {
    //ToDo auf änderungen am Titel reagieren
    return
  }
}

class NativeNSButton: NSButton {
  let standardAction: () -> Void
  let rightClickAction: () -> Void
  let leftClickAction: () -> Void

  init(
        rightClickAction : @escaping () -> Void,
        leftClickAction :  @escaping () -> Void,
        standardAction:    @escaping () -> Void) {

    self.standardAction = standardAction
    self.rightClickAction = rightClickAction
    self.leftClickAction = leftClickAction

    super.init(frame: .zero)

    self.title = title
    self.alignment = alignment
    self.target = self
    self.action = #selector(clickButton(_:))

    bezelStyle = .rounded
    isBordered = true
    focusRingType = .none

    self.translatesAutoresizingMaskIntoConstraints = false
    self.setContentHuggingPriority(.defaultHigh, for: .vertical)
    self.setContentHuggingPriority(.defaultHigh, for: .horizontal)
  }

  required init?(coder: NSCoder) {
    fatalError()
  }

  override func mouseDown(with theEvent: NSEvent) {
    //print("left mouse")
    leftClickAction()
  }

  override func rightMouseDown(with theEvent: NSEvent) {
    //print("right mouse")
    rightClickAction()
  }

  @objc func clickButton(_ sender: BbcNSButton) {
    //print("standard action")
    standardAction()
  }
}

 

Стандартное действие используется для обнаружения сочетаний клавиш (удалено в этом примере).

Комментарии:

1. NSButton рисует себя нажатым всякий mouseDown раз, когда вызывается его, но вы полностью переопределяете его (без вызова super), поэтому ничто не дает возможности кнопке нарисовать себя нажатой. Вам нужно переосмыслить свою концепцию NativeNSButton.

2. @Asperi Достаточно ли назвать super, как советовал Раджа Кишан, или вы видите дополнительные проблемы с концепцией?

Ответ №1:

Вызов супер метода

 override func mouseDown(with theEvent: NSEvent) {
    super.mouseDown(with: theEvent)
    //print("left mouse")
    leftClickAction()
  }