2010-10-03 11 views

risposta

17

Ottieni NSTableHeaderView da NSTableView e imposta il suo menu.

[[myTableView headerView] setMenu:aMenu]; 
+0

funziona perfetto :) grazie – tubtub

+2

Se si seleziona l'intestazione in Interface Builder, è anche possibile trascinare una connessione a un menu nel NIB/XIB. – Dov

+0

come faresti a sapere su quale colonna è stato fatto clic con il pulsante destro del mouse? –

38

A volte un'immagine spiega 1000 parole.

  1. Non è necessario eseguire la sottoclasse della vista tabella.
  2. Su qualsiasi tabellaView è possibile selezionare TableView e collegare la presa menu a un menu. enter image description here

  3. Ora è possibile collegare il selettore del menu (a destra) al codice.

  4. Per capire cosa uso riga nella tabella è stato cliccato

[yourTableView clickedRow]

Fatto. Come un capo.

+1

solo 18 "Mi piace" in 2 anni. –

+0

sì non molti. Ma ho ricevuto un distintivo per questo, credo. Ottenere più voti rispetto alla risposta accettata. –

+3

Non capisco perché questo abbia avuto così tanti voti positivi. La domanda chiede chiaramente un menu di scelta rapida per la tabella HEADER. Questo mostra solo come ottenere un menu di scelta rapida sulle righe. –

4

È necessario sottoclasse NSTableHeaderView. Mentre è possibile visualizzare un menu senza sottoclassi, non è possibile scoprire quale colonna della tabella è stata cliccata senza sottoclassi (rendendo il menu di scelta rapida inutilizzabile).

Ho scritto il mio sublcass della vista dell'intestazione della tabella e aggiunto un delegato. Nel generatore di interfacce, individuare NSTableHeaderView, assegnargli la sottoclasse personalizzata e collegarne la nuova presa delegate. Inoltre, creare un menu e assegnarlo alla presa menu.

Quindi implementare il metodo -validateMenu:forTableColumn: nel delegato. Abilitare/disabilitare le voci di menu come appropriato (assicurarsi che il menu non si autovalidazione in IB). Memorizza la colonna cliccata da qualche parte in una variabile di istanza, in modo da sapere su quale colonna agire quando l'utente seleziona un'azione.

PGETableViewTableHeaderView.h

#import <Cocoa/Cocoa.h> 
@protocol PGETableViewTableHeaderViewDelegate <NSObject> 
-(void)validateMenu:(NSMenu*)menu forTableColumn:(NSTableColumn*)tableColumn; 
@end 
@interface PGETableViewTableHeaderView : NSTableHeaderView 
@property(weak) IBOutlet id<PGETableViewTableHeaderViewDelegate> delegate; 
@end 

PGETableViewTableHeaderView.m

#import "PGETableViewTableHeaderView.h" 
@implementation PGETableViewTableHeaderView 
-(NSMenu *)menuForEvent:(NSEvent *)event { 
    NSInteger columnForMenu = [self columnAtPoint:[self convertPoint:event.locationInWindow fromView:nil]]; 
    NSTableColumn *tableColumn = nil; 
    if (columnForMenu >= 0) tableColumn = self.tableView.tableColumns[columnForMenu]; 
    NSMenu *menu = self.menu; 
    [self.delegate validateMenu:menu forTableColumn:tableColumn]; 
    return menu; 
} 
@end 
+0

Questa è la migliore risposta alla domanda - come a) risponde alla domanda eb) affronta il problema se la colonna è stata selezionata. –

+0

Questa è la risposta completa +1 – insys

0

Grazie Jakob Egger per la sua risposta precisa. Vengo con la versione Swift di questo approccio. Ho modificato leggermente la firma del metodo delegate per offrire maggiore flessibilità in caso di più di una TableView in ViewController.

protocol IMenuTableHeaderViewDelegate: class { 
    func menuForTableHeader(inTableView tableView: NSTableView, forTableColumn tableColumn: NSTableColumn) -> NSMenu? 
} 

class MenuTableHeaderView: NSTableHeaderView { 
    weak var menuDelegate: IMenuTableHeaderViewDelegate? 

    override func menu(for event: NSEvent) -> NSMenu? { 
     guard tableView != nil else { 
      return nil 
     } 
     let columnForMenu = column(at: convert(event.locationInWindow, from: nil)) 
     if columnForMenu >= 0, tableView!.tableColumns.count > columnForMenu { 
      if let tableColumn = tableView?.tableColumns[columnForMenu] { 
       return menuDelegate?.menuForTableHeader(inTableView: tableView!, forTableColumn: tableColumn) 
      } 
     } 
     return self.menu; 
    } 
} 

Per utilizzare questa classe personalizzata, trovare NSTableHeaderView nel generatore di interfaccia e cambiare la classe di MenuTableHeaderView

Window where you have to enter custom class name

esempio di questo uso approccio in un ViewController

class ExampleViewController: NSViewController, IMenuTableHeaderViewDelegate { 
    @IBOutlet weak var tableView: NSTableView! 
    @IBOutlet var tableHeaderMenu: NSMenu! 

    var lastColumnForMenu: HeaderColumnForMenu? 

    struct HeaderColumnForMenu { 
     let tableView: NSTableView 
     let tableColumn: NSTableColumn 
    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     if let tableHeaderWithMenu = tableView.headerView as? MenuTableHeaderView { 
      tableHeaderWithMenu.menuDelegate = self 
     } 
    } 

    func menuForTableHeader(inTableView tableView: NSTableView, forTableColumn tableColumn: NSTableColumn) -> NSMenu? { 
     //Save column to wich we are going to show menu 
     lastColumnForMenu = HeaderColumnForMenu(tableView: tableView, tableColumn: tableColumn) 
     if needShowMenu { 
      return tableHeaderMenu 
     } 
     return nil 
    } 
} 
Problemi correlati