麦克鲁比Interface Builder:如何显示、然后关闭、然后再次显示窗口
我对 MacRuby 和 Cocoa 非常精通,所以在回答时请记住这一点 - 我需要很多细节和解释。 :)
我已经建立了一个简单的项目,其中有 2 个窗口,这两个窗口都是用 Interface Builder 构建的。第一个窗口是使用表视图的简单帐户列表。它在表格下方有一个“+”按钮。当我单击 + 按钮时,我想显示“添加新帐户”窗口。
我还有一个 AccountsController < NSWindowController
和一个 AddNewAccountController
NSWindowController
类,设置为这些窗口的委托,连接适当的按钮单击方法,以及引用所需窗口的出口。
当我单击“帐户”窗口中的“+”按钮时,我会触发以下代码:
@add_account.center
@add_account.display
@add_account.makeKeyAndOrderFront(nil)
@add_account.orderFrontRegardless
第一次单击“+”按钮时效果很好。一切都会显示出来,我可以输入我的数据并将其绑定到我的模型。然而,当我关闭添加新帐户表单时,事情开始变得糟糕。
如果我将“添加新帐户”窗口设置为在关闭时释放,那么第二次单击“+”按钮时,该窗口仍会弹出,但已冻结。我无法单击任何按钮,输入任何数据,甚至无法关闭表单。我认为这是因为表单的代码已经发布,所以没有消息循环处理表单......但我对此并不完全确定。
如果我将“添加新帐户”窗口设置为在关闭时不释放,那么第二次单击“+”按钮时,该窗口显示正常并且可用 - 但它仍然包含我之前输入的所有数据...仍然绑定到我之前的 Account 类实例。
我做错了什么?当我单击“帐户”表单上的 + 按钮时,创建“添加新帐户”表单的新实例、创建新帐户模型、将该模型绑定到表单并显示表单的正确方法是什么?
...这一切都是在 OSX 10.6.6、64 位、XCode 3.2.4 上完成的
I'm a complete n00b with MacRuby and Cocoa, so keep that in mind when answering - I need lots of details and explanation. :)
I've set up a simple project that has 2 windows in it, both of which are built with Interface Builder. The first window is a simple list of accounts using a table view. It has a "+" button below the table. When I click the + button, I want to show an "Add New Account" window.
I also have an AccountsController < NSWindowController
and a AddNewAccountController < NSWindowController
class, set up as the delegates for these windows, with the appropriate button click methods wired up, and outlets to reference the needed windows.
When I click the "+" button in the Accounts window, I have this code fire:
@add_account.center
@add_account.display
@add_account.makeKeyAndOrderFront(nil)
@add_account.orderFrontRegardless
this works great the first time I click the + button. Everything shows up, I'm able to enter my data and have it bind to my model. however, when I close the add new account form, things start going bad.
if I set the add new account window to release on close, then the second time I click the + button, the window will still pop up but it's frozen. i can't click any buttons, enter any data, or even close the form. i assume this is because the form's code has been released, so there is no message loop processing the form... but i'm not entirely sure about this.
if i set the add new account window to not release on close, then the second time i click the + button, the window shows up fine and it is usable - but it still has all the data that i had previously entered... it's still bound to my previous Account class instance.
what am I doing wrong? what's the correct way to create a new instance of the Add New Account form, create a new Account model, bind that model to the form and show the form, when I click the + button on the Accounts form?
... this is all being done on OSX 10.6.6, 64bit, with XCode 3.2.4
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是它不会每次都创建窗口。关闭时释放是一个有点烦人的选项,通常仅在您知道窗口关闭时窗口控制器也被释放时才使用。 (请注意,我从未使用过 MacRuby,因此我将在 Obj-C 中提供代码,因为我知道它是正确的,希望您可以转换它。我将假设 GC 已打开,就像 MacRuby 中应有的那样)。
现在有两种方法可以做到这一点。我不完全确定你的 NIB/类是如何设置的,因为它可能是两种方式之一。
--
解决此问题的第一种方法是使用引用表单元素的出口,以便在再次显示窗口时将其清空,例如 [myTextField setStringValue:@""]。如果您使用可可绑定,那么这就有点棘手,但基本上您必须确保绑定对象被清空。如果您是 Cocoa 的新手,我建议您不要使用绑定。
--
第二种方法是使 AddNewAccountController 类成为 NSWindowController 的子类。当您按下 + 按钮时,您将创建它的一个新实例并显示它(记住将其存储在 ivar 中)。最好的方法是这样:
如果窗口已经可见,这可以防止创建新实例。然后,您需要实现委托:
显然,您需要将窗口移动到名为“AddNewAccountController”的单独 NIB。在此 NIB 中,确保将文件所有者的类设置为 AddNewAccountController,然后将文件所有者的窗口出口连接到窗口。
当所有这些都设置完毕后,您每次都会得到一个新的控制器/窗口。它还具有将笔尖和控制器分成更集中的单元的优点。
——
最后一件事。虽然在窗口中执行此类操作很好,但您可能最终希望通过工作表执行此操作,因为这样可以防止添加帐户窗口隐藏在其他窗口后面的可能性。
The issue is that it doesn't create the window each time. Release on close is a bit of an annoying option and generally is only used if you know the window controller is also being released when the window closes. (Note I've never used MacRuby so I'll be giving code in Obj-C as I know that it is correct, hopefully you can convert it. I'll be assuming GC is on as it should be with MacRuby).
Now there are two ways to do this. I'm not entirely sure how your NIB/classes are set up as it could be one of two ways.
--
The first way to solve it is to use the outlets you use to reference the form elements to blank them out when you display the window again eg [myTextField setStringValue:@""]. If you're using cocoa bindings then it's a little trickier, but basically you have to make sure the bound object is blanked out. I would recommend against bindings though if you are new to Cocoa.
--
The second way is to make the AddNewAccountController class a subclass of NSWindowController. When you press the + button you would then create a new instance of it and display it (remember to store it in an ivar). The best way to do it would be as so:
This prevents a new instance being made if the window is already visible. You then need to implement the delegate:
Obviously you would need to move the window to a separate NIB called "AddNewAccountController". In this NIB make sure to set the class of the File's Owner to AddNewAccountController and then to connect the File's Owner's window outlet to the window.
When all this is set up, you will get a fresh controller/window each time. It also has the benefit of splitting up nibs and controllers into more focused units.
--
One last thing. While it is fine to do something like this in a window, you may want to eventually look at doing this via a sheet, as it would then prevent the possibility of the add account window getting hidden behind other windows.