18

以前にこの質問をしたことがありますが、解決策にあまり満足していません。

NSTableView のサイズを自動的に調整する

、または にを表示NSTableViewしたい。 これで、ウィンドウのサイズがテーブル ビューに合わせて調整されます。NSPopoverNSWindow

Xcode と同じように:


ここに画像の説明を入力 ここに画像の説明を入力


これは Auto Layout を使用すると非常に簡単です。内部ビューをスーパー ビューにピン留めするだけです。

私の問題は、テーブル ビューの最適な高さがわからないことです。次のコードは、使用可能なすべての行を列挙しますが、テーブル ビューには区切り記号やテーブル ヘッドなどの他の要素があるため、正しい値を返しません。

- (CGFloat)heightOfAllRows:(NSTableView *)tableView {
    CGFloat __block height;
    [tableView enumerateAvailableRowViewsUsingBlock:^(NSTableRowView *rowView, NSInteger row) {
        // tried it with this one
        height += rowView.frame.size.height;

        // and this one
        // height += [self tableView:nil heightOfRow:row];
    }];

    return height;
}

1. 質問

どうすればこれを修正できますか? テーブル ビューの必要な高さを正しく計算するにはどうすればよいですか。

2. 質問

このコードはどこで実行すればよいですか?
テーブルビューがそれ自体を処理する必要があることは間違いないため、これをコントローラーに実装したくありません。
また、役立つデリゲート メソッドも見つかりませんでした。

だから私はあなたがサブクラス化できれば最善だと思っNSTableViewた.
だから私の質問2、どこに実装するのですか?


動機

間違いなく賞金に値する

4

5 に答える 5

11

この回答は、macOS 10.10 以降を対象とする Swift 4 向けです。

1.答え

テーブルビューを使用してfittingSize、ポップオーバーのサイズを計算できます。

tableView.needsLayout = true
tableView.layoutSubtreeIfNeeded()

let height = tableView.fittingSize.height

2.答え

そのコードをView Controllerの外に移動したいというあなたの希望は理解していますが、テーブルビュー自体はアイテムの数(委譲のみ)やモデルの変更について何も知らないので、それをView Controllerに入れます。macOS 10.10 以降、ポップオーバー内でサイズを設定できpreferredContentSizeます。NSViewController

func updatePreferredContentSize() {
    tableView.needsLayout = true
    tableView.layoutSubtreeIfNeeded()

    let height = tableView.fittingSize.height
    let width: CGFloat = 320

    preferredContentSize = CGSize(width: width, height: height)
}

私の例では、固定幅を使用していますが、計算された幅を使用することもできます (まだテストしていません)。

データ ソースが変更されるたびに、および/またはポップオーバーを表示しようとしているときに、update メソッドを呼び出す必要があります。

これで問題が解決することを願っています!

于 2017-05-21T04:55:59.983 に答える
3

Xcode の Interface Builder は、NSTableView を NSScrollView に自動的に配置します。NSScrollView は、ヘッダーが実際に配置されている場所です。ウィンドウのベース ビューとして NSScrollView を作成し、それに NSTableView を追加します。

NSScrollView * scrollView = [[NSScrollView alloc]init];
[scrollView setHasVerticalScroller:YES];
[scrollView setHasHorizontalScroller:YES];
[scrollView setAutohidesScrollers:YES];
[scrollView setBorderType:NSBezelBorder];
[scrollView setTranslatesAutoresizingMaskIntoConstraints:NO];

NSTableView * table = [[NSTableView alloc] init];
[table setDataSource:self];
[table setColumnAutoresizingStyle:NSTableViewUniformColumnAutoresizingStyle];
[scrollView setDocumentView:table];

//SetWindow's main view to scrollView

これで、scrollView の contentView に問い合わせて、NSScrollView のサイズを確認できます

NSRect rectOfFullTable = [[scrollView contentView] documentRect];

NSTableView は NSScrollView 内にあるため、NSTableView には、ヘッダーのサイズを見つけるために使用できる headerView があります。

NSScrollView をサブクラス化して、reflectScrolledClipView: メソッドをオーバーライドすることにより、テーブルのサイズが変更されたとき (ヘッダー + 行) にスーパービューを更新することができます。

于 2013-01-08T18:18:32.383 に答える
2

私の解決策があなたが持っているものよりも優れているかどうかはわかりませんが、とにかく提供したいと思いました. これを印刷ビューで使用します。自動レイアウトを使用していません。バインディングでのみ機能します。データ ソースを操作するには調整が必要です。

これを機能させるにはひどいハックがあることがわかります。慎重に計算した値に 0.5 を加算するだけです。

これはスペーシングを考慮に入れていますが、私が表示していないヘッダーは考慮していません。ヘッダーを表示している場合は、それを-tableView:heightOfRow:メソッドに追加できます。

NSTableViewサブクラスまたはカテゴリ:

- (void) sizeHeightToFit {
    CGFloat height = 0.f;
    if ([self.delegate respondsToSelector:@selector(tableView:heightOfRow:)]) {
        for (NSInteger i = 0; i < self.numberOfRows; ++i)
            height = height +
                     [self.delegate tableView:self heightOfRow:i] +
                     self.intercellSpacing.height;
    } else {
        height = (self.rowHeight + self.intercellSpacing.height) *
                 self.numberOfRows;
    }

    NSSize frameSize = self.frame.size;
    frameSize.height = height;
    [self setFrameSize:frameSize];
}

テーブル ビュー デリゲートの場合:

// Invoke bindings to get the cell contents
// FIXME If no bindings, use the datasource
- (NSString *) stringValueForRow:(NSInteger) row column:(NSTableColumn *) column {
    NSDictionary *bindingInfo = [column infoForBinding:NSValueBinding];

    id object = [bindingInfo objectForKey:NSObservedObjectKey];
    NSString *keyPath = [bindingInfo objectForKey:NSObservedKeyPathKey];

    id value = [[object valueForKeyPath:keyPath] objectAtIndex:row];

    if ([value isKindOfClass:[NSString class]])
        return value;
    else
        return @"";
}

- (CGFloat) tableView:(NSTableView *) tableView heightOfRow:(NSInteger) row {

    CGFloat result = tableView.rowHeight;

    for (NSTableColumn *column in tableView.tableColumns) {
        NSTextFieldCell *dataCell = column.dataCell;
        if (![dataCell isKindOfClass:[NSTextFieldCell class]]) continue;

        // Borrow the prototype cell, and set its text
        [dataCell setObjectValue:[self stringValueForRow:row column:column]];

        // Ask it the bounds for a rectangle as wide as the column
        NSRect cellBounds = NSZeroRect;
        cellBounds.size.width = [column width]; cellBounds.size.height = FLT_MAX;
        NSSize cellSize = [dataCell cellSizeForBounds:cellBounds];

        // This is a HACK to make this work.
        // Otherwise the rows are inexplicably too short.
        cellSize.height = cellSize.height + 0.5;

        if (cellSize.height > result)
            result = cellSize.height;
    }

    return result;
}
于 2013-01-17T15:14:45.107 に答える
-2

NSTableView-[NSTableView frame] がNSScrollViewに埋め込まれているだけですが、フルサイズです。

于 2013-01-16T14:52:15.157 に答える