【问题标题】:swift nsoutlineview open always one root elementswift nsoutlineview 总是打开一个根元素
【发布时间】:2017-05-14 16:08:04
【问题描述】:

我在 macOS 上使用 swift 3 和 Xcode 8。 我使用 nsoutlineview(没有 TreeController 并且处于基于 View 的模式)

我想意识到,始终可以打开一个带有子元素的根元素。如果我打开另一个,实际打开的根元素应该关闭,新的将打开。

为此,我尝试了以下代码:

@IBAction func outlineViewClickedRow(_ sender: NSOutlineView) {

for x in (0..<outlineView.numberOfRows) {               
outlineViewn.collapseItem(outlineView.item(atRow: x), collapseChildren: true)
}
outlineView.expandItem(outlineView.item(atRow: outlineView.selectedRow))

}

此 IBAction 已分配给我的 outlineView。 基本上效果不错。

但问题是:

  • 如果我点击一个实际打开的根元素,我的函数将再次打开它。这看起来不专业...
  • 而且这个“点击”功能也适用于不可展开的元素 - 这也不太好

我尝试了这段代码来解决第一点:

if (outlineView.isItemExpanded(outlineView.selectedRow) == true) {
  print("isExpanded")
}

但打印结果永远不会显示。 itItemExpanded 始终为 false ...

第二点同样的问题:

if (outlineView.isExpandable(outlineView.selectedRow) == true) {
  print("isExpandable")
}

是否可扩展总是“假”

【问题讨论】:

  • 没人知道吗?

标签: macos swift3 xcode8


【解决方案1】:

由于您的循环折叠所有项目,一旦完成, selectedRow 项目将始终在循环结束时折叠。如果它碰巧已经展开,这将不可避免地关闭并重新打开选定的项目。 (顺便说一句,您可以通过将 nil 项传递给该函数而不是使用循环来折叠所有节点)

如果您在函数开始时检查 outlineView.isItemExpanded(outlineView.selectedRow),如果它已经展开则直接退出,那应该可以解决您的第一个问题。

对于第二点,您必须在某处设置项目的“isExpandable”属性(您要么没有这样做,要么没有向我们展示)。

我不知道您的 outlineViewClickedRow 函数链接到哪个事件,但您必须确保 outlineView.selectedItem 包含您期望的内容。根据它是哪个事件,在调用 outlineViewClickedRow 之前可能不会更新行选择状态(这可能会导致一些不一致的结果)。

还有一件事,您是否以某种方式禁用或隐藏了大纲视图中的原生扩展图标(三角形)?如果没有,用户将能够展开多个顶部节点,而无需通过您的自动折叠逻辑。

[编辑] 我有时间测试事件行为,并且大纲的选择似乎在调用 IBAction 之前已更新。以下函数应正确执行自动展开和折叠:

@IBAction func outlineClicked(_ sender: Any) 
{
  autoExpandAndCollapse()
}

func autoExpandAndCollapse()
{
   guard let selectedItem = outline.item(atRow:outline.selectedRow),
             outline.parent(forItem: selectedItem) == nil
   else  { return }  

   for level1Index in (0..<outline.numberOfChildren(ofItem: nil)).reversed()
   {
      if let topLevelItem = outline.child(level1Index, ofItem: nil),
         outline.isExpandable(topLevelItem)
      {
         if outline.selectedRow == outline.row(forItem: topLevelItem)
         && !outline.isItemExpanded(topLevelItem)
         { outline.expandItem(topLevelItem)   }
         else 
         { outline.collapseItem(topLevelItem) }
      }
   }
}

顺便说一句,我假设您只想将此应用于顶级节点。如果没有,您可能可以根据您的要求调整逻辑。

[EDIT2] 调整以修复单击具有相同同级索引的子级时关闭父级的错误,简化代码。

【讨论】:

  • 嘿 Alain T. 感谢您的回答。你能把你的解释作为代码示例给我看吗?这对我来说更好学习:)
  • 现在我使用 outlineView.collapseItem(nil) 而不是循环来折叠所有项目。感谢这个提示。我只像这样链接我的大纲视图@IBAction func outlineViewClicked(_ sender: NSOutlineView) { }作为点击事件。
  • 如果我只将此代码放入我的函数print(outlineView.isItemExpanded(outlineView.selectedRow)),如果我展开一个项目,它总是打印“False”
  • 可能 OutlineView 的项目扩展仅在调用 outlineViewClicked() 事件后执行,因此此时项目尚未扩展。
  • 是的,它非常接近,但必须有一个小错误。一些子元素在单击时折叠根元素。一个想法? :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-10
  • 1970-01-01
相关资源
最近更新 更多