如何将滚动事件传递给父NSScrollView

时间:2011-06-09 17:40:29

标签: cocoa nsscrollview nsevent

我需要在更大的滚动窗口中使用固定大小的NSTextViews。 IB要求textviews位于他们自己的NSScrollViews中,即使他们的最小/最大大小是固定的,以便它们实际上不会滚动。当在textview框架内制作触控板手势时(无论它们是否具有焦点),它们都会被textview的scrollview捕获,因此没有任何反应。

如何告诉textviews的scrollviews将滚动事件传递到窗口的主滚动视图? (或许我应该问我如何告诉窗口的主滚动视图本身处理这些事件而不是将它们传递给它的子滚动视图。)

IB结构是这样的:

  • 窗口
    • 窗口的内容视图
      • 窗口的大滚动视图(滚动事件的所需目标)
          • 单独的xib中的可交换内容视图
            • 用于textview的scrollview
              • 的TextView
并且,是的,当文本视图具有焦点时,窗口会正确滚动。

5 个答案:

答案 0 :(得分:11)

您无需创建插座“svActive”来跟踪您的超级滚动视图。只需在scrollWheel事件中写下这句话:

[[self nextResponder] scrollWheel:event];

这会将事件传递给响应者链中的下一个响应者。

答案 1 :(得分:7)

IB不要求您在NSScrollView内有文字视图;这只是默认设置,因为大多数情况下您都希望视图滚动。选择NSTextView,然后选择布局> Unembed Objects。请注意,在此之后,您无法再在IB中移动视图或调整视图大小。这似乎是一个错误。

以下是如何将两个NSTextViews放入单个NSScrollView的示例。

彼此相邻添加两个文本视图;在其中加入一些文字,这样你就可以看到发生了什么。

选择视图;选择布局>在>中嵌入对象滚动视图。这会将它们置于NSView内的通用NSScrollView

选择文字视图;选择布局> Unembed Objects。

关闭每个文本视图的弹簧和支柱(自动调整大小),这样在缩小滚动视图时它们不会调整大小。

记下文档视图的高度(这里是175)。

使滚动视图变小。这也调整了文档视图的大小(NSView)。

将文档视图恢复为原始大小(我将高度设置为175)。

完成!滚动按预期工作。

答案 2 :(得分:3)

这真是令人尴尬。经过几周的推迟,我首次尝试让一个子类NSScrollView被动地行动 - 结果证明这是一个没脑子的事。

这是子类:

h file:

#import <Cocoa/Cocoa.h>

@interface ScrollViewPassive : NSScrollView {

// This property is assigned a ref to windowController’s main scrollview.
NSScrollView *svActive; 

}

@property (nonatomic, retain) NSScrollView *svActive;

@end

m file:

#import "ScrollViewPassive.h"

@implementation ScrollViewPassive

@synthesize svActive;

// Pass any gesture scrolling up to the main, active scrollview.
- (void)scrollWheel:(NSEvent *)event {
    [svActive scrollWheel:event];
}

@end

没有必要为这些被动滚动视图制作出口;在将xib作为内容分配给NSBox后,我将它们的引用提供给主scrollview:

    [self.boxDisplayingTextViews setContentView:self.subviewCtllr1.view];
    // A textview's superview's superview is its scrollview:    
    ((ScrollViewPassive *)[[self.subviewCtllr1.textview1 superview] superview]).svActive = self.scrollviewMain;

就是这样。像魅力一样。

答案 3 :(得分:1)

我发现如果你试图直接这样做,IB3和Xcode4都会打你,但你可以间接地做到这一点。首先,将textview拖出scrollview并删除scrollview。你最终会得到一个孤立的textview。我不知道有什么方法可以让IB把它放到你的窗口,但它会在你的NIB中。现在,将IBOutlet附加到它,并在运行时执行addSubview:并调整其帧以将其移动到您希望它所在的任何滚动视图中。

根据我的经验,NIB是一件好事,但是我曾经使用过的每一个复杂的NIB都需要在代码中进行最后的重新排列。

答案 4 :(得分:0)

根据@phaibin的回答,这是您在 Swift 4.2 中执行的操作。

首先,子类NSScrollView并覆盖scrollWheel

class ScrollThingy: NSScrollView{
  override func scrollWheel(with event: NSEvent) {
    self.nextResponder?.scrollWheel(with: event)
  }
}

然后将ScrollThingy类(或任何您命名的类)放在NSScrollView周围的NSTextView上。父级NSScrollView之后将获得滚动事件。