2017-07-29 16 views
1

誰もが右クリック中に青い輪郭を取り除く方法について議論しましたが、私はそうです。NSOutlineView右クリックで青い輪郭を表示する方法

代わりに、青い輪郭を表示しようとしています。

アウトラインビューの行を右クリックしても輪郭が表示されませんでした。メニューは表示されましたが、アウトラインは表示されませんでした。

あなたは青のアウトラインは以下のこの絵で表示されていないことがわかります。

以下

enter image description here



は私が達成しようとしているものです。

Blue outline


更新

これは私がNSMenuを実装する方法です。 NSOutlineViewをサブクラス化し、NSOutlineViewDelegateをオーバーライドする新しいプロトコルを作成しました。

この考えは、NSOutlineViewに各項目のNSMenuを尋ねることで簡単にしていましたので、各項目ごとに異なるメニューを実装することができます。それは動作しますが、青いアウトラインビューは右クリックの間に表示されません。

KRMenuOutlineView.swift

import Cocoa 

@objc protocol KRMenuOutlineViewDelegate: NSOutlineViewDelegate { 
    // This method will ask NSMenu for each item in outline view 
    func outlineView(_ outlineView: KRMenuOutlineView, menuFor item: Any, event: NSEvent) -> NSMenu? 
} 

class KRMenuOutlineView: NSOutlineView { 

    override var delegate: NSOutlineViewDelegate? { 
     didSet { 
      if let newValue = delegate { 
       /* 
       * Swift doesn't support overriding inherited properties with different type 
       * like Objective C Does, therefore we need internal delegate. 
       */ 
       internalDelegate = unsafeBitCast(newValue, to: KRMenuOutlineViewDelegate.self) 
      } else { 
       internalDelegate = nil 
      } 
     } 
    } 

    private var internalDelegate: KRMenuOutlineViewDelegate? 

    override func menu(for event: NSEvent) -> NSMenu? { 
     let point = self.convert(event.locationInWindow, from: nil) 
     if let item = self.item(atRow: self.row(at: point)) { 
      return self.internalDelegate?.outlineView(self, menuFor: item, event: event) 
     } 
     return super.menu(for: event) 
    } 
} 

その後、私はこのような私のビューコントローラでそれを使用します。適切にコンテキストを表示する方法

KRTreeViewController.swift

extension KRTreeViewController: KRMenuOutlineViewDelegate { 
    func outlineView(_ outlineView: KRMenuOutlineView, menuFor item: Any, event: NSEvent) -> NSMenu? { 
      let menu = NSMenu(title: "Contextual Menu") 
      menu.delegate = self 

      let key = String(utf16CodeUnits: [unichar(NSBackspaceCharacter)], count: 1) as String 
      let deleteMenuItem = menu.addItem(withTitle: "Delete", 
               action: #selector(didClickMenuItem(_:)), 
               keyEquivalent: key) 
      deleteMenuItem.representedObject = myItem 
      deleteMenuItem.target = self 

      return menu 
    } 

    @objc fileprivate func didClickMenuItem(_ menuItem: NSMenuItem) { 
     // ... 
    } 
} 
+0

青いアウトラインが消えるようにしたことはわかりません。コンテキストメニューをどのように実装しましたか? 'NSOutlineView'のデフォルト動作を変更するために何かしましたか? – Willeke

+0

@Willeke私の質問が更新されました。 –

+0

あなた自身のメニューを返す前に 'super.menu(for:event)'を呼び出すことを試みてください。 – Willeke

答えて

1

メニュー:

ストーリーボードを使用してメニューを作成した場合: まず、ストーリーボードに進み、outlineViewを含むviewControllerにメニューを追加します。 @IBOutletにして、後で参照できるようにしてください。 viewDidLoad()のような方法で

、MYMENUはあなたがInterface Builderでまたはコードで作成したもののいずれかとすることができる

outlineView.menu = myMenu 

を呼び出すことにより、outlineViewにメニューを追加します。

今すぐアプリを実行すると、セルの周りに青色の輪郭が表示されます。

問題は、ユーザーがクリックしたセルがわからないことです。 これを修正するには、自分自身をmyMenuのデリゲートとして設定し、NSMenuDelegateプロトコルを採用します。

func menuNeedsUpdate(_ menu: NSMenu) { 
    let row = self.outlineView.clickedRow 

    guard row != -1 else { return } 
    for item in menu.items { 
     item.representedObject = row 
    } 
} 

ここでは、必要な操作を行うことができます。この実装は、各メニュー項目のrepresentObjectとしてrowIndexを設定します。これは静的なアウトラインビュー(バックグラウンドで変更されないもの)とメニューが1レベルだけ深くなる場合にのみ機能することに注意してください。

また、セルによって表されるインデックスまたはオブジェクト(outlineViewが静的でない場合)をローカル変数に格納することもできます。

+0

このソリューションを使用していただきありがとうございます。NSOutlineViewの特定の項目にのみメニューを表示するにはどうしたらよいですか?コードの実装を示す私の質問も更新しました。 –

+0

ストーリーボードを使用してメニューを作成していない場合はどうなりますか?私はアウトラインビューのサブクラスですべてのオーバーライドをコメントアウトしています。青いアウトラインはまだ表示されていません。 –

+0

@Nicolas Miari:コード内にメニューを作成するだけです。たとえば、 'viewDidLoad()'では、メニューを作成し、 'outlineView.menu = myMenu'を呼び出します。残りは上記のとおりでなければなりません。 – mangerlahn

関連する問題