每个人都讨论过如何在右键单击中摆脱蓝色轮廓......但是我。
相反,我试图显示蓝色轮廓。
当我右键单击我的大纲视图行时,我没有得到任何轮廓。菜单出现但轮廓不是。
您可以看到下图中看不到蓝色轮廓:
以下是我想要实现的目标。
更新
这是我实施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 :(得分:1)
如何正确显示上下文菜单:
如果您使用故事板创建了菜单:
首先,转到故事板并将菜单添加到包含outlineView的viewController。
然后将其设为@IBOutlet
,以便稍后引用。
在像viewDidLoad()
这样的方法中,通过调用
outlineView.menu = myMenu
其中myMenu可以是您在Interface Builder中创建的,也可以是代码。
您现在可以运行应用程序,并且应该看到单元格周围的蓝色轮廓。
现在的问题是您不知道用户点击了哪个单元格。 要解决此问题,请将自己设置为myMenu的委托并采用NSMenuDelegate协议。
func menuNeedsUpdate(_ menu: NSMenu) {
let row = self.outlineView.clickedRow
guard row != -1 else { return }
for item in menu.items {
item.representedObject = row
}
}
在这里你可以做任何你需要的事情。此实现将rowIndex设置为每个菜单项的representObject。请记住,这只适用于静态outlineViews(在后台不会改变的那些)和只有一层深度的菜单。
您还可以将单元格表示的索引或对象(如果outlineView不是静态的)存储在局部变量中。