32

私は、NSCollectionViewマイナーではあるが重大な例外を 1 つ扱っています。コレクション内の選択された項目を取得して強調表示します。

私は Snow Leopard の前にこのすべての作業を行っていましたが、何かが変わったようで、指を置くことができないのでNSCollectionView、基本的なテストに戻って、NSCollectionView を作成するための Apple のドキュメントに従いました。

http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Conceptual/CollectionViews/Introduction/Introduction.html

コレクション ビューは、クイック スタート ガイドに従って正常に動作します。ただし、このガイドでは、 以外の選択については説明しません"There are such features as incorporating image views, setting objects as selectable or not selectable and changing colors if they are selected"

NSCollectionViewこれを例として使用して、コントローラー キーを使用しselectionIndexesてArray Controller を にバインドする次のステップに進みましたNSCollectionViewNSCollectionViewまた、IBで選択できるように設定しました。

NSCollectionViewほとんどの Cocoa UI ビューとは異なり、デフォルトで選択されたハイライトがないように見えます。

したがって、私の問題は実際には関連する問題に帰着しますが、2 つの異なる質問があります。

  1. アイテムの選択をキャプチャするにはどうすればよいですか?
  2. アイテムのハイライトを表示するにはどうすればよいですか?

NSCollectionViewのプログラミング ガイドはほとんどなく、Google を介したほとんどの検索では、Snow Leopard より前の実装が表示されるか、別の XIB ファイルのビューが使用されているようです。

後者 (ビュー用の別の XIB ファイル) の場合、これが前提条件である理由がわかりません。そうしないと、Apple がコレクション ビュー アイテムと同じバンドルにビューを含めなかったのではないかと疑っていたでしょう。

これが「木を見て木が見えない」問題になることはわかっています。一瞬。

いつものように、ありとあらゆる助けが大歓迎です。

更新 1

わかりましたので、選択したアイテムを見つけることを考えましたが、まだハイライトを理解していません。選択した項目を理解することに興味がある場合 (Apple ガイドに従っていると仮定します):

コントローラー (私のテストケースでは App Delegate) に以下を追加しました:

In awakeFromNib

[personArrayController addObserver:self
       forKeyPath:@"selectionIndexes" 
       options:NSKeyValueObservingOptionNew
       context:nil];

新しい方法

-(void)observeValueForKeyPath:(NSString *)keyPath 
                     ofObject:(id)object
                       change:(NSDictionary *)change
                      context:(void *)context
{
    if([keyPath isEqualTo:@"selectionIndexes"])
    {
        if([[personArrayController selectedObjects] count] > 0)
        {
            if ([[personArrayController selectedObjects] count] == 1)
            {
                personModel * pm = (PersonModel *) 
                       [[personArrayController selectedObjects] objectAtIndex:0];
                NSLog(@"Only 1 selected: %@", [pm name]);
            }
            else
            {
                // More than one selected - iterate if need be
            }
        }
    }

非 GC の割り当てを解除することを忘れないでください

-(void)dealloc
{
    [personArrayController removeObserver:self 
                               forKeyPath:@"selectionIndexes"];
    [super dealloc];
}

まだハイライト解像度を探しています...

更新 2

Macatomy のアドバイスを受けましたが、まだ問題がありました。関連するクラスメソッドを投稿して、どこが間違っているかを確認してください。

MyView.h

#import <Cocoa/Cocoa.h>

@interface MyView : NSView {
    BOOL selected;
}

@property (readwrite) BOOL selected;

@end

MyView.m

#import "MyView.h"

@implementation MyView

@synthesize selected;

-(id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
    }
    return self;
}

-(void)drawRect:(NSRect)dirtyRect
{
    NSRect outerFrame = NSMakeRect(0, 0, 143, 104);
    NSRect selectedFrame = NSInsetRect(outerFrame, 2, 2);

    if (selected)
        [[NSColor yellowColor] set];
    else
        [[NSColor redColor] set];

    [NSBezierPath strokeRect:selectedFrame];
}

@end

MyCollectionViewItem.h

#import <Cocoa/Cocoa.h>
@class MyView;

@interface MyCollectionViewItem : NSCollectionViewItem {

}

@end

"MyCollectionViewItem.m*

#import "MyCollectionViewItem.h"
#import "MyView.h"

@implementation MyCollectionViewItem

-(void)setSelected:(BOOL)flag
{

    [(MyView *)[self view] setSelected:flag];
    [(MyView *)[self view] setNeedsDisplay:YES];
}

@end
4

