9 Stimmen

Benutzerdefinierte NSView in NSMenuItem empfängt keine Mausereignisse

Ich habe ein NSMenu popping aus einem NSStatusItem mit popUpStatusItemMenu. Diese NSMenuItems zeigen eine Reihe von verschiedenen Links, und jeder ist mit setAction: mit der openLink: Methode eines Ziels verbunden. Diese Anordnung hat lange Zeit gut funktioniert. Der Benutzer wählt einen Link aus dem Menü aus und die openLink:-Methode kümmert sich dann um ihn.

Leider habe ich vor kurzem beschlossen, mit der Verwendung von NSMenuItem's setView: Methode zu experimentieren, um eine schönere / glattere Schnittstelle zu bieten. Im Grunde habe ich einfach aufgehört, den Titel zu setzen, das NSMenuItem erstellt und dann setView: verwendet, um eine benutzerdefinierte Ansicht anzuzeigen. Dies funktioniert perfekt, die Menüelemente sehen toll aus und meine benutzerdefinierte Ansicht wird angezeigt.

Wenn der Benutzer jedoch einen Menüpunkt auswählt und die Maus loslässt, funktioniert die Aktion nicht mehr (d. h. openLink: wird nicht aufgerufen). Wenn ich den setView:-Aufruf einfach auskommentiere, dann funktionieren die Aktionen wieder (natürlich sind die Menüpunkte leer, aber die Aktion wird korrekt ausgeführt). Meine erste Frage ist also, warum das Setzen einer Ansicht die Aktion des NSMenuItem unterbricht.

Kein Problem, dachte ich, ich werde es beheben, indem ich das mouseUp-Ereignis in meiner benutzerdefinierten Ansicht erkenne und meine Aktionsmethode von dort aus aufrufe. Ich habe diese Methode zu meiner benutzerdefinierten Ansicht hinzugefügt:

- (void)mouseUp:(NSEvent *)theEvent {
  NSLog(@"in mouseUp");
  }

Keine Chance! Diese Methode wird nie aufgerufen.

Ich kann Tracking-Reichweiten festlegen und empfangen mouseEntered: Ereignisse, obwohl. Ich habe ein paar Tests in meiner mouseEntered Routine, wie folgt:

if ([[self window] ignoresMouseEvents]) {  NSLog(@"ignoring mouse events");  }
else {  NSLog(@"not ignoring mouse events");  }
if ([[self window] canBecomeKeyWindow]) {  dNSLog((@"canBecomeKeyWindow"));  }
else {  NSLog(@"not canBecomeKeyWindow");  }
if ([[self window] isKeyWindow]) {  dNSLog((@"isKeyWindow"));  }
else {  NSLog(@"not isKeyWindow");  }

Und erhielt die folgenden Antworten:

not ignoring mouse events
canBecomeKeyWindow
not isKeyWindow

Ist dies das Problem? "not isKeyWindow"? Vermutlich ist das nicht gut, weil die Apple-Dokumente sagen: "Wenn der Benutzer auf eine Ansicht klickt, die sich nicht im Schlüsselfenster befindet, wird das Fenster standardmäßig nach vorne gebracht und zum Schlüsselfenster gemacht, aber das Mausereignis wird nicht ausgelöst." Aber es muss einen Weg geben, diese Ereignisse zu erkennen. WIE?

Hinzufügen:

[[self window] makeKeyWindow];

hat keine Auswirkungen, obwohl canBecomeKeyWindow YES ist.

0 Stimmen

Weitere Informationen zu diesem Problem finden Sie unter Open Radar: openradar.appspot.com/7128269 Es gibt auch eine angebliche Umgehung, aber ich kann die Umgehung nicht zum Laufen bringen. Im Grunde weigert sich das Fenster einfach, Schlüssel zu werden, obwohl es canBecomeKey meldet.

0 Stimmen

Hallo, ich habe das gleiche Problem konfrontiert, haben Sie irgendwelche Fortschritte mit ihm? Ich habe versucht, einige Wege, um es zu lösen, ich habe einen Workaround gefunden, aber seine schrecklich hässlich, und nach der Anzeige der Menü-Statusleiste Element ist nicht hervorgehoben, aber Menü angezeigt wird und voll funktionsfähig. Ich habe das Menü für das Statuselement auf Null gesetzt und das Menü-Popup manuell gesteuert. Wenn die Anwendung aktiv ist, rufe ich einfach die Methode menu popup auf, wenn nicht, sende ich die Nachricht make application active, und im Callback öffne ich das Menü. Hier ist etwas Code. Wieder seine schrecklich und hässlich. gist.github.com/224275

0 Stimmen

Ich muss sagen, dass der Code von iafonov großartig ist! Allerdings ein Jahr vorher!!! Allerdings scheint der Code irrelevant zu sein. Danke dafür! Es löst alle Probleme über NSVIew, NSTextEdit in NSMenuItem. Zuerst funktioniert NSTextEdit (in NSMenuItem) nicht normal, kann keinen Tastendruck empfangen und die Maus ändert sich nicht, jetzt funktioniert alles wunderbar!!! Kein acceptsFirstResponder, kein self window makeFirstResponder:xxx, nur iafonov'code. Es ist der Weg zum Pop-up-Menü, das zählt. gist.github.com/224275

17voto

Lothar Punkte 11643

Fügen Sie diese Methode zu Ihrer benutzerdefinierten NSView hinzu, und sie wird mit Mausereignissen gut funktionieren

- (void)mouseUp:(NSEvent*) event {
    NSMenuItem* mitem = [self enclosingMenuItem];
    NSMenu* m = [mitem menu];
    [m cancelTracking];
    [m performActionForItemAtIndex: [m indexOfItem: mitem]];
}

Aber ich habe Probleme mit dem Keyhandling, wenn Sie dieses Problem gelöst haben, können Sie vielleicht auf meine Frage eingehen und mir ein wenig helfen.

10voto

fabian Punkte 101

Fügen Sie dies zu Ihrer benutzerdefinierten Ansicht hinzu, und Sie sollten keine Probleme haben:

- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
{
    return YES;
}

10voto

Justin Voss Punkte 6174

Ich habe diese Methode zu meiner benutzerdefinierten Ansicht hinzugefügt, und jetzt funktioniert alles wunderbar:

- (void)viewDidMoveToWindow {
    [[self window] becomeKeyWindow];
}

Ich hoffe, das hilft!

3voto

SwiftyFinch Punkte 375

Ich habe diese Version aktualisiert für SwiftUI Swift 5.3 :

final class HostingView<Content: View>: NSHostingView<Content> {
    override func viewDidMoveToWindow() {
        window?.becomeKey()
    }
}

Und dann wie folgt verwenden:

let item = NSMenuItem()
let contentView = ContentView()
item.view = HostingView(rootView: contentView)

let menu = NSMenu()
menu.items = [item]

2voto

Marcin Punkte 3549

Bislang besteht die einzige Möglichkeit, das Ziel zu erreichen, darin, einen Tracking-Bereich manuell in updateTrackingAreas - die zum Glück so genannt wird:

override func updateTrackingAreas() {
    let trackingArea = NSTrackingArea(rect: bounds, options: [.enabledDuringMouseDrag, .mouseEnteredAndExited, .activeInActiveApp], owner: self, userInfo: nil)
    addTrackingArea(trackingArea)
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X