PDA

View Full Version : Tables and Timers and Steppers, oh my!




gamestriker
Dec 19, 2005, 04:37 PM
I have several questions on how to do certain things in Cocoa:

1) How does NSStepper work exactly? Can I simply connect it to a method in a custom controller, or do I have to set it up a special way? How would that method get the increment from NSStepper? My aim is to have an NSStepper fire a custom method that will do incrementing and decrementing for the values I want it to, and then I can update the UI myself.

2) How can I change the text in a button when its pressed? Do I just call a method to change the text of the button?

3) I want set up a table so that when I click on a cell, it fires a method that will change the text in a text field to the desired text. How would I do this?

4) How do I use an NSTimer? I want to have an NSTimer countdown every second, and at every second, fire a method to update the values and UI. I also want to know how I can start or pause the NSTimer with the push of an NSButton.

5) Is there a way to set values (text) in table cells from IB or do I have to do it through code? If through code only, how would I do that?

6) How can I change what shows up on the "About" panel when you click on About NewApplication?

I appreciate the help.



HexMonkey
Dec 19, 2005, 05:16 PM
1) How does NSStepper work exactly? Can I simply connect it to a method in a custom controller, or do I have to set it up a special way? How would that method get the increment from NSStepper? My aim is to have an NSStepper fire a custom method that will do incrementing and decrementing for the values I want it to, and then I can update the UI myself.

In Interface Builder, set up the NSStepper attributes (min value, max value, increment amount etc). These can also be set programmatically at runtime if necessary. When the user clicks the up or down arrows, the value of the NSStepper changes automatically according to its attributes. Set up an IBAction for the control, and then you can get its new value there:

- (IBAction)stepStepper:(id)sender
{
int stepperValue = [sender intValue]; //Get the new value

//Do other things (eg update other controls if necessary)
}

2) How can I change the text in a button when its pressed? Do I just call a method to change the text of the button?

In the button's action method just call [sender setTitle:newTitle];

3) I want set up a table so that when I click on a cell, it fires a method that will change the text in a text field to the desired text. How would I do this?

In Interface Builder, set one of your classes as the table's delegate (it's an attribute of the table view). Then in the class, implement the -tableViewSelectionDidChange: method, eg:

- (void)tableViewSelectionDidChange:(NSNotification *)aNotification
{
int selectedRow = [[aNotification object] selectedRow];
...
[myTextField setStringValue:someString];
}

4) How do I use an NSTimer? I want to have an NSTimer countdown every second, and at every second, fire a method to update the values and UI. I also want to know how I can start or pause the NSTimer with the push of an NSButton.

Start the timer as follows (note you'll need to store the timer as a variable so that you can stop it later, unless you stop it from within the timer's selector):

NSTimer* myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateInterface:) userInfo:nil repeats:YES];

Then your timer method would be something like this:

- (void) updateInterface:(NSTimer*)theTimer
{
//Update interface here
}

An NSTimer can't be paused, so to pause and restart you'd have to stop a timer then create a new one. To stop a timer:

[myTimer invalidate]

5) Is there a way to set values (text) in table cells from IB or do I have to do it through code? If through code only, how would I do that?

Through code, you'll need to implement the NSTableView data source methods. Set one of your classes as the table's data source in Interface Builder, then in that class implement (at minimum) the following methods:

- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex //Return the cell contents from this method
- (int)numberOfRowsInTableView:(NSTableView *)aTableView

Alternatively, you could use Cocoa bindings if you're not supporting Jaguar users.

6) How can I change what shows up on the "About" panel when you click on About NewApplication?

Set the appropriate values in the Info.plist and InfoPlist.strings files in your project and it will update automatically. If you want to display more information, add a Credits.rtf or Credits.html file to your project, and it will be added to your about box as well.

Edit to add: You might find AppKiDo (http://homepage.mac.com/aglee/downloads/appkido.html) a useful application. It shows documentation for each class in a nicer way than Xcode's documentation.

robbieduncan
Dec 19, 2005, 05:17 PM
0) Have you read the documentation and looked at the sample apps?

1) Read the documentation!

2) Have you tried calling setStringValue:?

3) Look at the delegate methods of NSTableView. You can get informed whenever the selection changes. Note that in an NSTableView you cannot select a single cell, only a row or column. You probably really want an NSMatrix.

4) Read the documentation. It's really quite simpe.

5) You have to do it in code. Either by a datasource or via Bindings.

6) Put a file called Credits.rtf (or Credits.html) in Resources. If you mean the Copyright string look at the Info.plist entries.

HiRez
Dec 19, 2005, 10:21 PM
2) How can I change the text in a button when its pressed? Do I just call a method to change the text of the button?.You can set the buttons Alt. Title attribute in IB, then when the button is pressed it will change to that text. However, this only works when you have the button behavior set as Toggle, which the default button does not allow, so you'd have to change button styles.

