16

NSTableViewのヘッダーの右クリック/Ctrlキーを押しながらクリックを検出するための洗練された方法を探しています。

右クリックが発生したら、コンテキストメニューを表示したい。

- (NSMenu *)menuForEvent:(NSEvent *)

テーブルの右クリックのみを検出します。テーブルのヘッダーでは検出しません。

ご協力いただきありがとうございます。

4

4 に答える 4

40

時々絵は1000の言葉を説明します。

  1. テーブルビューをサブクラス化する必要はありません。
  2. 任意のtableViewで、TableViewを選択し、メニューアウトレットをメニューに接続できます。 ここに画像の説明を入力してください

  3. これで、メニューのセレクター(右側)をコードに接続できます。

  4. テーブルのどの行がクリックされたかを把握するには、

[yourTableView clickedRow]

終わり。偉ぶって。

于 2011-04-19T22:36:47.460 に答える
19

NSTableViewからNSTableHeaderViewを取得し、そのメニューを設定します。

[[myTableView headerView] setMenu:aMenu];
于 2010-10-03T14:51:41.820 に答える
9

サブクラス化する必要がありますNSTableHeaderView。サブクラス化せずにメニューを表示することはできますが、サブクラス化せずにクリックされたテーブル列を見つけることはできません(コンテキストメニューが役に立たなくなります)。

テーブルヘッダービューの独自のサブクラスを作成し、デリゲートを追加しました。Interface Builderで、を見つけNSTableHeaderViewてカスタムサブクラスを割り当て、新しいdelegateアウトレットを接続します。さらに、メニューを作成してmenuアウトレットに割り当てます。

-validateMenu:forTableColumn:次に、デリゲートにメソッドを実装します。メニュー項目を適切に有効/無効にします(メニューがIBで自動検証されないことを確認してください)。クリックした列をインスタンス変数のどこかに格納して、ユーザーがアクションを選択したときにどの列を操作するかがわかるようにします。

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
于 2014-06-27T07:57:07.217 に答える
1

正確な答えをくれたJakobEggerに感謝します。私はこのアプローチのSwiftバージョンを思いつきます。ViewControllerに複数のTableViewがある場合に柔軟性を高めるために、デリゲートメソッドのシグネチャを少し変更しました。

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;
    }
}

このカスタムクラスを使用するには、Interface BuilderでNSTableHeaderViewを見つけて、クラスをMenuTableHeaderViewに変更します。

カスタムクラス名を入力する必要があるウィンドウ

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
    }
}
于 2017-11-04T06:31:51.440 に答える