I have a number of rollovers in a custom graphic interface. Everything works fine except they are a little laggy (especially if you run the mouse over multiple buttons).
Here is how my code looks (the example has just one of the buttons, I have about 12 total):
------------------------------------------------------------------------------------
-- On Mouse Entered --
------------------------------------------------------------------------------------
if name of theObject is "OK_BUTTON" then
play (some item of KEY_SOUNDS)
set visible of image view "ROLLOVER_OK" of window "MAIN" to true
set position of image view "ACTIVE_ARROW" of window "MAIN" to {252, 47}
else
set visible of image view "ROLLOVER_OK" of window "MAIN" to false
end if
------------------------------------------------------------------------------------
-- On Mouse Exited --
------------------------------------------------------------------------------------
if name of theObject is "OK_BUTTON" then set visible of image view "ROLLOVER_OK" of window "MAIN" to false
Are you just trying to change the image of a button? I can’t really tell what you’re trying to do. What is the purpose of hiding/unhiding an image view?
I have a base graphic that fills the entire main window. This base graphic contains all the custom user interface elements including all the custom buttons in their inactive state in one flat graphic. When a users rolls over one of the base graphic buttons the code is unhiding a small active (rollover) graphic in an image view that pertains to that button. I have a transparent IB button over top of the base graphic to act as the “real” button. I hope this makes sense.
Mikey, BTW I am not that familiar with Cocoa/Obj-C. I want to learn. I have been reading up on Cocoa/Obj-C and it might be awhile before I understand it enough to actual apply it. Thanks, CarbonQuark
Why are you faking your interface with transparent controls? Is it some kind of game? More details, please.
Your speed problem:
You’re using AppleScript. (I’m not crapping on AS, but that’s one of your bottlenecks right now. It just ain’t built for speeeeeed.)
You’re redrawing the entire view every time you enter the tracking rect, and redrawing it again when you exit. Futhermore, you have to wait for the redraw before the next redraw.
It’s not a game. However, the interface needs to be custom (the standard look of the buttons and controls that Apple provides won’t work). One note, when a user rolls over a button the code unhides a rollover graphic that is only the size of that button (I don’t have the entire background changing).
If I was using Obj-C to perform this, would the redraw wait still be as laggy?
You should run Quartz Debug to see what parts of the screen are being redrawn. You may not be telling the entire background to redraw, but maybe you’re doing something that’s making it happen. Rule it out.
Your speed problems are probably just AppleScript, if you’re not redrawing the entire background.
Edit for future searchers: See NSButton subclass below, and my note below it. This is how it’s done.
sorry for answering late … if your buttons don’t need a third state (mouse out, over and down) then you can use this simple NSButton subclass to make the buttons show their alternate image (as set in Interface Builder - set behaviour ‘momentary change’) on mouseover:
Thanks for the help. I made my best attempt to get your suggestion to work. Unfortunatly, I am lost at the moment at implementing a custom subclass. I am still learning just the basics of Obj-C. I’m not sure how to get all the conections hooked up.
It’s usually considered better to implement -[NSView viewDidMoveToSuperview] and add the tracking rect there instead of -awakeFromNib (or -initWithFrame:).
You should not have your button play the sounds, however, because that requires you to initialize an instance of each sound for each button, which is a waste of memory (unless each button has a unique sound pool, but even then, it might be a bit of a MVC violation).
What you might consider doing is initializing your five random sounds when your application controller awakens. Add them to an NSArray so you can pick one later. Have the button call back to your controller to play a random sound when -mouseEntered: is triggered.
Now that my rollover buttons use the new subclass they don’t seem to be connecting to my Applescript via “mouse entered” and “mouse exited” to run my other tasks (see below). It seems that the code "[self addTrackingRect:[self bounds] " might be keeping the button from connecting to my Applescript. Any thoughts?
CarbonQuark
if name of theObject is "BUTTON_1" then
set position of image view "ACTIVE_ARROW" of window "MAIN" to {9, 47}
if SOUNDS_SWITCH is 1 then play (some item of KEY_SOUNDS)
end if
I would not be surprised if overriding -mouseEntered: and -mouseExited: prevents passing of the events to AppleScript connections. Normally, the two methods don’t do anything at all, but perhaps when you attach the AppleScript hooks, actions are added. Therefore, you may need to pass the NSEvent back to the superclass to get the AppleScript side to trigger. Try doing this:
(void)mouseExited:(NSEvent *)theEvent{
[self highlight:NO];
[super mouseExited];
}[/code]
This is just a guess, however, as I have never been in a situation where I’ve needed to handle this.
Edit: Or you could always dive further and reimplement those two AppleScript Studio parts in Cocoa, now that your buttons are set up.
I really would like to implement the two AppleScript Studio parts in the custom class. However, at the moment I’m a Cocoa n00b. I don’t believe learning Cocoa is beyond my abilities I just need experience and time with it.