4

私の目的: アプリが長いループを処理している間に、決定的な NSProgressIndicator を含むカスタム シートを表示します。シートをドキュメントモーダルではなく、アプリケーションモーダルにしたい。ユーザーはモーダル シートを閉じることができません。アプリがループの処理を完了するまで待つ必要があります。

問題: カスタム シートをウィンドウに取り付けることができません。ウィンドウのタイトル バーがない別のウィンドウとして表示されます (シートのように)。また、ループが終了してもシートは解放されません (閉じません)。

シートとメイン アプリケーション ウィンドウ用に 2 つの個別の nib ファイルがあり、各ウィンドウ用に 2 つのコントローラー クラスもあります。

関連情報は次のとおりです: カスタム シートのコントローラーの実装:

@implementation ProgressSheetController //subclass of NSPanel

-(void)showProgressSheet:(NSWindow *)window
{
    //progressPanel is an IBOutlet to the NSPanel
    if(!progressPanel)
        [NSBundle loadNibNamed:@"ProgressPanel" owner:self];

    [NSApp beginSheet: progressPanel
       modalForWindow: window
        modalDelegate: nil
       didEndSelector: nil
          contextInfo: nil];

    //modalSession is an instance variable
    modalSession = [NSApp beginModalSessionForWindow:progressPanel];

    [NSApp runModalSession:modalSession];
}

-(void)removeProgressSheet
{
    [NSApp endModalSession:modalSession];
    [NSApp endSheet:progressPanel];
    [progressPanel orderOut:nil];
}

//some other methods 
@end

メイン アプリケーション ウィンドウの実装。testFiles メソッドは、ボタンに接続された IBAction です。

@implementation MainWindowViewController //subclass of NSObject

-(IBAction)testFiles:(id)sender;
{
    //filesToTest is a mutable array instance variable
    int count = [filesToTest count];

    float progressIncrement = 100.0 / count;

    ProgressSheetController *modalProgressSheet = [[ProgressSheetController alloc] init];
    [modalProgressSheet showProgressSheet:[NSApp mainWindow]];

    int i,
    for(i=0; i<count; i++)
    {
        //do some stuff with the object at index i in the filesToTest array

        //this method I didn't show in ProgressSheetController.m but I think it's self explanatory
        [modalProgressSheet incrementProgressBarBy:progressIncrement];
    }
    //tear down the custom progress sheet
    [modalProgressSheet removeProgressSheet];
    [modalProgressSheet release];
}
@end

1 つの考え: 正しくサブクラス化していますか? 代わりに NSWindowController を使用する必要がありますか? よろしくお願いします。

4

2 に答える 2

15

グーグルでこの宝石を見つけました。Interface Builder での NSPanel の動作は、IB を使用する場合の新しいウィンドウのデフォルトである「起動時に表示」に設定されていました。何が起こったのかというと、ペン先が読み込まれるとすぐに、ウィンドウが BEFORE に表示されました[NSApp beginSheet:...]。したがって、「起動時に表示」オプションのチェックを外すと問題が解決し、シートがウィンドウに接続されて表示されるようになりました。

于 2010-11-03T20:25:57.973 に答える
1
@implementation ProgressSheetController //subclass of NSPanel

-(void)showProgressSheet:(NSWindow *)window
{
    //progressPanel is an IBOutlet to the NSPanel
    if(!progressPanel)
        [NSBundle loadNibNamed:@"ProgressPanel" owner:self];

あなたの NSPanel は別の NSPanel を所有していますか? 2 番目が進行状況パネルの場合、最初のパネルには何が表示されますか?

代わりに NSWindowController を [サブクラス化] する必要がありますか?

そのように聞こえます。

modalSession = [NSApp beginModalSessionForWindow:progressPanel];

なんで?

[modalProgressSheet showProgressSheet:[NSApp mainWindow]];

メインウィンドウがあることを確認しましたか? mainWindow最も関心のあるウィンドウを返しません。アクティブなウィンドウを返します (これはおそらくキーでもありますが、必ずしもそうとは限りません)。

mainWindowが を返す場合nil、それが問題の原因である可能性があります。

int i,
for(i=0; i<count; i++)
{
    //do some stuff with the object at index i in the filesToTest array

まず、intタイプが間違っています。NSUIntegerNSArray インデックスに使用する必要があります。

第二に、他の何かのためにインデックスが必要でない限り、高速列挙を使用する必要があります。

于 2010-11-01T19:51:48.323 に答える