Help on NSbutton States with IF statements

Discussion in 'Mac Programming' started by zophtx, Apr 3, 2010.

  1. zophtx macrumors member

    Joined:
    Mar 8, 2010
    Location:
    Inside a Cocoa Book
    #1
    hi i been have trouble with NSbutton State and If statments.
    i have Subclassed the NSButton therefore i have used "self" as the button.

    example :
    Code:
    if (self == NSOnState) {
    [self setTitle:@"Button On"];
    }else if (self == NSOffState){
    [self setTitle:@"Button Off"];
    }else{
    [self setTitle:@"Button Mixed"];
    }
    

    but this seem to not work. is their a way to declare the Button state properly or is this properly.
    i have [self allowsMixedState:YES]; on so it mixed state will be on.

    if you can help me out that would be great.

    One more question.:
    is their any way for a button to have more than 3 states. if soo how.?
    would i need to code the new states?

    i have a pdf of all the button class references so please dont tell me to look ate them cause i already have like 20 times.

    thanks in advanced :)

    ok i figure out the right way to use states.
    Code:
    -(void) awakeFromNib {
    	[self setAllowsMixedState:YES];
    	[self setButtonType: NSPushOnPushOffButton];
    	
    	if ([self state] != NSOnState || NSMixedState) {
    		
    		[self setTitle:@"OFF"];
    	}else if ([self state] != NSOffState || NSMixedState) {
    		
    		[self setTitle:@"ON"];
    	}else if ([self state] != NSOnState || NSOffState) {
    		
    		[self setTitle:@"Mixed"];
    	}
    }
    
    here is my AwakeFromNib section.
    but there is some thing wrong. the buttons title will not change. it is always on OFF. if i click on the button "which turns the button state ON" the title is still "OFF" but the button is darken as it would be if it were On or Mixed. do any of you know why this is happening?
     
  2. JoshDC macrumors regular

    Joined:
    Apr 8, 2009
    #2
    This is really quite wrong. First of all it's in the wrong place. awakeFromNib: only gets called when loading the nib, so will not affect the button when you click on it.

    You should probably put the code in an override of setState: (remember to call [super setState:]). The if statement itself is wrong as well, you'll always get "OFF" because:

    ([self state] != NSOnState || NSMixedState) doesn't mean if state is not equal to on or mixed. It's treating NSMixedState as a separate condition. NSMixedState is -1, is non-zero and therefore TRUE. Anything OR true is true, so that whole if statement evaluates to TRUE. Use if([self state] == SomeState) {...}.
     
  3. lloyddean macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #3
    While a lot was written, not a thing said as to what you are actually trying to accomplish. Perhaps you'd be better off describing what you're trying to do and someone could point you in how to implement it.
     
  4. zophtx thread starter macrumors member

    Joined:
    Mar 8, 2010
    Location:
    Inside a Cocoa Book
    #4
    ok i have attached my project.
    i found a way to give a button color. what im try to do with this code is to get a different color on each click. i know i posted a question about how can i do it. but i didn't have time to give more information at the time that i was posting the question.

    why im not using
    Code:
    [self setButtonColor:[NSColor aColor]];
    
    cause im test it with change the title and if change the title on every click work than i assume the color will change as well.

    the reason i want to get this accomplished is because i make a program and each color means different thing. i don't need text in the button just a color on every click.

    ill try overriding the -setState Method to see if this it works.
    i tried this:
    Code:
    	if ([self state] == 0) {
    		
    		[self setTitle:@"OFF"];
    	}else if ([self state] == 1) {
    		
    		[self setTitle:@"ON"];
    	}else if ([self state] == -1) {
    		
    		[self setTitle:@"Mixed"];
    	}
    }
    
    this doesnt work it just gives me "Off" ^^
    and i tried this:
    Code:
    	
    if ([self state] == FALSE) {
    		
    		[self setTitle:@"OFF"];
    	}else if ([self state] == TRUE) {
    		
    		[self setTitle:@"ON"];
    	}else {
    		
    		[self setTitle:@"Mixed"];
    	}
    }
    this one just gives me "ON" ^^

    well if you could help me succeed in this "test" that will be great :)
    it will be great help for the program im a making.
    if you want to know what the program is a bout.

    the program is going to a Attendance program for my Teacher as a farewell gift at my gradation this year. im am 2010 grad :D
     

    Attached Files:

  5. JoshDC macrumors regular

    Joined:
    Apr 8, 2009
    #5
    Override the setState: method in your button cell subclass. I did this and it works fine:

    Code:
    - (void)setState:(NSInteger)state
    {
    	[super setState:state];
    	
    	if (state == NSOnState) {
    		[self setTitle:@"ON"];
    	}
    	else if (state == NSOffState) {
    		[self setTitle:@"OFF"];
    	}
    	else if (state == NSMixedState) {
    		[self setTitle:@"MIXED"];
    	}
    }
    
     
  6. zophtx thread starter macrumors member

    Joined:
    Mar 8, 2010
    Location:
    Inside a Cocoa Book
    #6
    Thank You so much :D

    i got a button to change color on every click :) with your help... :D
    but i can only do 3 colors. :p

    the second question was can a button have more than 3 states?
    do i have to code the new state or should i try different approach like having a NSArry of colors and each toggle of the button sets a color to the button from the array.

    but thank you again this is really a break tho for me.

    EDIT Below ..

    for a new state what if i edit the "enum" for state clarification in NSCell.
    Code:
    enum {
    NSOffState = 0,
    NSOnState = 1,
    NSMixedState = -1,
    // this where i add a new state
    SLTNewState = -2,
    nil;
    }
    
    than than add the new state to the IF statement.. im going to to try that right now.
    that doesnt work :mad: i even add the new methods to the NSButton and NSCell.
    what i did was every thing that had MixedState in NSButton & NSCell i copy and Change it to SLTNewState.
    but when i try it in my ButtonCell the program crashes. so i quess i have to find a diffent way to add a new state or just change the color on every toggle using a NSArray of colors.
     
  7. Sydde macrumors 68020

    Sydde

    Joined:
    Aug 17, 2009
    #7
    You could just ignore the button's actual state and create an ivar within your subclass to track whatever state it is in. Override -mouseUp: to catch the clicks, and use your multistate ivar as an array index.
     
  8. zophtx thread starter macrumors member

    Joined:
    Mar 8, 2010
    Location:
    Inside a Cocoa Book
    #8
    could you give me an example please?
     
  9. Sydde macrumors 68020

    Sydde

    Joined:
    Aug 17, 2009
    #9
    No, but I could outline what I am describing. In your SLTColoredButton.h file, add an NSArray and an int to the class. Then, in the .m file, put in a method

    Code:
    - (void)mouseUp:(id)sender {...
    in which you increment the int variable and change the color of the button to the array object at that index (make sure the int wraps). At some point in that method, you will want to set the button state in the superclass to remove hiliting. You will want to alter the setter and getter methods accordingly.
     
  10. zophtx thread starter macrumors member

    Joined:
    Mar 8, 2010
    Location:
    Inside a Cocoa Book
    #10
    Code:
    // Class Header
    @interface SLTColoredButton : NSButton {
        NSArry *multiState;
    }
    
    
    // Class Implement
    
    @implamention SLTColoredButton 
    
    - (void)setState:multiState {
        multiState = [NSArray alloc] initWithObjects:
                                    [state stateOne],
                                    [state stateTwo],
                                    [state stateThree],
                                    [state stateFour],
                                    [state stateFive],
                                    nil];
        [super setState:multiState];
        
        if(state == stateOne){
            [self setButtonColor:[NSColor aColor];
        }else if(state == stateTwo){
            [self setButtonColor:[NSColor aColor];
        }.........
        else if(state == stateFive){
            [self setButtonColor:[NSColor aColor];
        }else{
            [self setButtonColor:[NSColor clearColor];
        }
    }
    
    -(void)mouseUp(id)sender{
        [self setNextState];
    }
       
    something like this.. im not even sure if this code is correct. but do you mean somethinig like this?
    you know im still quite new to Objective-C.
    but would some thing like this work.
    have a NSArray of madeup state and every click on the button equals to the made up state than when the made up state is set to the button the Color takes over the button. than one more clikc and again a diffent color.
    am i on the right tack or is this going the other direction.

    what if i have multiply button that are to be one button. after one button has gone tho his 3 states its tranpent becomes YES. than the second button become visiable with 3 more state but with 3 diffent colors than the first. than the it repeats it self so after 2nd button 3 states are gone the 1st one becomes visable and the 2n button becomes transpreant. so on so on.
    is this a easyer sultion or should i work alitte with sydde idea/sultion.

    since i am a novice to Objectiv-C and C language. this is the best i can do for now but im sure i figure it it out. what do you think i should do. cause my mind is in a cramp.
     
  11. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #11
    Are you writing the button-color changing program as part of a tutorial? If so which one (what is its URL, or what book is it)?

    If it's not part of a tutorial, and you're a novice, then why are you trying to do something so far beyond your understanding? I'm usually in favor of exploring a language, but if you're in over your head, it's best to recognize it as soon as possible and stop.

    You don't learn to swim better or sooner by jumping headlong into deep water. All that does is make the consequences more painful.
     
  12. Sydde macrumors 68020

    Sydde

    Joined:
    Aug 17, 2009
    #12
    My apologies for confusing the issue. chown33 is correct, learn Objective-C more thoroughly and perhaps study programming technique.
     
  13. zophtx thread starter macrumors member

    Joined:
    Mar 8, 2010
    Location:
    Inside a Cocoa Book
    #13
    http://www.cocoadev.com/index.pl?CCDColoredButtonCell
    here is the url.

    well sometime the best way to learn is by jump in headfirst in to the water even if you dont know how to swim. it better to take risk than learning ways around the risk. LIFE == RISK.
    enough of that.

    i can read the code and understand it 90% but i have a hard time put the pieces for puzzle togeter.

    im going to see if i can put two button together one shows up when the other run out of states. than the cycle goes on and on.
     
  14. Sydde macrumors 68020

    Sydde

    Joined:
    Aug 17, 2009
    #14
    What you tried to write in the previous post shows a serious lack of understanding the fundamentals. You need to work on that first. Part of being a skilled programmer is writing proper code by habit, which means doing stuff over and over until it becomes like riding a bicycle. Yes, it is good to challenge yourself and try difficult things, but then you have to understand why they are not working. When a program fails to work properly, a lack of fundamental understanding will sink you like a rock.
     
  15. zophtx thread starter macrumors member

    Joined:
    Mar 8, 2010
    Location:
    Inside a Cocoa Book
    #15
    ya i quess you are right. i quess the resaon i cant put the puzzles together is cause i dont have "ALL" the fundamentals in my head.
    well thanks for the help so far. i wish you could give me the example of what you mean about the array part*.

    *maybe if you give me the example of the array thing that you were talk about earlier but like in example form not like the actual code example of it is suppose to be in the file. like a tutorail example not this is how you make this button work. i hope you know what i mean.
    and like i said i can read code 90% and understand it 90%.

    but for now im stick my head back into "Programming Obj-C 2.0" by Steve K. book.

    i feel disappointed at myself i thought i could do it and i was looking for example and help to see i f i can finish this project. but i know i can do it if i learn more and more and keep on practice code. and this is the most complex program i actually worked on. actually the first. i quess i overwhelming my self with this project. but i want to figure it out sooo badly.:(

    but than after this part of the project i have to figure out a way to make a NSMatix of Buttons like the one in iCal side bar where that calender part is. you click on the day and shows the schedule of that day. and have it work like the iCal calender but instead of a schedule it shows the buttons im am working on.:(

    i really want to get this done before i grad high school this year in june.
    do you thin k i can finish the project before june??:confused:

    well i quess im going to take you advice. im going to put this project on hold until for a litte while until i get the fundalment in my head .
     
  16. EnigMoiD macrumors member

    Joined:
    Aug 10, 2007
    #16
    Maybe this would be confusing it more, but I'd just make an NSArray filled with as many colors as you need ([NSColor redColor], etc.) and then have an int increment every time the button is pressed, so that you start with color 0, then get color 1, then color 2, etc. (using objectAtIndex:i where i is the int and using whatever the setter method is for the button color). I don't see the point of overriding the setState method or adding new states.

    But I do agree that you should get back to the fundamentals... you can probably get this done before June if you do.
     
  17. zophtx thread starter macrumors member

    Joined:
    Mar 8, 2010
    Location:
    Inside a Cocoa Book
    #17
    i understand what you are saying.

    this is what i got so far with the array be tell me what is right what is not.

    Code:
    -(id) init {
    	self = [super init];
    	if (self != nil) {
    		
    		colorArry = [[NSMutableArray alloc] init];
    		[colorArry addObject:[NSColor redColor]];
    		[colorArry addObject:[NSColor blueColor]];
    		[colorArry addObject:[NSColor greenColor]];
    		[colorArry addObject:[NSColor yellowColor]];
    		[colorArry addObject:[NSColor purpleColor]];
    	}
    	
    
    	
    	return self;
    }
    - (void) dealloc; {
    	[colorArry release];
    	[super dealloc];
    }
    
    - (void) mouseUp:(NSEvent *)theEvent {
    	[self setButtonColor:[self nextColor]];
    }
    
    
    
    - (NSColor *)nextColor {
    	if ([colorArry count] > 0 && [colorArry indexOfObject:[self buttonColor]]) {
    		return [colorArry objectAtIndex:([colorArry indexOfObject:[self buttonColor]]+1)];
    		
    	}else {
    		return [colorArry objectAtIndex:0];
    	}
    	
    	return nil;
    	
    }
    i think im heading to the right direction
     
  18. EnigMoiD macrumors member

    Joined:
    Aug 10, 2007
    #18
    This is an interesting way to do it, not how I would have done it, but it might work... you should test it. Get rid of the ; after dealloc, and don't make your nextColor method return nil. That doesn't make any sense; it's returning one of your colors, not nil.
     
  19. zophtx thread starter macrumors member

    Joined:
    Mar 8, 2010
    Location:
    Inside a Cocoa Book
    #19
    well thats my brain working at 11:00 at night.
     
  20. zophtx thread starter macrumors member

    Joined:
    Mar 8, 2010
    Location:
    Inside a Cocoa Book
    #20
    i actually dont know how i would test the mouseUP: part.
    i have been try other thing like instead of a color i bee testing with set a title on every click. but i been have a hard time with my GUI Connections;:confused:

    i think i doning it right but i dont know how i will get it to work.:confused:





    this is what ihade soo far with title change but i quess i have a had time get a array object onto a value for some thing like setTitle: or setButtonColor: or setWhatever:

    Code:
    
    @implementation Button
    
    -(id) initWithCapacity {
    	self = [super init];
    	
    	if (self != nil) {
    		
    		theTitles = [[NSMutableArray alloc] initWithCapacity:5];
    		[theTitles addObject: @"ONE"];		// arrayIndex:0
    		[theTitles addObject: @"TWO"];		// arrayIndex:1
    		[theTitles addObject: @"THREE"];	// arrayIndex:2
    		[theTitles addObject: @"FOUR"];		// arrayIndex:3
    		[theTitles addObject: @"FIVE"];		// arrayIndex:4
    	}
    	return theTitles;
    }
    -(NSString *)title {
    	title = [theTitles objectAtIndex:0];
    	return [theTitles objectAtIndex:0];
    }
    -(NSString *) nextTitle {
    	unsigned int i;
    	if ([theTitles count] > 0) {
    		return [theTitles objectAtIndex:i = i + 1];
    	}
    	
    	return [theTitles objectAtIndex:i];
    }
    
    - (void) awakeFromNib {
    	//[self setTitle:[self nextTitle]];
    	//[self setTitle:[theTitles objectAtIndex:1]];
    	
    }
    - (void) setState:(NSInteger)state {
    	[super setState:state];
    	
    	if (state) {
    		//[self setTitle:[self nextTitle]];
    		//[self setTitle:[theTitles objectAtIndex:1]];
    		//[self setTitle:title];
    		
    	}
    }
    
    
    @end
    
     
  21. EnigMoiD macrumors member

    Joined:
    Aug 10, 2007
    #21
    Okay, well one problem with this is that you put your array in the method initWithCapacity, which will never be called, since all the methods in this file are for an instance of your class, Button. This code should go in your awakeFromNib method (of course eliminating the return part).

    You also can't do this: [theTitles objectAtIndex:i = i + 1]; I think you just want to write i + 1.

    You should only need one method for this; there's no need to create so many. Just write the method, then drag from a button to your class in IB and select it.

    Also, NSButton doesn't have a setButtonColor: method, and you can't use "self" since the button you want to set is not "self." Setting the button's color is a lot more complicated, and you can only do it to borderless buttons. You could also switch between different buttons that you colored with interface builder, but that would get annoying.

    You should really learn the basics, even if what I'm saying makes sense, and do what other people have been telling you, but here's code I wrote that does both the things you wanted, just to show you how little code you actually need to write.

    Code:
    #import "ButtonColor.h"
    
    
    @implementation ButtonColor
    
    - (void)awakeFromNib {
    	colors = [[NSArray alloc] initWithObjects: 
    			  [NSColor redColor], 
    			  [NSColor blueColor],
    			  [NSColor greenColor], 
    			  [NSColor yellowColor], 
    			  [NSColor purpleColor], 
    			  nil];
    	titles = [[NSArray alloc] initWithObjects:@"One",
    			  @"Two", @"Three", @"Four", @"Five", nil];
    	pressCount=0;
    }
    
    - (void)buttonClicked:(NSButton *)sender {
    	[sender setTitle:[titles objectAtIndex:pressCount]];
    	[[sender cell] setBackgroundColor:[colors objectAtIndex:pressCount]];
    	pressCount++;
    }
    
    @end
     
  22. zophtx thread starter macrumors member

    Joined:
    Mar 8, 2010
    Location:
    Inside a Cocoa Book
    #22
    i actally was just useing the title as a test. i dont want a title i just want thee color. and it going to be more than one button on the GUI.

    the setBackgroundColor does not work. even if the button was boarderless.

    the "setButtonColor:" method works with the button cell. but what is werid is that "pressCount" skips the 3 objects and than goes to the 5th. soo. instead of going red, blue, green, yellow, purple. it goes red, purple. soo if i added 3 blank object such as @"" and the add a new color such as "magenta" it would go red, purple, magenta. but it the code says it should go red, blue, green, yellow, purple, @"", @"", @"", magenta.
    why is that??

    the [sender cell] is not need in the ButtonCell file so self is used instead.

    soo this code works sore da. but it doesnt loop. i would have to add approx 44 objects to the array just to have one button to loop approx 10 times over 5 different colors.

    what i did:

    instead of "colors" i used "colorArray";
    instead of "pressCount" i used a NSUInteger "arrayIndex";

    i connected the buttonClicked to button as a action from the buttonCell Object.
    ((note:)the button itself is SLTColoredButton and the button cell is SLTColoredButtonCell.)

    ive used your code but when i found out that it skiped the 3 object in between the 5 objects you have up now for colors. i added 8 more object just to get 4 colors on every click with no loop.
    that is what i did.

    im trying and tryin and im learning while i doing this.
    i am thankful for all your advice and help expectally from EnigMoiD, and JoshDC but this still hasnt solved my problem. almost. i have been try different things but no luck. the only thin i hope right now is to get the achieved and i need you help to get achieved.
     
  23. EnigMoiD macrumors member

    Joined:
    Aug 10, 2007
    #23
    It would really help to see your code, or even the whole project, because I'm having trouble understanding a lot of the things that are going on.

    Also, Apple's documentation makes no mention of setButtonColor:, so I have to assume that you're using a non-Apple subclass. Could you tell me which one?

    Borderless buttons do work with setBackgroundColor:, but you have to uncheck a box in IB to make them borderless.

    Again, please attach your project; I'd really like to see what's going on.
     
  24. Sydde macrumors 68020

    Sydde

    Joined:
    Aug 17, 2009
    #24
    Have you tried putting a debugger breakpoint in the -buttonClicked: method to see what is happening?

    EnigMoiD: the object origin SLTColoredButton is linked in post 13 above.
     
  25. EnigMoiD macrumors member

    Joined:
    Aug 10, 2007
    #25
    Thanks, missed that.

    EDIT: The implementation of CCDColoredButtonCell is a little more complicated than I thought. It applies to the cell, so to use it you have to either give NSButton a custom cell (which I don't know how to do) or use something like an NSMatrix that lets you deal directly with cells.

    This goes beyond the basics (I think), so like others have been saying, I think you should go back to the basics, zophtx, and come back when you've gotten to subclassing, button cells, and matrices.
     

Share This Page