Loop to make grid of NSButtons? - objective-c

I am trying to loop through and programmatically make a grid of 256 NSButtons (16x16). The code I have so far is below. This is in Objective-C for my Mac app. So I am logging to see which tag I get when I click a button, but it keep returning the same tag every time.
I want it so that every button goes 1-256 from left to right, top to bottom. This code successfully makes them load into my view, but the tags are wrong.
#define N_ROWS 16
#define N_COLS 16
int btnSpaceDifference = 1;
int btnSpacing = N_ROWS + btnSpaceDifference;
for (int j = 0; j < N_ROWS; j++) {
for (int i = 0; i < N_COLS; i++) {
paintPixel = [[[NSButton alloc] initWithFrame:NSMakeRect(10 + (i * btnSpacing), 10 + (j * btnSpacing), 16, 16)] autorelease];
[paintPixel setTitle:#""];
[paintPixel setBezelStyle:NSBorderlessWindowMask];
[paintPixel setTag:j + i * N_ROWS + 1];
[paintPixel setAction:#selector(btnPaintAction:)];
[[[box.tabViewItems objectAtIndex:0]view] addSubview:paintPixel];
}
}
-(void)btnPaintAction:(id)sender{
NSLog(#"%ld", paintPixel.tag);
}

Instead of making all of these buttons yourself, why not use an NSMatrix? This is the sort of thing it's perfect for.

Not sure how its compiling, you might have paintPixel defined elsewhere. But you need to change your btnPaintAction from:
-(void)btnPaintAction:(id)sender {
NSLog(#"%ld", paintPixel.tag);
}
To something like this:
-(void)btnPaintAction:(id)sender {
NSButton * myButton = (NSButton *) sender;
NSLog(#"%ld", myButton.tag);
}

call setTag with an increment variable
int TagVal = 1;
for (int j = 0; j < N_ROWS; j++) {
....
[paintPixel setTag:TagVal++];
....
}
Then modify your btnPaintAction:
UIButton *button = (UIButton *)sender;
NSLog(#"%ld", button.tag);

It's returning the same tag every time because your action is referring to your (apparently) member variable paintPixel. Use the sender parameter to the action instead.
NSLog(#"%ld", ((NSButton *)sender).tag);

This is old post but I see no correct answer, thus my addition.
Q. " I want it so that every button goes 1-256 from left to right, top to bottom."
Kevin was on the good track, however one more alteration is required:
paintPixel = [[[NSButton alloc] initWithFrame:NSMakeRect(10 + (i * btnSpacing), 10 - (j * btnSpacing), 16, 16)] autorelease];
Thus minus(-) instead of plus(+) results in numbering top to bottom.

Related

Creating a lot of buttons for levels in Cocos2d using a for loop

I'm trying to make a couple hundred levels for a game I'm developing, so obviously I want to use a for loop and not create each button individually.
I do all of this fine, but the code I'm currently using makes it so that the call block for each button is the same. Obviously if I'm going to have the different level buttons go to different levels, the call block must be different for each one.
In order to differentiate which level I'm on, I call [[LevelManager sharedInstance] nextLevel] the number of times corresponding to the level number. I attempted to change this number by getting the touch location of the user touching the button, getting a row/column number, then running the above code a certain number of times. However, it was not updating the touch position before running the whole call block after touching the button, which obviously makes my code not work.
Is there a way to update the touch position manually, before the call block finishes? Is there a way to somehow store every button in an array and establish a different call block for each one? I'm not sure what the best approach is to fixing my problem. Thanks and my code is below.
Called upon initialization
for (int l = 0; l < NUMBER_OF_WORLDS; l++) {
for (int j = 0; j < 4; j++) {
for (int k = 0; k < 5; k++) {
NSString *tempTitle = [NSString stringWithFormat:#"%i",(k+1)+(l*5)];
CCButton *tempButton;
tempButton = [CCButton buttonWithTitle:tempTitle]
tempButton.block = ^(id sender) {
int row = floorf(touchLocation.y/(screenBounds.size.height/6)) + 1;
int column = floorf(touchLocation.x/(screenBounds.size.width/4)) + 1;
int buttonIndex = row*column;
for (int m = 1; m < buttonIndex; m++) {
[[LevelManager sharedInstance] nextLevel];
}
CCScene *gameplayScene = [CCBReader loadAsScene:#"LevelScene"];
[[CCDirector sharedDirector] replaceScene:gameplayScene];
levelNumber = i;
};
tempButton.position = ccp((screenBounds.size.width/4)*j + levelImagePlaceholder.contentSize.width*tempButton.scale, screenBounds.size.height/6*k + 50 + l*screenBounds.size.height);
[self addChild:tempButton];
i++;
}
}
}
Method for getting touch position
-(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CCLOG(#"touch ran");
touchLocation = [touch locationInNode:self];
}
You already have the row/column available. They are j and k. Those variables can be referenced in your button's "on pressed" block.

Objective-C/Cocos2D - Display different Sprites with Animation on the same positon on the Screen

Hello i have a big question and i don't find a way to solve my problem till now.
I work on simple game with objective-c and cocos2D.
I have 3 different objects (sprites with animation) and four fixed position on the screen.
Alternately with a interval i want to display the different objects on the positions.
I wanted to do it with a double for() to position the objects. And in the for for i want to create a multidimensional array with all the objects.
And then i want to create a Method where i have access to the time-interval and the frequency of the different objects.
Do you think i can solve my problem with this solution or do you know a better way…??
It would be great if anybody could help me.
Thanky you
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"myPlist.plist"];
myArray = [[CCArray alloc] init];
for (int i = 1; i <= 2; i++) {
for (int j = 1; j <= 2; j++) {
Figure *figure = [Figure spriteWithSpriteFrameName:#"a0001.png"];
figure.position = ccp(j * figure.contentSize.width + 50, i * figure.contentSize.height + 50);
[myArray addObject: figure];
[self addChild:figure z:1];
}
}
I do not know how you structured your plist, but I imagine that you have renamed the images in this way:
a0001.png
a0002.png
a0003.png
why you don't try to make a more simple for loop instead of a "for inside a for" for place only 3 images at your view and manage your file like this:
for (int i = 1; i < 3; i++) {
Figure *figure = [Figure spriteWithSpriteFrameName:[NSString stringWithFormat:#"a000%i.png", i]]
figure.position = //add something that fit with your layout
[myArray addObject: figure];
[self addChild:figure z:1];
}

Logically Layout Multiple Items into a View by their X and Y coordinates

I have a UIView and I want to add a series of programmatically generated UIButtons to it.
I've created a method that places each button (of standard size) via a CGPoint.
I want to lay these buttons out 3 in a row, over as many rows as needed.
I've no idea how to go about programatically generating the x and y coordinates to place the items on the view. I'm stuck on how to get the buttons to drop onto a new row once three have been placed.
Here's my code, I want to process something in this method to return the coordinates based only upon the index of the button:
- (CGPoint)calculateCoordinatesWithIndex:(NSInteger)index{
NSInteger x = 100;
NSInteger y = 50;
return CGPointMake(x, y);
}
The only solutions I can think of seem really clunky and inefficient.
Hello what about something like :
#define BUTTON_WIDTH 100
#define BUTTON_HEIGHT 50
- (void) placeButtonsFromButtonsArray:(NSArray *) buttons{
CGFloat currentXPosition = 0.0;
CGFloat currentYPosition = 0.0;
for (NSUInteger i = 0; i < [buttons count]; i++){
b.frame = CGRectMake(currentXPosition, currentYPosition, BUTTON_WIDTH, BUTTON_HEIGHT);
if (i%3 == 2){
currentXPosition = 0;
currentYPostion += BUTTON_HEIGHT;
}
else currentXPosition += BUTTON_WIDTH;
}
}
or Using your method :
- (CGPoint)calculateCoordinatesWithIndex:(NSInteger)index{
//computes on which line the button should be
NSUInteger line = (index/3);
//computes on which row the button should be
NSUInteger row = (index%3) ;
return CGPointMake(row*BUTTON_WIDTH, line*BUTTON_HEIGHT);
}
If you're targeting iOS 6, you could use a UICollectionView for this.
try this,
in .h
{
NSInteger x;
NSInteger y;
int noOfbtninrow;
}
-(void)viewDidload
{
x = 100;
y = 50;
noOfbtninrow=0;
}
- (CGPoint)calculateCoordinatesWithIndex:(NSInteger)index
{
if(noOfbtninrow==3)
{
x=100;
y=y+100
noOfbtninrow=0;
}
else
{
noOfbtninrow++;
x=x+100;
}
return CGPointMake(x, y);
}

Getting button names to string format

I have a lot of custom buttons in my program and I need to use methods to get their names. I've figured out how to get their names through their tag, but I cant seem to follow it through to have the name in a string format.
Heres what I'm using:
-(void)pickRandomToHide {
for (int check = 1; check <=5; check++)
{
int eventNumber = 1 + arc4random() % 43;
UIButton *pick;
pick = (UIButton *)[_mapImageView viewWithTag:eventNumber];
[pick setHidden:YES];
NSString *buttonName;
buttonName = [pick currentTitle];
NSLog(#"%#",buttonName);
}
}
The NSLog just gives 'Null' five times. But 5 buttons are disappearing so the start is working.
The reason you're not seeing any titles is because the buttons are hidden and disabled, whereas the titles are likely only set to appear when the button's control state is "normal" (enabled and visible). Here's more information from Apple on the UIButton control states.
Try doing this:
-(void)pickRandomToHide {
for (int check = 1; check <=5; check++)
{
int eventNumber = 1 + arc4random() % 43;
UIButton *pick = (UIButton *)[_mapImageView viewWithTag:eventNumber];
if(pick)
{
[pick setHidden:YES];
NSString *buttonName = [pick titleForState: UIControlStateNormal];
NSLog(#"%#",buttonName);
} else {
NSLog( #"hmmm, no button with a tag corresponding to event number %d", eventNumber);
}
}
}

Reversing a string using array in xcode

this is my first question in stackoverflow!
im trying to reverse a string using two arrays in xcode, ive set up the interface,i got a button,a text field and a label.
whatever goes into the text field is reversed when the button is touched!
i got the code and it seems correct to me on paper,the problem is that when i test the application with for example "HELLO", the content of myArray is "H E" and reverseArray is" O L L".
id be grateful if anyone cud help im pretty fed up with tracing this code :(((
here is the code:
#interface ViewController ()
#end
#implementation ViewController
#synthesize textField,string1,string2,reverseArray,myArray;
#synthesize Label1;
- (IBAction)Reverse:(UIButton *)sender {
reverseArray=[[NSMutableArray alloc]init];
string1=[[NSString alloc]init];
string2=[[NSString alloc]init];
string1=textField.text;
myArray=[[NSMutableArray alloc]init];
for (int i=0; i<=string1.length-1; i++) {
[myArray insertObject:[[NSString alloc] initWithFormat:#"%c",[string1 characterAtIndex:i]] atIndex:i];
}
for (int j=0; j<=myArray.count-1; j++) {
[reverseArray insertObject:[myArray objectAtIndex:myArray.count-1] atIndex:j];
[myArray removeLastObject];
}
NSLog(#"%#",myArray);
NSLog(#"%#",reverseArray);
For the second loop, you're using myArray.count as the end condition for the "for" loop, but myArray.count is decreasing by one each iteration of the loop because you're removing the last object from myArray each iteration. Think about it:
First iteration: j=0; myArray.count - 1 = 4
Second iteration: j=1; myArray.count - 1 = 3
Third iteration: j=2; myArray.count - 1 = 2
It stops here at the forth iteration because j=3 > myArray.count -1 = 1
Try something like this for the second loop (Note: I'm not in front of xCode right now, so there might be errors in the following block. Take it with a grain of salt):
for( int j = string1.length -1; j >= 0; j-- ) {
[reverseArray addObject:[myArray objectAtIndex:j]];
}