用例:
这是一种数据输入方案,用户需要在基于视图的NSTableView的三列中修改数据;数量,项目编号和价格。目的是使用户可以一直握在键盘上,并减少了鼠标在桌子周围进行编辑的需要。
详细的用户界面:
在一行中切换时,下一列应变为选中状态且可编辑,这是(可能是)NSTableView的默认行为。但是,当在最后一列(价格)中进行编辑并跳出时,它应环绕到下一个可用行,第0列(数量),并允许用户继续编辑。
同样,应在一行中支持backtab,并且在第一列(qty)中使用backtab时,应将上一行,最后一列(价格)包裹起来。如果它们位于第0行第0列,则应将其包装到最后一行,最后一列。
因此,基本上,用户应该能够使用Tab键或Backtab键导航和编辑任何行,列。
虽然有几种解决方案,使用keyDown,keyUp,通知等,但很多解决方案是较旧的ObjC代码,而且不是很迅速。
通常情况下,问题应包含某种代码,但由于我有一个可行的解决方案,因此将其作为答案,因此希望它将对将来的读者有所帮助。
问题:
您能否建议一个简单的解决方案,以基于上述参数导航基于视图的表视图。
答案 0 :(得分:0)
首先是对基于NSTableView的视图进行子类设置,像这样设置
class ItemTableView: NSTableView, NSTableViewDataSource, NSTableViewDelegate, NSTextFieldDelegate {
我有一个名为transactionArray的tableView数据源,它保存要在tableView中显示的项目。我还包括了委托方法
func numberOfRows(in tableView: NSTableView) -> Int
和
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView?
在类中,因此它是独立的。
这是处理标签导航的功能
// handle tab and backtab in an editable view based tableView subclass
// will also scroll the edited cell into view when tabbing into view that are outside the viewable area
//ref https://developer.apple.com/documentation/appkit/nscontroltexteditingdelegate/1428898-control
func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
print(#function)
//let whichControl = control //this is the tableView textField where the event
// happened. In this case it will only be the
// NSTableCellView located within this tableView
let whichSelector = commandSelector //this is the event; return, tab etc
//these are the keypresses we are interested in, tab, backtab, return/enter.
let tabSelector = #selector( insertTab(_:) )
//let returnSelector = #selector( insertNewline(_:) ) //use this if you need
//custom return/enter handling
let backtabSelector = #selector( insertBacktab(_:) )
//if the user hits tab, need to determine where they are. If it's in the last
// column, need to see if there is another row and if so, move to next
// row, col 0 and go into edit. If it's a backtab in the first column, need
// to wrap back to the last row, last col and edit
if whichSelector == tabSelector {
let row = self.row(for: textView)
let col = self.column(for: textView)
let lastCol = self.tableColumns.count - 1
if col == lastCol { //we tabbed forward in the last column
let lastRow = self.transactionArray.count - 1
var rowToEdit: Int!
if row < lastRow { //if we are above the last row, go to the next row
rowToEdit = row + 1
} else { //if we are at the last row, last col, tab around to the first row, first col
rowToEdit = 0
}
self.editColumn(0, row: rowToEdit, with: nil, select: true)
self.scrollRowToVisible(rowToEdit)
return true //tell the OS we handled the key binding
} else {
self.scrollColumnToVisible(col + 1)
}
} else if whichSelector == backtabSelector {
let row = self.row(for: textView)
let col = self.column(for: textView)
if col == 0 { //we tabbed backward in the first column
let lastCol = self.tableColumns.count - 1
var rowToEdit: Int!
if row > 0 { //and we are after row zero, back up a row and edit the last col
rowToEdit = row - 1
} else { // we are in row 0, col 0 so wrap forward to the last col, last row
rowToEdit = self.transactionArray.count - 1
}
self.editColumn(lastCol, row: rowToEdit, with: nil, select: true)
self.scrollRowToVisible(rowToEdit)
self.scrollColumnToVisible(lastCol)
return true
} else {
self.scrollColumnToVisible(col - 1)
}
}
return false //let the OS handle the key binding
}