For the default button style, you'd have to do it manually using setStringValue:. It would be nice if bindings could better communicate directly between two UI objects. For example, provide a text field right in the IB bindings palette where your object would take on that static value when a bound control has NSOnState (or whatever). You can do this with bindings by going through an abject with bound properties and methods, but I'd like a simpler, more direct way as an option.

caveman_uk
Dec 20, 2005, 03:51 AM
I
4) How do I use an NSTimer? I want to have an NSTimer countdown every second, and at every second, fire a method to update the values and UI. I also want to know how I can start or pause the NSTimer with the push of an NSButton.

Have you considered using notifications to trigger updates to your UI?

gamestriker
Dec 21, 2005, 12:04 PM
Thanks HexMonkey, you helped quite a bit.

0) Have you read the documentation and looked at the sample apps?

1) Read the documentation!

Some of the documentation did not make sense to me or I did not understand. The Apple Documentation is good, but not always clear.

You can set the buttons Alt. Title attribute in IB, then when the button is pressed it will change to that text. However, this only works when you have the button behavior set as Toggle, which the default button does not allow, so you'd have to change button styles.

Thank you, that is a much nicer way of doing that. Is there a way to sychronize that with a menu item? I have a menu item for that button as well and I want it to change text just like the actual button. At the moment, I'm doing this through code (in the action that is called when the button is pressed).

Have you considered using notifications to trigger updates to your UI?

Elaborate please. I'm still not yet familiar with a lot of stuff in Objective-C and Cocoa.

caveman_uk
Dec 22, 2005, 04:24 AM
Notifications are a way of communicating between objects without actually doing a method call. Basically objects that are interested in something happening register as observers of a notification. When the thing happens the object that makes it happen posts a notification and then all the objects that registered as observers get told. In your case you might have code that updates the UI and another object that handles your data model. The UI code registers as an observer of a notification that the data model would post if there were any changes.

The Apple documentation is here (http://developer.apple.com/documentation/Cocoa/Conceptual/Notifications/index.html)

HiRez
Dec 22, 2005, 01:28 PM
Is there a way to sychronize that with a menu item? I have a menu item for that button as well and I want it to change text just like the actual button. At the moment, I'm doing this through code (in the action that is called when the button is pressed).I'm not sure I'm understanding exactly what you're asking here...you're saying you have both a menu item and a button which both control the same variable (they are always synchronized), and can have one of two states with different text for each state? In that case you might want to try Cocoa bindings to keep the two synchronized, with an object controller (or bind to a controller you wrote). Cocoa bindings are powerful, but far too difficult to explain here, search for "Cocoa bindings" in the documentation using a full-text search to get you started. There's also a pretty good intro here (http://cocoadevcentral.com/articles/000080.php). Be careful of changing the text of menu items as well, that can be bad interface design if misused and confusing for the user. Sometimes you can indicate "on" or "off" status for a menu item by checking it. Another strategy is to have two items visible all the time, but only keep the currently-applicable one enabled.

gamestriker
Dec 24, 2005, 09:39 PM
Rather than start a separate thread, I'll just ask here.

Does anyone know if and what is the equivalent of making a "public static final CONSTANT_HERE" variable in Objective-C/Cocoa?

gamestriker
Dec 24, 2005, 10:00 PM
Through code, you'll need to implement the NSTableView data source methods. Set one of your classes as the table's data source in Interface Builder, then in that class implement (at minimum) the following methods:

- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex //Return the cell contents from this method
- (int)numberOfRowsInTableView:(NSTableView *)aTableView

Alternatively, you could use Cocoa bindings if you're not supporting Jaguar users.


I implemented the 2 methods (with a little help from the Apple Documentation) and set the class as the data source, but the text still won't show up.

I'd appreciate the help.

HexMonkey
Dec 24, 2005, 10:57 PM
I implemented the 2 methods (with a little help from the Apple Documentation) and set the class as the data source, but the text still won't show up.

Do the methods get called? To find out, add breakpoints to the methods then debug (and see if they are triggered), or use functions such as NSBeep or NSLog inside them (which have immediately noticeable effects).

Double check the connections in Interface Builder, it's the most common place for things to go wrong. If that doesn't fix it, post your code for those methods here.

Catfish_Man
Dec 25, 2005, 12:08 AM
Rather than start a separate thread, I'll just ask here.

Does anyone know if and what is the equivalent of making a "public static final CONSTANT_HERE" variable in Objective-C/Cocoa?

#define CONSTANT_HERE constant

i.e. #define PI 3.1415926535

HiRez
Dec 25, 2005, 01:36 PM
#define CONSTANT_HERE constant

i.e. #define PI 3.1415926535Just a quick tip, you do NOT put a semicolon after #defines (known along with other "#" markers as preprocessor directives because during compilation these are evaluated first before the rest of the code). Normally you put these at the very top of your .h (header) file, just underneath your#import/#include statements (also preprocessor directives). Alternatively, when using Xcode, you can put #define statements in your "prefix" header file, which will automatically make them usable to all the classes in your project.