Cocoa - 从笔尖加载视图并将其作为子视图显示在 NSView 容器中

发布于 2024-09-06 09:41:43 字数 3005 浏览 1 评论 0原文

我之前已经问过这个问题,但问题本身和其中的所有信息可能有点令人困惑,而且我想要得到的结果有点复杂。所以我开始了一个新的干净测试项目来处理我目前有兴趣了解的部分。

所以我想要的基本上是这样的:我有一个视图容器(继承 NSView)。在里面,我想放置一些图像,但不仅仅是简单的 NSImage 或 NSImageView,而是一些自定义视图(也继承 NSView),它本身包含一个文本字段和一个 NSImageView。我称之为“图像持有者”,它位于一个单独的 nib 文件中(我使用这种方法是因为我在 Apple SAmple 应用程序 COCOA SLIDES 之后指导自己)。 到目前为止我得到的结果是一些东西,但不是我所期望的。我想我一定在界面生成器中做错了什么(没有连接正确的东西),但我希望有更多专业知识的人能够启发我。

下面我将尝试放置到目前为止我拥有的所有代码:

//ImagesContainer.h
#import <Cocoa/Cocoa.h>


@interface ImagesContainer : NSView {

}
@end
//ImagesContainer.m
#import "ImagesContainer.h"
#import "ImageHolderView.h"
#import "ImageHolderNode.h"
@class ImageHolderView;
@class ImageHolderNode;
@implementation ImagesContainer

- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
  //create some subviews
  for(int i=0;i<3;i++){
   ImageHolderNode *node = [[ImageHolderNode alloc] init];
   [self addSubview:[node rootView]];
  }
    }
 NSRunAlertPanel(@"subviews", [NSString stringWithFormat:@"%d",[[self subviews] count]], @"OK", NULL, NULL);
    return self;
}

- (void)drawRect:(NSRect)dirtyRect {
    // Drawing code here.

 [[NSColor blackColor] set];
 NSRectFill(NSMakeRect(0,0,dirtyRect.size.width,dirtyRect.size.height));
 int i=1;
 for(NSView *subview in [self subviews]){
  [subview setFrameOrigin:NSMakePoint(10*i, 10)];
  i++;
 }
}

@end

//ImageHolderView.h
#import <Cocoa/Cocoa.h>


@interface ImageHolderView : NSView {
 IBOutlet NSImageView *imageView;
}
@end
//ImageHolderVIew.m
#import "ImageHolderView.h"


@implementation ImageHolderView
- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {

    }
    return self;
}

- (void)drawRect:(NSRect)dirtyRect {
    // Drawing code here.
 [[NSColor blueColor]set];
 NSRectFill(NSMakeRect(10,10, 100, 100));
 //[super drawRect:dirtyRect];
}
@end

//ImageHolderNode.h
#import <Cocoa/Cocoa.h>
@class ImageHolderView;

@interface ImageHolderNode : NSObject {
 IBOutlet ImageHolderView *rootView;
 IBOutlet NSImageView *imageView;
}
-(NSView *)rootView;
-(void)loadUIFromNib;
@end

//ImageHolderNode.m
#import "ImageHolderNode.h"


@implementation ImageHolderNode

-(void)loadUIFromNib {
 [NSBundle loadNibNamed:@"ImageHolder" owner: self];
}
-(NSView *)rootView {
 if( rootView == nil) {
  NSRunAlertPanel(@"Loading nib", @"...", @"OK", NULL, NULL);
  [ self loadUIFromNib];
 }
 return rootView;
}

@end

我的 nib 文件是:

  1. MainMenu.xib
  2. ImageHolder.xib

  3. MainMenu 是我启动时生成的 xib新项目。

  4. ImageHolder 看起来像这样: 图像链接

我将尝试提及到目前为止在 xib ImageHolder 中的连接:

文件的所有者 - 具有 ImageHolderNode 类 ImageHolder.xib 的主视图具有 ImageHolderView 类,

因此要恢复,我得到的结果是视图容器中的 3 个蓝色矩形,但我似乎无法使其显示从 ImageHolder.xib 加载的视图

如果有人想要看看 CocoaSlides 示例应用程序,它在苹果开发者页面上(不幸的是,我不允许发布超过 1 个链接:))

