Creating a Color Meter Using Cocoa06/15/2001
In this column weíre going to create a simple Cocoa application that will allow us to explore how we interact with interfaces and obtain information from user controls. This app is a standard Cocoa application -- a color meter -- rather than a document-based project.
The color meter we'll be making isn't complicated. It consists of four sliders -- a slider each for red, blue, green, and alpha (transparency) -- four text fields, and one "color well." So let's get started.
In this project, I want to introduce you to Interface controls as a class, rather than as an image on the screen. Graphical interface devices in Cocoa are all descended from the abstract Application Kit class,
These devices you are probably already familiar with in form -- buttons, sliders, scrollers, color wells, tables, text fields, and more -- but maybe not so familiar with in low-level function. I want to spend some time with the
NSControl class to show you how you can take basic control over all the components of your interface. The methods of
NSControl are the methods we use to obtain information from the interface such as text or numbers entered into a text field.
The methods that will be of most use to us at this time are the ones that allow us to retrieve data from a control, and set the data contained in control.
NSControl has several methods that allow us to do just this. These methods are called accessor methods, as they allow us to access the data owned by some object.
To get a number, or a string from a control, we use one of the following methods:
The method names identify what type of data they will return:
double will return a number that is of type "double",
float will return a float-typed number, and
int an integer.
To get a string from the control we use
objectValue method will return the object value contained in the controlís cell.
Keeping control values as objects makes it simple to move data around between different objects that might use that data, as most objects when taking number or string arguments require
NSString data types.
To set the value of a controlís cell, we invoke the following methods:
For instance, if we had a text field in which we wanted to display a number, we would send the text field the following message:
The argument of each of the set-methods are of type indicated in the method name.
The naming scheme seen above with the accessor methods is standard throughout Cocoa. You will see these methods again and again in many Foundation and Application Kit classes, and has the advantage that you donít have to remember as much vocabulary to get stuff done. For example,
NSString has these same methods, which allow one to extract an integer from a
NSString typed variable.
NSNumber also has a
stringValue method that lets you return the a number as a string.
The implications of this naming scheme run deeper than simple convenience. Many nice features of the Cocoa frameworks will work only if this naming scheme is adhered to. We wonít talk about it now, but if you just canít wait, check out Key Value Coding, which is described in the
NSKeyValueCoding informal protocol. The reference for this is found in the Foundation Framework class reference, NSKeyValueCoding (Objective-C).
NSControl also defines several other methods. There are methods that allow you to
format the text. There are methods that let you change the font with which text is
displayed within a control. You can enable or disable the control if you like by sending it a
setEnabled:NO message (remember,
NO is how Objective-C represents Boolean values). Every attribute of a control that you set in Interface Builder -- including placement, targets, and whatever you set in the Info panel -- you can change via code.
With the methods that are part of
NSControl, you have total control over every aspect of your interface controls and components. If you want to see a full, detailed description of what
NSControl has to offer, including all the methods that are a part of it, check out its class reference found here: NSControl (Objective-C)
Building our interface
Now that we have the means to work with our controls, let's build an interface and code it to do something fun.
The interface for the color meter consists of four sliders, four text fields that serve as labels, four text fields that dynamically display text, and one color well.
Text fields can be found on the Cocoa-Views palette. Our applicationís interface uses two of the ones found on this palette. On the right is a blank white rectangle. This is a text field that allows the user to type text into it. There is also a field that says "Informational Text".
These two text fields are both instances of the same class
NSTextField. They differ only in the options that are set for display, font, and user interaction options. In fact, it is possible to turn these text fields into each other through the attributes info panel, or programmatically. In Cocoa, you have full control over every element of the interface.
Now, drag four each of these onto your main window; donít worry about organizing them until we get the sliders out. The sliders can be found on the Cocoa-More Views palette. You will see several varieties of sliders here. Again, the situation is the same as before with the text fields. You can change the appearance of one slider to look like any of the ones you see here, both in the code and the Attributes info panel.
The last thing we need from the current palette is the color well object. Drag this somewhere onto your interface as well. You can see in the image below how I set up my interface. Organize yours in a similar fashion.
Interface Builder provides several tools to help you quickly align your control objects in accordance to the Aqua Human Interface Guidelines. We talked about one in a previous column, and that is the pop-up guidelines.
By default, when you move an object next to another object, there will be certain "sweetspots" corresponding to ideal object separation distances and alignments. You can augment this feature by turning on Layout Rectangles from the Layout menu, or by pressing Command-L. Layout rectangles provide the added convenience that objects will momentarily lock into place as you move them near the Aqua sweetspots.
If you desire even more precise control over the placement of your interface objects, you can move selected objects around using the arrow keys. A single key stroke in any direction will move the selected object one pixel in that direction. If you hold the Option key and move the mouse cursor over another object, you will be provided information about how many pixels separate (in the applicable dimension) the selected object from the object under the pointer. The selected object can, in this case as well, be moved using the arrow keys.
Finally, if you prefer more automation, there's an alignment tool, found in the Tools menu, which has several options for aligning a group of selected objects, much like in any drawing program.
Setting interface object attributes
Before we continue with the interface, let's change the behavior of the sliders. Open the inspector to view the attributes of the objects. The inspector allows you to set many of the runtime attributes and characteristics of certain interface objects. The options are different for each class of object.
Let's talk about your experiences while building this application.
Also in Programming With Cocoa:
The Info panel also allows you to change the way interface objects adapt to window resizing. You can also view any connections to the object, and even associate a custom class with the object.
Our purpose here is to change the way the in which sliders send action methods. The default option is to send a message to whomever is listening after the person operating the slider has stopped dragging the indicator about.
We want the sliders to continuously send action messages as the slider is dragged to update the color displayed in the color well. This is accomplished by enabling the "Continuous" option in the attributes panel of the inspector.
Another thing we can change is the bounds of the slider, that is, the smallest
and largest values our slider will take on at its extremes. Because the way weíre going to create a custom color is to instantiate an
NSColor object with values of red, green, blue, and alpha (transparency), which takes value between zero and one, we want to set the minimum value of all of our sliders to zero and the maximum value to one. "Current" is the value the control is set at initially. You can set this to whatever you want (as long as it's within the bounds); Iíve set mine to .5, for no reason in particular.
Weíre not going to change anything about the way our text fields behave, but if you look at the attributes for one of our text fields, youíll see that you can change the text font, color, size, alignment, and editability. You can, of course, change these if you like; I just left them as they were to make things easier.
Pages: 1, 2