基于视图的NSTableView:拖动时为空/白色标签

时间:2019-03-19 14:04:11

标签: cocoa drag-and-drop nstableview appkit

我设置了一个基于NSTableView的简单视图,该视图是用作标签的简单NSTextField:

  func tableView(_ tv: NSTableView, viewFor tc: NSTableColumn?, row: Int)
       -> NSView?
  {
    let v = (tv.makeView(withIdentifier: viewID, owner: nil) as? NSTextField)
        ?? NSTextField()
    v.isSelectable = false
    v.isEditable   = false
    v.stringValue  = data[row] // [String]
    v.identifier   = viewID
    return v
  }

,然后使用此委托方法启用拖动的项目:

  func tableView(_ tableView: NSTableView, pasteboardWriterForRow row: Int)
       -> NSPasteboardWriting?
  {
    return MyPasteboardItem(value: data[row])
  }

这有效,但是当我拖动该行时,我得到了一个空白的文本字段表示形式:

Empty NSTextField on drag

(在不同的设置中,绘制了图像视图和按钮,但NSTextField也以白色结尾)。

我非常怀疑这是由于NSTextField由TextLayer支持,如果tableview捕获了拖动的视图层次结构的图像,则该TextLayer无法绘制。

什么是解决此问题的好方法?我考虑过实施draw(),但是很好。

更新:如果我做一个自己的NSTextField子类并覆盖draw(),它确实开始起作用:

final class MyTextField : NSTextField {
  override func draw(_ dirtyRect: NSRect) {
    super.draw(dirtyRect)
  }
}

查看视图调试器中的内容表明,NSTextLayer被覆盖时,图层从_NSViewBackingLayer切换到draw。 但是我认为这不是完全合乎需要的吗?有没有更好的方法可以做到这一点?

完整示例:https://gist.github.com/helje5/48728983951ab3362af43b967c554475

2 个答案:

答案 0 :(得分:0)

在文本字段上设置drawsBackground = false可以为我修复此问题。

如果您使用的是xib文件,请取消选中“文本字段”或viewFor:方法中的“绘制背景”,例如:

from bokeh.plotting import figure,show, ColumnDataSource, output_notebook
from bokeh.models import Label
from bokeh.models import CustomJS, HoverTool
import numpy as np
output_notebook()
TOOLS = "xpan,crosshair"

callback_js ="""
        var geometry = cb_data['geometry'];
        var x_data = geometry.x; // current mouse x position in plot coordinates
        var y_data = geometry.y; // current mouse y position in plot coordinates
        console.log("(x,y)=" + x_data+","+y_data); //monitors values in Javascript console
        date_label.text ='x=' + x_data.toFixed(2) + '    ' + 'y=' + y_data.toFixed(2)
        console.log(date_label.text)
    """


s = ColumnDataSource(data = dict(x=[0,1],y=[0,1])) #points of the line
p = figure(x_range=(0,1), y_range=(0,1),tools=TOOLS)
p.line(x='x',y='y',source=s)
date_label = Label(x=30, y=30, x_units='screen', y_units='screen',
                     text='', render_mode='css',
                     border_line_color='white', border_line_alpha=1.0,
                     background_fill_color='white', background_fill_alpha=1.0)

date_label.text = ""
p.add_layout(date_label)
callback=CustomJS(args={'date_label':date_label},code=callback_js)
p.add_tools(HoverTool(tooltips=None, callback=callback))
show(p)

答案 1 :(得分:0)

我最终在NSTextField子类中得到了这个,不确定是否是个好主意:

  override public func draw(_ dirtyRect: NSRect) {
    // This switches from the UXLabel being backed by `NSTextLayer` to
    // `_NSViewBackingLayer`, which may not be desirable.
    // BUT: This enables proper drawing of the Drag&Drop cell.
    super.draw(dirtyRect)
  }