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

发布于 2024-11-14 18:10:00 字数 572 浏览 3 评论 0原文

我需要在更大的滚动窗口内固定大小的 NSTextView。 IB 要求文本视图位于它们自己的 NSScrollView 内部,即使它们的最小/最大尺寸是固定的,因此它们实际上不会滚动。当在文本视图框架内做出触控板手势时(无论它们是否具有焦点),它们都会被文本视图的滚动视图捕获,因此不会发生任何事情。

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

IB 结构如下:

  • 窗户
    • 窗口的内容视图
      • 窗口的大滚动视图(滚动事件的所需目标)
        • 盒子
          • 单独 xib 中的可交换内容视图
            • 文本视图的滚动视图
              • 文本视图
And, yes, the window does scroll correctly when the textviews do not have focus.

I need fixed-size NSTextViews inside a larger scrolling window. IB requires that the textviews be inside their own NSScrollViews, even though their min/max sizes are fixed so that they won’t actually scroll. When trackpad gestures are made within the textview frames (regardless of whether they have focus), they are captured by the textviews’ scrollviews, so nothing happens.

How do I tell the textviews’ scrollviews to pass scroll events up to the window’s main scrollview? (Or perhaps I should be asking how I tell the window’s main scrollview to handle these events itself and not pass them on to its child scrollviews.)

The IB structure is like this:

  • window
    • window’s content view
      • big scrollview for window (desired target for scroll events)
        • box
          • swappable content view in separate xib
            • scrollview for textview
              • textview

And, yes, the window does scroll correctly when the textviews do not have focus.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

╰ゝ天使的微笑 2024-11-21 18:10:00

您不需要创建一个出口“svActive”来跟踪您的超级滚动视图。只需在scrollWheel事件中写入这句话:

[[self nextResponder] scrollWheel:event];

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

You needn't create a outlet "svActive" to track your super scrollview. Just write this sentence in scrollWheel event:

[[self nextResponder] scrollWheel:event];

this will pass the event to next responder in the responder chain.

姜生凉生 2024-11-21 18:10:00

IB 不要求您在 NSScrollView 中有一个文本视图;这只是默认值,因为大多数时候您希望视图滚动。选择 NSTextView 并选择 Layout >取消嵌入对象。请注意,此后,您将无法再在 IB 中移动视图或调整其大小。这似乎是一个错误。

下面是如何将两个 NSTextViews 放入一个 NSScrollView 中的示例。

添加两个相邻的文本视图;在其中添加一些文本,以便您可以看到发生了什么。

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

选择文本视图;选择布局>取消嵌入对象。

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

记下文档视图的高度(此处为 175)。

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

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

完成!滚动效果正如您所期望的那样。

IB does not require you have a text view inside a NSScrollView; this is just the default, because most of the time you'll want your view to scroll. Select the NSTextView and choose Layout > Unembed Objects. Note that after this point, you can no longer move or resize your view in IB. This seems to be a bug.

Here's an example of how to put two NSTextViews in a single NSScrollView.

Add two text views next to each other; put some text in them so you can see what's happening.

Select the views; choose Layout > Embed Objects In > Scroll View. This puts them in a generic NSView inside a NSScrollView.

Select the text views; choose Layout > Unembed Objects.

Turn off the springs and struts (autosizing) for each text view, so they don't resize when you shrink the scroll view.

Take note of the height of the document view (here it's 175).

Make the scroll view smaller. This also resizes the document view (NSView).

Restore the document view to its original size (I set the height back to 175).

Done! Scrolling works as you'd expect.

流年里的时光 2024-11-21 18:10:00

这实在是太尴尬了。经过几周的推迟,我第一次尝试让 NSScrollView 的子类表现得被动——结果证明这是理所当然的。

这里是子类:

h 文件:

#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 文件:

#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 后,我立即向它们提供对主滚动视图的引用:

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

就是这样。就像魅力一样。

This is really embarrassing. After weeks of putting it off, I made a first attempt to get a subclassed NSScrollView to behave passively — and it turned out to be a no brainer.

Here’s the subclass:

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

There’s no need to make outlets for these passive scrollviews; I give them their refs to the main scrollview right after their xibs are assigned as content to the NSBox:

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

That’s it. Works like a charm.

真心难拥有 2024-11-21 18:10:00

我发现如果您尝试直接执行此操作,IB3 和 Xcode4 都会与您对抗,但您可以间接执行此操作。首先,将textview拖出scrollview并删除scrollview。你最终会得到一个孤立的文本视图。我不知道有什么方法可以让 IB 允许您将其放入您的窗口中,但它会在您的 NIB 中。现在,将 IBOutlet 附加到它,并在运行时执行 addSubview: 并调整其框架以将其移动到您希望它位于的任何滚动视图中。

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

I find that IB3 and Xcode4 both fight you if you try to do this directly, but you can do it indirectly. First, drag the textview out of the scrollview and delete the scrollview. You'll wind up with an orphaned textview. I don't know any way to get IB to allow you to put this into your window, but it'll be in your NIB. Now, attach an IBOutlet to it, and at runtime do a addSubview: and adjust its frame to move it into whatever scrollview you wanted it to be in.

In my experience, NIBs are a good thing, but every complex NIB I've ever worked with needed some final rearranging in code.

歌入人心 2024-11-21 18:10:00

根据 @phaibin 的回答,您可以在 Swift 4.2 中执行此操作。

首先,子类 NSScrollView 并覆盖 scrollWheel

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

然后将 ScrollThingy 类(或任何您命名的名称)放在 NSScrollView 上> 包裹在你的 NSTextView 周围。此后父 NSScrollView 将获取滚动事件。

Based on @phaibin's answer, here's how you'd do it in Swift 4.2.

First, subclass NSScrollView and override scrollWheel:

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

Then place the ScrollThingy class (or whatever you name it) on the NSScrollView that is wrapped around your NSTextView. The parent NSScrollView will get the scroll event thereafter.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文