I've asked about this earlier but the question itself and all the information in it might have been a little confusing, plus the result i want to get is a little more complicated. So i started a new clean test project to handle just the part that im interested to understand for the moment.

So what i want, is basically this: i have a view container (inherits NSView). Inside, i want to place some images, but not just simple NSImage or NSImageView, but some custom view (inherits NSView also), which itself contains a textfield and an NSImageView. This 'image holder' as i called it, is in a separate nib file (im using this approach since i am guiding myself after an Apple SAmple Application, COCOA SLIDES).
The results i got so far, is something but not what i am expecting. Im thinking i must be doing something wrong in the Interface Builder (not connecting the proper thingies), but i hope someone with more expertise will be able to enlighten me.

Below i'll try to put all the code that i have so far:

//ImagesContainer.h
#import <Cocoa/Cocoa.h>


@interface ImagesContainer : NSView {

}
@end
//ImagesContainer.m
#import "ImagesContainer.h"
#import "ImageHolderView.h"
#import "ImageHolderNode.h"
@class ImageHolderView;
@class ImageHolderNode;
@implementation ImagesContainer

- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
  //create some subviews
  for(int i=0;i<3;i++){
   ImageHolderNode *node = [[ImageHolderNode alloc] init];
   [self addSubview:[node rootView]];
  }
    }
 NSRunAlertPanel(@"subviews", [NSString stringWithFormat:@"%d",[[self subviews] count]], @"OK", NULL, NULL);
    return self;
}

- (void)drawRect:(NSRect)dirtyRect {
    // Drawing code here.

 [[NSColor blackColor] set];
 NSRectFill(NSMakeRect(0,0,dirtyRect.size.width,dirtyRect.size.height));
 int i=1;
 for(NSView *subview in [self subviews]){
  [subview setFrameOrigin:NSMakePoint(10*i, 10)];
  i++;
 }
}

@end

//ImageHolderView.h
#import <Cocoa/Cocoa.h>


@interface ImageHolderView : NSView {
 IBOutlet NSImageView *imageView;
}
@end
//ImageHolderVIew.m
#import "ImageHolderView.h"


@implementation ImageHolderView
- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {

    }
    return self;
}

- (void)drawRect:(NSRect)dirtyRect {
    // Drawing code here.
 [[NSColor blueColor]set];
 NSRectFill(NSMakeRect(10,10, 100, 100));
 //[super drawRect:dirtyRect];
}
@end

//ImageHolderNode.h
#import <Cocoa/Cocoa.h>
@class ImageHolderView;

@interface ImageHolderNode : NSObject {
 IBOutlet ImageHolderView *rootView;
 IBOutlet NSImageView *imageView;
}
-(NSView *)rootView;
-(void)loadUIFromNib;
@end

//ImageHolderNode.m
#import "ImageHolderNode.h"


@implementation ImageHolderNode

-(void)loadUIFromNib {
 [NSBundle loadNibNamed:@"ImageHolder" owner: self];
}
-(NSView *)rootView {
 if( rootView == nil) {
  NSRunAlertPanel(@"Loading nib", @"...", @"OK", NULL, NULL);
  [ self loadUIFromNib];
 }
 return rootView;
}

@end

My nib files are:

  1. MainMenu.xib
  2. ImageHolder.xib

  3. MainMenu is the xib that is generated when i started the new project.

  4. ImageHolder looks something like this:
    image link

I'll try to mention the connections so far in the xib ImageHolder :

File's Owner - has class of ImageHolderNode
The main view of the ImageHolder.xib , has the class ImageHolderView

So to resume, the results im getting are 3 blue rectangles in the view container, but i cant seem to make it display the view loaded from the ImageHolder.xib

If anyone wants to have a look at the CocoaSlides sample application , its on apple developer page ( im not allowed unfortunately to post more than 1 links :) )

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

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

发布评论

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