9 に答える 9

34

ハイライトとして別の背景色で十分な場合は、単に NSBox をコレクション アイテム ビューのルート アイテムとして使用できます。選択したハイライト色で NSBox を塗りつぶします。塗りつぶしが機能するように、NSBox を Custom に設定します。NSBox を透明に設定します。

NSBox の透過属性を File Owner(Collection Item) の選択された属性にバインドします透過バインドの値トランスフォーマーを NSNegateBoolean に設定します。

Interface builder のスクリーンショットを添付しようとしましたが、初心者なので拒否されました :-(

于 2011-01-31T15:40:48.180 に答える
26

それほど難しいことではありません。Interface Builder で NSCollectionView の「選択」が有効になっていることを確認します。次に、プロトタイプ ビューに使用している NSView サブクラスで、「selected」というプロパティを宣言します。

@property (readwrite) BOOL selected;

更新されたコードはこちら:(スーパーコールを追加)

NSCollectionViewItem をサブクラス化し、-setSelected をオーバーライドします。

- (void)setSelected:(BOOL)flag
{
    [super setSelected:flag];
    [(PrototypeView*)[self view] setSelected:flag];
    [(PrototypeView*)[self view] setNeedsDisplay:YES];
}

次に、プロトタイプ ビューの drawRect: メソッドにコードを追加して、ハイライトを描画する必要があります。

- (void)drawRect:(NSRect)dirtyRect 
{
    if (selected) {
       [[NSColor blueColor] set];
       NSRectFill([self bounds]);
    }
}

選択するとビューが青で塗りつぶされるだけですが、ハイライトを好きなように描画するようにカスタマイズできます。私は自分のアプリでこれを使用しましたが、うまく機能します。

于 2010-03-29T23:10:56.647 に答える
5

プロトタイプ ビューの NSView をサブクラス化していない場合は、別の方法を使用することもできます。

サブクラス化された NSCollectionViewItem オーバーライドでsetSelected:

- (void)setSelected:(BOOL)selected
{
    [super setSelected:selected];
    if (selected)
        self.view.layer.backgroundColor = [NSColor redColor].CGColor;
    else
        self.view.layer.backgroundColor = [NSColor clearColor].CGColor;
}

そしてもちろん、私の前のすべての賢明な人々が言っ​​たように、Interface Builder で NSCollectionView に対して「選択」が有効になっていることを確認してください。

于 2013-12-09T19:16:15.457 に答える
1

私の場合、オブジェクトの選択を示すために画像(チェックマーク)が必要でした。ImageWell を Collection Item nib にドラッグします。目的の画像を設定し、非表示としてマークします。バインディング インスペクタに移動し、隠し属性をコレクション ビュー アイテムにバインドします。

ここに画像の説明を入力

(私の場合、CollectionViewItem 用に別の nib を作成したので、File の所有者にバインドされます。そうではなく、Item ビューが CollectionView と同じ nib にある場合は、Collection View Item にバインドします)

モデル キー パスを に設定しselected、値トランスフォーマーを に設定しNSNegateBooleanます。これで、個々のセル/アイテムが選択されるたびに画像が表示され、選択が示されます。

Alterの回答に追加します。

NSBox をルート アイテムとして設定します。新しい IB ドキュメント (CollectionItem など) を作成し、NSBox を空の領域にドラッグするだけです。必要に応じて、ボックス内にすべての要素を追加します。File's Owner をクリックし、Custom Class を に設定しNSCollectionViewItemます。

ここに画像の説明を入力

そして、NSCollectionView追加されたペン先で、ペン先名を変更しますCollectionViewItem

ここに画像の説明を入力

NSBox で、残りの要素を にバインドしFiles Ownerます。ラベルの場合、次のようになります。

ここに画像の説明を入力

アルターが彼の回答で述べたようにハイライト色を取得するには、[塗りつぶしの色] オプションで目的の色の組み合わせを設定し、以下のように透明に設定しNSBox、透明属性をバインドします。

ここに画像の説明を入力

Collection View Items を選択すると、ボックスの塗りつぶしの色が表示されるはずです。

于 2014-05-13T09:00:12.353 に答える
0

これは最高でした、どうもありがとう!私はこれに苦労していました!

他の人に明確にするために:

 [(PrototypeView*)[self view] setSelected:flag];
 [(PrototypeView*)[self view] setNeedsDisplay:YES];

PrototypeView* をプロトタイプ クラス名の名前に置き換えます。

于 2011-02-02T20:02:00.093 に答える