响应基于视图的表格视图中文本字段中的鼠标事件
我在 NSOutlineView
内的自定义视图内有文本字段。编辑其中一个单元格需要单击一下、暂停一下,然后再单击一次。第一次单击选择表视图行,第二次单击将光标绘制在字段中。双击单元格可以在基于单元格的表格视图中进行编辑,但只能选择该行。
我想要的行为:一键更改选择并编辑。
我需要重写什么才能获得此行为?
我读过其他一些帖子:
NSTextField
flyweight模式似乎不适用于基于视图的表格视图,其中单元格视图都是从笔尖实例化的。- 我尝试对
NSTextField
进行子类化,例如 此解决方案描述了,但未调用我重写的mouseDown
方法。覆盖awakeFromNib
和viewWillDraw
(在这篇文章) 被调用。当然,如果我将文本字段放在表视图之外的某个位置,就会调用 mouseDown 。
相比之下,我的单元格视图中的 NSSegmentedControl
无需先选择行即可更改其值。
这是根据已接受的响应改编的工作解决方案:
在大纲视图子类中:
-(void)mouseDown:(NSEvent *)theEvent {
[super mouseDown:theEvent];
// Forward the click to the row's cell view
NSPoint selfPoint = [self convertPoint:theEvent.locationInWindow fromView:nil];
NSInteger row = [self rowAtPoint:selfPoint];
if (row>=0) [(CellViewSubclass *)[self viewAtColumn:0 row:row makeIfNecessary:NO]
mouseDownForTextFields:theEvent];
}
在表格单元格视图子类中:
// Respond to clicks within text fields only, because other clicks will be duplicates of events passed to mouseDown
- (void)mouseDownForTextFields:(NSEvent *)theEvent {
// If shift or command are being held, we're selecting rows, so ignore
if ((NSCommandKeyMask | NSShiftKeyMask) & [theEvent modifierFlags]) return;
NSPoint selfPoint = [self convertPoint:theEvent.locationInWindow fromView:nil];
for (NSView *subview in [self subviews])
if ([subview isKindOfClass:[NSTextField class]])
if (NSPointInRect(selfPoint, [subview frame]))
[[self window] makeFirstResponder:subview];
}
I have text fields inside a custom view inside an NSOutlineView
. Editing one of these cells requires a single click, a pause, and another single click. The first single click selects the table view row, and the second single click draws the cursor in the field. Double-clicking the cell, which lets you edit in a cell-based table view, only selects the row.
The behavior I want: one click to change the selection and edit.
What do I need to override to obtain this behavior?
I've read some other posts:
- The
NSTextField
flyweight pattern wouldn't seem to apply to view-based table views, where the cell views are all instantiated from nibs. - I tried subclassing
NSTextField
like this solution describes, but my overriddenmouseDown
method is not called. OverriddenawakeFromNib
andviewWillDraw
(mentioned in this post) are called. Of coursemouseDown
is called if I put the text field somewhere outside a table view.
By comparison, a NSSegmentedControl
in my cell view changes its value without first selecting the row.
Here's the working solution adapted from the accepted response:
In outline view subclass:
-(void)mouseDown:(NSEvent *)theEvent {
[super mouseDown:theEvent];
// Forward the click to the row's cell view
NSPoint selfPoint = [self convertPoint:theEvent.locationInWindow fromView:nil];
NSInteger row = [self rowAtPoint:selfPoint];
if (row>=0) [(CellViewSubclass *)[self viewAtColumn:0 row:row makeIfNecessary:NO]
mouseDownForTextFields:theEvent];
}
In table cell view subclass:
// Respond to clicks within text fields only, because other clicks will be duplicates of events passed to mouseDown
- (void)mouseDownForTextFields:(NSEvent *)theEvent {
// If shift or command are being held, we're selecting rows, so ignore
if ((NSCommandKeyMask | NSShiftKeyMask) & [theEvent modifierFlags]) return;
NSPoint selfPoint = [self convertPoint:theEvent.locationInWindow fromView:nil];
for (NSView *subview in [self subviews])
if ([subview isKindOfClass:[NSTextField class]])
if (NSPointInRect(selfPoint, [subview frame]))
[[self window] makeFirstResponder:subview];
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
有同样的问题。经过一番努力,当我为
Highlight 选择
IB 中表格视图的选项!None
而不是默认的Regular
(其他选项是Source List
)时,它神奇地起作用了另一种选择是 https://stackoverflow.com/a/13579469/804616 的解决方案,它似乎更具体但与此相比有点hacky。
Had the same problem. After much struggle, it magically worked when I selected
None
as against the defaultRegular
(other option isSource List
) for theHighlight
option of the table view in IB!Another option is the solution at https://stackoverflow.com/a/13579469/804616, which appears to be more specific but a little hacky compared to this.
我会尽力回报恩惠 ...子类
NSOutlineView
并覆盖-mouseDown:
如下所示:I'll try to return the favor... Subclass
NSOutlineView
and override-mouseDown:
like so:您确实想重写 validateProposeFirstResponder 并允许根据您的逻辑创建(或不创建)特定的第一响应者。 NSTableView 中的实现(有点)像这样(我将其重写为伪代码):
You really want to override validateProposedFirstResponder and allow a particular first responder to be made (or not) depending on your logic. The implementation in NSTableView is (sort of) like this (I'm re-writing it to be pseudo code):
我编写了以下内容来支持当您有一个包含多个文本字段的更复杂的 NSTableViewCell 或文本字段不占据整个单元格的情况。这里有一个翻转 y 值的技巧,因为当您在 NSOutlineView 或 NSTableView 和 NSTableCellViews 之间切换时,坐标系会翻转。
I wrote the following to support the case for when you have a more complex NSTableViewCell with multiple text fields or where the text field doesn't occupy the whole cell. There a trick in here for flipping y values because when you switch between the NSOutlineView or NSTableView and it's NSTableCellViews the coordinate system gets flipped.
只是想指出,如果您想要的只是编辑(即在没有选择的表格中),则覆盖
-hitTest:
似乎更简单并且更像 Cocoa:Just want to point out that if all that you want is editing only (i.e. in a table without selection), overriding
-hitTest:
seems to be simpler and a more Cocoa-like:这是 @Dov 答案的 swift 4.2 版本:
Here is a swift 4.2 version of @Dov answer: