#objective-c #cocoa #macos #nswindow
#objective-c #cocoa #macos #nswindow
Вопрос:
У меня есть экземпляр NSWindow, размер которого я изменяю программно (с помощью setFrame). При ее создании размер по умолчанию составлял 50×50. Затем я вызываю setFrame, чтобы изменить ее размер до 350×450: все в порядке, я могу перетаскивать свое окно сколько захочу. Затем, позже в программе, я изменяю ее размер до 1024х768. На данный момент единственная часть строки заголовка, которую я могу перетащить, — это первые 350 пикселей: левая часть. Ничего не произойдет, если я перетащу правую часть. Как будто строка заголовка все еще считает, что окно имеет прежний размер.
Обновлено (добавлен код, который задает фрейм):
void CGLWindowMac::_setSize(int width, int height)
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSRect sFrame;
sFrame = [NSWindow contentRectForFrameRect:[mObjcImp frame] styleMask:[mObjcImp styleMask]];
sFrame.origin.y = sFrame.size.height;
sFrame.origin.y -= height;
sFrame.size.height = height;
sFrame.size.width = width;
sFrame = [NSWindow frameRectForContentRect:sFrame
styleMask:[mObjcImp styleMask]];
NSLog(@"Frame Before setsize: cur Size(%f, %f) ", [mObjcImp frame].size.width, [mObjcImp frame].size.height);
[mObjcImp setFrame:sFrame display:YES animate:NO];
NSLog(@"Frame After setsize: cur Size(%f, %f) new val(%d, %d)", [mObjcImp frame].size.width, [mObjcImp frame].size.height, width, height);
// Tell the application that the window size has change.
onSize(width, height);
[pool release];
}
И вот результат:
2011-05-04 08:50:47.313 ClientProMac[2461:a0f] Frame Before setsize: cur Size(50.000000, 72.000000)
2011-05-04 08:50:47.340 ClientProMac[2461:a0f] Frame After setsize: cur Size(350.000000, 472.000000) new val(350, 450)
2011-05-04 08:50:49.148 ClientProMac[2461:7003] Frame Before setsize: cur Size(350.000000, 472.000000)
2011-05-04 08:50:49.160 ClientProMac[2461:7003] Frame After setsize: cur Size(1024.000000, 790.000000) new val(1024, 768)
Странно то, что если я затем изменю размер окна, перетащив его угол, полная строка заголовка снова станет перетаскиваемой: ошибка исчезнет.
Кто-нибудь видел такое поведение раньше? Что вызывает это и как я могу это исправить.
Спасибо.
Комментарии:
1. Вы должны включить код, который изменяет размер окна и откуда оно вызывается. Возможно, размер окна изменяется в месте, которое вызывает эту ошибку.
2. Джош: Размер экрана, похоже, на это не влияет. У меня была ошибка с двойным дисплеем (оба с разрешением 1280×1024) и с одним дисплеем (1280×1024 и 1024×768).
3. Я согласен с jslap, когда вызывается ваш метод «_setSize»? Скорее всего, вы выполняете изменение размера в то время, когда Windows не может быть безопасно изменена. В опубликованном вами коде нет ничего плохого, поэтому это должно зависеть от того, что произойдет до / после этого.
4. Зачем вы создаете свой собственный пул автоматического выпуска? В этом нет ничего плохого, но это предполагает, что вы находитесь в фоновом потоке или что-то в этом роде? NSWindow вряд ли будет потокобезопасным.
5. ДА. Я делал это в другом потоке. Я думал, что NSWindows потокобезопасны. Я только что сделал это в основном потоке, и она исчезла. @Abhi: Хотите написать ответ, чтобы я мог пометить его как отвеченный?
Ответ №1:
NSWindow (и большинство операций GUI в cocoa) не являются потокобезопасными. Убедитесь, что вы изменяете размер окна в главном потоке.
Например:
NSRect frame = NSMakeRect(42, 42, 420, 420);
dispatch_sync(dispatch_get_main_queue(), ^{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[window setFrame:frame];
[pool release];
});
Если вам нужна обратная совместимость и вы не хотите использовать GCD, вы можете использовать -[NSObject performSelectorOnMainThread:withObject:waitUntilDone:].