Drag&Drop in einer Menu-Bar-App

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Drag&Drop in einer Menu-Bar-App

    Hallo zusammen,

    ich versuche die Drag&Drop-Funktionalität für eine Menu-Bar-App zu realisieren. Für eine "normale" App ist das kein Problem, da hat man ein NSView mit Methoden wie shouldAllowDrag, draggingEntered usw... Dazu gibt es noch ein Delegate-Protokoll, welches von Delegate-Klasse implementiert wird. Dieser Fall ist, wie gesagt, kein Problem.

    In meinem Fall habe ich ja kein Programmfenster, in welches NSView eingebettet wird. Ich habe versucht beim Anlegen des Menüs ein NSView zu erzeugen:

    Quellcode

    1. statusItem.menu = menu
    2. statusItem.menu?.autoenablesItems = false
    3. var viewItem = StatusItemView(with: statusItem)
    4. viewItem.delegate = self


    Dazu die entsprechende StatusItemView-Klasse:

    Quellcode

    1. var item: NSStatusItem?
    2. var delegate: DropViewDelegate?
    3. let types = [NSPasteboard.PasteboardType.png, NSPasteboard.PasteboardType.fileURL]
    4. let filteringOptions = [NSPasteboard.ReadingOptionKey.urlReadingContentsConformToTypes:NSImage.imageTypes]
    5. override init(frame frameRect: NSRect) {
    6. super.init(frame: frameRect)
    7. self.registerForDraggedTypes(types)
    8. }
    9. convenience init(with item: NSStatusItem) {
    10. let itemRect = NSMakeRect(0.0, 0.0, item.length, item.length)
    11. self.init(frame: itemRect)
    12. }
    Alles anzeigen
    Damit habe ich leider keinen Erfolg. Ich vermute ein NSView bringt ohne NSWindow nicht viel, aber ich habe keine andere Idee. Vielleicht hat jemand einen Tipp für mich?
    Swift-Anfänger
  • Hallo,

    geht definitiv, da ich es ebenfalls an mehreren Stellen verwende.
    Siehe unten für die Methoden, die ich implementiere.

    Viele Grüße

    C-Quellcode

    1. - (id)initWithFrame:(NSRect)frameRect
    2. dropsStatusItem:(DropsStatusItem*)newDropsStatusItem
    3. {
    4. [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
    5. }
    6. - (void) setFrameSize:(NSSize)newSize
    7. {
    8. // Alte TrackingAreas entfernen
    9. NSArray *trackingAreas = [self trackingAreas];
    10. for(id nTrackingArea in trackingAreas)
    11. {
    12. [self removeTrackingArea:nTrackingArea];
    13. }
    14. // Neues TrackingArea
    15. [self addTrackingRect:NSMakeRect(0, 0, newSize.width, newSize.height)
    16. owner:self
    17. userData:nil
    18. assumeInside:NO];
    19. [super setFrameSize:newSize];
    20. }
    21. - (BOOL)acceptsFirstResponder
    22. {
    23. return YES;
    24. }
    25. - (BOOL)becomeFirstResponder
    26. {
    27. return YES;
    28. }
    29. #pragma mark -
    30. #pragma mark Drag & Drop
    31. - (NSDragOperation)draggingEntered:(id < NSDraggingInfo >)sender
    32. {
    33. return dragOperation;
    34. }
    35. - (BOOL)prepareForDragOperation:(id < NSDraggingInfo >)sender
    36. {
    37. return YES;
    38. }
    39. - (void)draggingExited:(id < NSDraggingInfo >)sender
    40. {
    41. }
    42. - (BOOL)performDragOperation:(id < NSDraggingInfo >)sender
    43. {
    44. return YES;
    45. }
    Alles anzeigen
  • Hi,

    kann kaum was mit den trackingAreas in deinem Code anfangen, sonst sieht es bei mir ziemlich gleich aus (Swift). Ich habe gerade getestet, keine der Methoden "springt an", wenn ich ein Bild darüber ziehe. Ein Objekt dieser Klasse wird in der AppDelegate mit einem StatusItem als Parameter erzeugt - ob da noch was fehlt.

    Quellcode

    1. import Foundation
    2. import Cocoa
    3. class DropAreaView: NSView {
    4. var item: NSStatusItem?
    5. var types = [NSPasteboard.PasteboardType.png, NSPasteboard.PasteboardType.pdf]
    6. let filteringOptions = [NSPasteboard.ReadingOptionKey.urlReadingContentsConformToTypes:NSImage.imageTypes]
    7. override init(frame frameRect: NSRect) {
    8. super.init(frame: frameRect)
    9. registerForDraggedTypes(types)
    10. }
    11. convenience init(with item: NSStatusItem) {
    12. let itemRect = NSMakeRect(0.0, 0.0, item.length, item.length)
    13. self.init(frame: itemRect)
    14. }
    15. required init?(coder decoder: NSCoder) {
    16. fatalError("init(coder:) has not been implemented")
    17. }
    18. override func becomeFirstResponder() -> Bool {
    19. return true
    20. }
    21. func shouldAllowDrag(_ draggingInfo: NSDraggingInfo) -> Bool {
    22. let pasteBoard = draggingInfo.draggingPasteboard
    23. if pasteBoard.canReadObject(forClasses: [NSImage.self], options: filteringOptions) {
    24. return true
    25. }
    26. return false
    27. }
    28. var isReceivingDrag = false {
    29. didSet {
    30. needsDisplay = true
    31. }
    32. }
    33. override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
    34. let allow = shouldAllowDrag(sender)
    35. isReceivingDrag = allow
    36. return allow ? .copy : NSDragOperation()
    37. }
    38. override func draggingExited(_ sender: NSDraggingInfo?) {
    39. //
    40. }
    41. override func prepareForDragOperation(_ sender: NSDraggingInfo) -> Bool {
    42. return true
    43. }
    44. override func performDragOperation(_ draggingInfo: NSDraggingInfo) -> Bool {
    45. isReceivingDrag = false
    46. let pasteBoard = draggingInfo.draggingPasteboard
    47. let point = convert(draggingInfo.draggingLocation, from: nil)
    48. if let urls = pasteBoard.readObjects(forClasses: [NSURL.self], options:filteringOptions) as? [URL], urls.count > 0 {
    49. return true
    50. }
    51. return false
    52. }
    53. }
    Alles anzeigen
    Swift-Anfänger
  • Ich habe es hinbekommen. Sollte es jemanden interessieren:
    1. let itemRect = NSMakeRect(0.0, 0.0, item.length, item.length) Item.length macht in diesem Fall keinen Sinn, da es -2 ist, habe auf 24 gesetzt
    2. View dem Button hinzufügen -> statusItem.button?.addSubview(dropView)
    Swift-Anfänger