gpt4 book ai didi

cocoa - 如何在NSScrollView中控制NSTableView的绘制?

转载 作者:行者123 更新时间:2023-12-03 17:21:12 25 4
gpt4 key购买 nike

无论水平滚动条位置如何,如何让 NSTableView 始终显示相同的列?在最右边的可见列中,我有自定义单元格 View 。我希望水平滚动条能够控制这些自定义 View 中绘制的内容。垂直滚动应该可以正常工作。

我尝试了多种方法,但都没有成功。例如,我可以通过使表格 View 更宽,或者通过使 ScrollView 认为其文档 View 实际上比实际更宽来控制水平滚动条的旋钮比例。一种方法是继承 NSClipView 并重写 -documentRect,如下所示:

-(NSRect)documentRect {
NSRect rect = [super documentRect];
rect.size.width += [[NSApp delegate] hiddenRangeWidth];
return rect;
}

但是,虽然滚动旋钮看起来应该是这样,并且我可以在不移动表格 View 的情况下向右拖动它,但当我开始向另一个方向滚动时,旋钮会返回到左边缘。我还有一个问题,就是无法让水平滚动条自动出现。原始类也会发生这种情况,而不仅仅是我的自定义剪辑 View 。这些问题可能有关联吗?

我还尝试用自定义 View 替换文档 View ,该自定义 View 充当剪辑 View 和表格 View 之间的代理。它的-drawRect:调用 TableView 的-drawRect:。然而,什么也没有绘制。我想这是因为 TableView 现在没有 super View 。如果 TableView 作为 subview 添加到此代理 View 中,它将随之移动。如何使其在水平轴上静止?

所以,重申一下:

  1. 使表格 View 可滚动,同时始终显示相同的列(无论水平滚动条位置如何)的最佳方法是什么?
  2. 获取滚动条位置和旋钮比例的最佳方法是什么?我应该为 NSClipView 中的 NSViewBoundsDidChangeNotification 添加观察者吗?

最佳答案

我终于通过让 ScrollView 和表格 View 正常运行并添加一个 NSScroller 解决了这个问题。为了更容易隐藏滚动条,我决定使用自动布局并将其添加到 Interface Builder 中。 (对象库不包含滚动条,但您可以添加自定义 View 并将其类设置为 NSScroller。)我将滚动条的高度设置为约束,并在代码中将滚动条和约束绑定(bind)到 socket :

@property (nonatomic, retain) IBOutlet NSScroller *scroller;
@property (nonatomic, unsafe_unretained) IBOutlet NSLayoutConstraint *scrollerHeightConstraint;

现在我可以使滚动条可见或在必要时隐藏它:

if (_zoomedIn) {
_scrollerHeightConstraint.constant = [NSScroller scrollerWidthForControlSize:NSRegularControlSize scrollerStyle:NSScrollerStyleOverlay];
[_scroller setKnobProportion:(_visibleRange / _maxVisibleRange)];
[_scroller setDoubleValue:_visibleRangePosition];
[_scroller setEnabled:YES];
} else {
_scrollerHeightConstraint.constant = 0.0;
}

这里属性visibleRange、maxVisibleRange和visibleRangePosition是可见范围的长度(由滚动条旋钮表示)、总范围(由滚动条槽表示)和可见范围的起点(旋钮位置),分别。可以通过将滚动条的发送操作绑定(bind)到 Interface Builder 中的以下方法来读取这些内容:

- (IBAction)scrollAction:(id)sender {
switch (self.scroller.hitPart) {
case NSScrollerNoPart:
break;
case NSScrollerDecrementPage:
_visibleRangePosition = MAX(_visibleRangePosition - _visibleRange / _maxVisibleRange, 0.0);
self.scroller.doubleValue = _visibleRangePosition;
break;
case NSScrollerIncrementPage:
_visibleRangePosition = MIN(_visibleRangePosition + _visibleRange / _maxVisibleRange, 1.0);
self.scroller.doubleValue = _visibleRangePosition;
break;
case NSScrollerKnob:
case NSScrollerKnobSlot:
_visibleRangePosition = self.scroller.doubleValue;
break;
default:
NSLog(@"unsupported scroller part code %lu", (unsigned long)self.scroller.hitPart);
}
// Make the custom cell views draw themselves here.
}

为了通过手势实现滚动,我们需要在自定义单元格 View 类中实现 -scrollWheel:

- (void)scrollWheel:(NSEvent *)event {
if (event.deltaX != 0.0) {
NSScroller *scroller = appDelegate.scroller;
if (scroller.isEnabled) {
double delta = event.deltaX / (NSWidth(scroller.bounds) * (1.0 - scroller.knobProportion));
scroller.doubleValue = MIN(MAX(scroller.doubleValue - delta, 0.0), 1.0);
}
}
if (event.deltaY != 0.0) {
[self.nextResponder scrollWheel:event];
}
}

我以为我可以将事件传递给滚动条,但显然它不处理该事件。上面的代码似乎无法处理反弹,并且动量滚动并不总是有效。有时旋钮会在运动过程中停止。我相信这与默认情况下 NSScrollerStyleLegacy 的滚动条样式有关。将其设置为 NSScrollerStyleOverlay 需要更改布局,所以我还没有尝试过。

另一个问题是滚动条不会像在 ScrollView 中那样在角落里相互融合(见下文)。也许 NSScrollerStyleOverlay 也能解决这个问题。

corner between the scrollers

关于cocoa - 如何在NSScrollView中控制NSTableView的绘制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26971958/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com