评论(1

遗失的美好 2024-09-13 09:41:43

确切地说,这不是一个答案,因为不清楚您在问什么。

您创建了一个视图(class 'ImagesContainer')。我们称之为imagesContainerView

ImagesContainerView 创建 3 个对象(类“ImageHolderNode”)。 ImagesContainerView 向每个 imageHolderNode 询问其 -rootView (可能是“ImageHolderView”),并将返回值添加到其视图层次结构中。

ImagesContainerView 丢弃(但泄漏)每个 imageHolderNode。

所以视图层次结构看起来像:-

+ imagesContainerView
    + imageHolderView1 or maybe nil
    + imageHolderView2 or maybe nil
    + imageHolderView3 or maybe nil

这是您所期望的吗?

那么您在哪里调用 -(void)loadUIFromNib 并等待笔尖加载?
在某些代码中您没有显示?

一般来说,一步一步进行,让每一步都发挥作用。

NSAssert 是你的朋友。尝试一下,而不是错误地使用警报面板和日志记录来进行调试。 IE。

ImageHolderNode *node = [[[ImageHolderNode alloc] init] autorelease];
NSAssert([node rootView], @"Eek! RootView is nil.");
[self addSubview:[node rootView]];

一个视图当然应该画一些东西。 TextView 绘制文本,ImageView 绘制图像。如果您需要绘制 Cocoa 提供的文本、图像、表格等以外的内容,您应该继承 NSView 。

您应该根据应用程序的需要在 nib 中排列视图,或者如果您需要从多个 nib 组装视图,则应使用 viewController 或 windowController。这就是他们的目的。

编辑

Interface Builder连接

如果RootView不为零,那么看起来您已经正确连接了连接,但您说您不清楚所以..

确保IB窗口设置为列表视图,以便您可以看到笔尖的内容清楚。
“文件所有者”代表将加载笔尖的对象,对吧?在你的例子中 ImageHolderNode。
按住 Control 单击文件的所有者,除其他外,您还可以看到它的出口。当 ImageHolderNode 加载笔尖时,控制从插座拖动(在列表视图中)到要设置为实例变量的对象。我知道你已经知道这一点,但除此之外别无他法。

Doh

你究竟希望看到什么?一个空的 imageView?好吧,那看起来没什么。空文本字段?这看起来也没什么。将插座连接到您的文本字段和图像视图,并在它们上设置一些内容。

Not an answer, exactly, as it is unclear what you are asking..

You make a view (class 'ImagesContainer'). Lets call it imagesContainerView.

ImagesContainerView makes 3 Objects (class 'ImageHolderNode'). ImagesContainerView asks each imageHolderNode for it's -rootView (maybe 'ImageHolderView') and adds the return value to it's view-heirarchy.

ImagesContainerView throws away (but leaks) each imageHolderNode.

So the view heirachy looks like:-

+ imagesContainerView
    + imageHolderView1 or maybe nil
    + imageHolderView2 or maybe nil
    + imageHolderView3 or maybe nil

Is this what you are expecting?

So where do you call -(void)loadUIFromNib and wait for the nib to load?
In some code you are not showing?

In general, progress a step at a time, get each step working.

NSAssert is your friend. Try it instead of mis-using alert panels and logging for debugging purposes. ie.

ImageHolderNode *node = [[[ImageHolderNode alloc] init] autorelease];
NSAssert([node rootView], @"Eek! RootView is nil.");
[self addSubview:[node rootView]];

A view of course, should draw something. TextViews draw text and ImageViews draw images. You should subclass NSView if you need to draw something other than text, images, tables, etc. that Cocoa provides.

You should arrange your views as your app requires in the nib or using a viewController or a windowController if you need to assemble views from multiple nibs. Thats what they are for.

EDIT

Interface Builder Connections

If RootView isn't nil then it seems like you have hooked up your connections correctly, but you say you are unclear so..

Make sure the IB window is set to List view so you can see the contents of you nib clearly.
'File's Owner' represents the object that is going to load the nib, right? In your case ImageHolderNode.
Control Click on File's owner and amongst other things you can see it's outlets. Control drag (in the list view) from an outlet to the object you want to be set as the instance var when the nib is loaded by ImageHolderNode. I know you know this already, but there is nothing else to it.

Doh

What exactly are you expecting to see ? An empty imageView? Well, that will look like nothing. An empty textfield? That too, will look like nothing. Hook up an outlet to your textfield and imageView and set some content on them.

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