2010-10-03 13 views

Respuesta

17

Obtenga NSTableHeaderView de NSTableView y configure su menú.

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

funciona perfecto :) gracias – tubtub

+2

Si selecciona el encabezado en el Interface Builder, también puede arrastrar una conexión a un menú en su NIB/XIB. – Dov

+0

¿Cómo sabrías en qué columna se ha hecho clic con el botón derecho? –

38

A veces una imagen explica 1000 palabras.

  1. No es necesario que subponga su vista de tabla.
  2. En cualquier tableView puede seleccionar TableView y conectar la salida del menú a un menú. enter image description here

  3. Ahora puede conectar el selector del menú (a la derecha) a su código.

  4. de averiguar lo que su uso fila de la tabla se ha hecho clic

[yourTableView clickedRow]

Listo. Como un jefe.

+1

solo 18 'Me gusta' en 2 años. –

+0

sí, no tantos. Pero creo que obtuve una insignia para esta. Obteniendo más votos que la respuesta aceptada. –

+3

No entiendo por qué esto tiene tantos upvotes. La pregunta claramente pregunta sobre un menú contextual para la tabla HEADER. Esto solo muestra cómo obtener un menú contextual en las filas. –

4

Tiene que subclase NSTableHeaderView. Si bien es posible hacer aparecer un menú sin crear subclases, no es posible descubrir en qué columna de la tabla se hizo clic sin subclases (haciendo inútil el menú contextual).

Escribí mi propia subcase de la vista de encabezado de tabla y agregué un delegado. En el generador de interfaces, busque NSTableHeaderView, asígnele su subclase personalizada y conecte su nueva toma de corriente delegate. Además, cree un menú y asígnelo a la salida menu.

Luego, implemente el método -validateMenu:forTableColumn: en el delegado. Habilite/deshabilite los elementos del menú según corresponda (asegúrese de que el menú no se autovalide en IB). Almacene la columna cliqueada en algún lugar de una variable de instancia, para que sepa en qué columna actuar cuando el usuario seleccione una acción.

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

Esta es la mejor respuesta a la pregunta, ya que a) responde la pregunta yb) trata el problema si se hace clic en la columna. –

+0

Esta es la respuesta completa +1 – insys

0

Gracias Jakob Egger por su respuesta precisa. Vengo con la versión Swift de este enfoque. Cambié un poco la firma del método de delegado, para dar más flexibilidad en caso de más de una TableView en 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; 
    } 
} 

Para utilizar esta clase personalizada, encontrará NSTableHeaderView en el generador de interfaz y cambiar la clase a MenuTableHeaderView

Window where you have to enter custom class name

ejemplo de este uso enfoque en 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 
    } 
} 
Cuestiones relacionadas