inexplicable problem with GroupBox(es)

J

johnmmcparland

Hi all,

my program is trying to add group boxes with radio buttons at run time.
While at one point it was able to draw the group boxes without the
radio buttons, now it encounters problems just getting the radiobuttons
out of the group box.

/// area where radio buttons added to groupbox

/// this code is wrapped in another loop creating group boxes
for (int j= 0; j < TactonManager.noTactons(); j++)
{
// create a radio button
RadioButton rb= new RadioButton();
rb.CreateControl();
Console.WriteLine("going to create a radio button");
rb= createRadioButton(j,yVal,tactonMids);
gb.Controls.Add(rb);
Console.WriteLine("created radio button {0} and added it to the
controls of the group box",j);
Console.WriteLine("rb location= {0}",rb.Location.ToString());
} // radio button for

// update the current bottom position before drawing next group box
bottomY= gb.Location.Y + gb.Size.Height;

grpBxs.Add(gb);
/// end of enclosing loop

// groupBoxes is a member of the class
groupBoxes= grpBxs;


/// area where radio buttons accessed from groupBox

int count = groupBoxes.Count;
Console.WriteLine("no group boxes= {0}",count);
// loop round group boxes
foreach (Object o in groupBoxes)
{
GroupBox g = (GroupBox)o;
Console.WriteLine("location of GroupBox=
{0}",g.Location.ToString());
int temp= g.Controls.Count;
this.Controls.Add(g);
Console.WriteLine("group boxes.controls= {0}",g.Controls.Count);
// loop round radiobuttons
int j = 0;
foreach (Control c in g.Controls)
{
Console.WriteLine("going to draw a radio button {0}",j);
Console.WriteLine("RadioButton location=
{0}",((RadioButton)c).Location);
this.Controls.Add((RadioButton)c);
j++;
}
/// <debug>
/// note: this only seems to try to draw radio buttons 0,2 (at
posns 45, 127)
/// it misses out those at 86 and 168, and still does with a normal
loop.
/// plus it doesn't actually draw them
/// </debug>
Console.WriteLine("exited the loop for the radio buttons");
}

it only finds two of my radio buttons (on the 3rd (index 2) I get an
error.

Below is all of the relevant output from the program and compiler

going to create a radio button
creating radio buttons
created radio button 0 and added it to the controls of the group box
rb location= {X=45,Y=287}
going to create a radio button
creating radio buttons
created radio button 1 and added it to the controls of the group box
rb location= {X=86,Y=287}
going to create a radio button
creating radio buttons
created radio button 2 and added it to the controls of the group box
rb location= {X=127,Y=287}
going to create a radio button
creating radio buttons
created radio button 3 and added it to the controls of the group box
rb location= {X=168,Y=287}
no group boxes= 1
location of GroupBox= {X=16,Y=267}
group boxes.controls= 4
going to draw a radio button 0
RadioButton location= {X=45,Y=287}
going to draw a radio button 1
RadioButton location= {X=127,Y=287}
going to draw a radio button 2
An unhandled exception of type 'System.NullReferenceException' occurred
in SimpleSimonTactile.exe

Additional information: Object reference not set to an instance of an
object.

The thread '<No Name>' (0xab8) has exited with code 0 (0x0).

Unhandled Exception: System.NullReferenceException: Object reference
not set to an instance of an object.
at SimpleSimonTactile.UserGuessUI.drawSelectors() in c:\documents
and settings\mcparlaj\my documents\degree course\4th
year\project\software\simplesimontactile\simplesimontactile\userguessui.cs:line
345
at SimpleSimonTactile.UserGuessUI..ctor() in c:\documents and
settings\mcparlaj\my documents\degree course\4th
year\project\software\simplesimontactile\simplesimontactile\userguessui.cs:line
96
at SimpleSimonTactile.UserGuessUI.ShowForm() in c:\documents and
settings\mcparlaj\my documents\degree course\4th
year\project\software\simplesimontactile\simplesimontactile\userguessui.cs:line
396

as you may notice that while only two radio buttons are able to be
"drawn" (at x posns 45 and 127) those at posns 16 and 168 are missed
out. Why?

Please help

John
 
B

Bruce Wood

It's pretty difficult to diagnose what's going on here, because there
are some odd bits in this code that I don't really understand. Maybe if
I point out some oddities you'll either find your problem or help me
understand.

First off, you have

RadioButton rb= new RadioButton();
rb.CreateControl();
Console.WriteLine("going to create a radio button");
rb= createRadioButton(j,yVal,tactonMids);
gb.Controls.Add(rb);

Why do you create a RadioButton only to replace it with the result of
calling "createRadioButton" on the fourth line? Whatever was in rb
before (a reference to the RadioButton created on the first line) will
be replaced by whatever createRadioButton returns. I really hope that's
a RadioButton, and I hope that it's never null....

Down farther, the code seems a little too sure of itself:

foreach (Control c in g.Controls)
{
Console.WriteLine("going to
draw a radio button {0}",j);
Console.WriteLine("RadioButton
location=
{0}",((RadioButton)c).Location);

this.Controls.Add((RadioButton)c);
j++;
}

Casting every control to a RadioButton? Brave soul. What if some other
control ends up inside one of your GroupBoxes. This would be safer:

foreach (Control c in g.Controls)
{
Console.WriteLine("going to
draw a radio button {0}",j);
RadioButton rb = c as
RadioButton;
if (rb == null)
{
Console.WriteLine("Got a
{0} instead of a RadioButton!", c.GetType());
}
else
{

Console.WriteLine("RadioButton location=
{0}",rb.Location);
this.Controls.Add(rb);
}
j++;
}

But then I don't understand why you're doing this.Controls.Add(rb);?!?
You're removing the radio buttons from their group boxes and putting
them directly on the parent container?
 
J

johnmmcparland

thanks for your reply,

well I got some help from a friend who said that I needed to specify
the size of the radio buttons to fix the problem: and it did!

In answer to your queries;

"createRadioButton" is a poor name for a method which sets the radio
button's name, location etc. While it does make a call to new
RadioButton() it does not use createControl().

as for the danger that someone may add a different type of control,
while indeed I should have checked for this, I haven't as this is a
small project and only I will edit the code. Also all the controls and
any way to access them are private. None-the-less I will put this
check in as I should have.

finaly, it seems that I need to add the radio buttons to the group box
so that when I check one, the rest in that groupBox are unchecked. But
after doing this, if I do not add them to the form directly, they are
not displayed when I add the groupBox to the form. Therefore I must
add the radio buttons to both the groupBox and the Form, and add the
groupBox to the form.

hope this helps anyone else with this bewildering problem.
 
B

Bruce Wood

"createRadioButton" is a poor name for a method which sets the radio
button's name, location etc. While it does make a call to new
RadioButton() it does not use createControl().

OK, but the code still doesn't make sense. createRadioButton creates a
whole new radio button and then you assign that to rb, throwing away
the radio button you created a few lines above. There's something wrong
there.
finaly, it seems that I need to add the radio buttons to the group box
so that when I check one, the rest in that groupBox are unchecked. But
after doing this, if I do not add them to the form directly, they are
not displayed when I add the groupBox to the form. Therefore I must
add the radio buttons to both the groupBox and the Form, and add the
groupBox to the form.

No, this isn't true. You do _not_ need to add the radio buttons to both
the GroupBox and the Form. At least, not in WinForms. I don't program
in ASP.NET, but I would assume that the same rule applies there. If
you're having a problem with things not appearing correctly when you
add the radio buttons to the GroupBox and the GroupBox to the Form,
then there is some other problem cropping up there.

If you add the RadioButtons to the Form directly, then they will be
removed from the GroupBoxes. A control can have only one containing
control, or Parent. A RadioButton cannot be simultaneously directly
contained within a GroupBox and a Form.

So, something else is happening in your program. Unfortunately I don't
have enough information to tell you what might be wrong.
 
J

johnmmcparland

thanks for the help, but I'm still having problems

yea I've noticed, as you say that adding to the group box and then to
the form doesn't work. unfortunately if I do not add the radio buttons
to the form, I can't see them at all.

ok, here's an improved version of the above code;

private void createSelectors()
{
// calculate the neccessary positions
// tactonMids contains the x positions for each radio button
int[] tactonMids= new int[TactonManager.noTactons()];
Size gbSize= new Size();
calculatePositions(out tactonMids, out gbSize);

// generate a group box for every tacton in the sequence
for (int i= 0; i < sqg.sequenceLength(); i++)
{
// create a group box
GroupBox gb= new GroupBox();
setGroupBox(i, gbSize, ref gb); // sets the size, name, text and
location of gb
this.Controls.Add(gb);
// generate radio buttons for every tacton in the TactonManager

// this is the y value for all radio buttons in this group box
int yVal= (gb.Size.Height/2) + gb.Location.Y;

// noTactons-1 is the number of radio buttons needed. same as
tactonMids array

for (int j= 0; j < TactonManager.noTactons(); j++)
{
// create a radio button
RadioButton rb= new RadioButton();
// set rb's text, name, size, location
setRadioButton(j,yVal,tactonMids, ref rb);
gb.Controls.Add(rb);
} // radio button for

// update the current bottom position before drawing next group box
bottomY= gb.Location.Y + gb.Size.Height;

// groupBoxes is a static variable in the class, i need it
later
groupBoxes.Add(gb);
} // groupBox for
}

as mentioned, after doing this, the groupBoxes show up but not the
radio buttons.
 
B

Bruce Wood

If I had to hazard a quick guess (and I do right now), I'd say that the
problem is your x,y coordinates for the radio buttons.

Do you realize that if you're adding radio buttons to a group box, then
the x,y coordinates of the radio button are relative to the top left of
the group box? That is, you're adding in the group box's coordinate
system, not the form's coordinate system.

So, if your group box is at location 200, 400 on you form, and the
group box is 500 by 100 pixels, you add radio buttons starting at, say,
10, 10 in the group box, and then add the group box at 200, 400 in the
form. You don't add the radio buttons at 210, 410 in the group box, or
they'll be off the bottom of it.

I predict that if you adjust your radio buttons accordingly, they will
show up properly.
 
J

johnmmcparland

Do you realize that if you're adding radio buttons to a group box, then
the x,y coordinates of the radio button are relative to the top left of
the group box?

-> no I didn't d'oh! thanks very much! it works!
 
B

Bruce Wood

Just as a hint to make this sort of thing easier in the future.

Whenever I have to generate controls in code and add them to a panel,
user control, form, whatever... I use the Visual Studio Designer first.

Yeah, I know: the Designer can't write your code for you because you
need to calculate things at runtime. However, you _can_ mock up a quick
example in the Designer and then go and look at the code it generated.
You can even copy and paste the generated code into a loop (or
whatever) and then butcher the Designer-generated code to your
purposes.

I find that writing WinForms code from scratch, by hand, is a
nightmare. There are so many little details that you need to take care
of... it can get ugly. That's why I prefer to do a quick mock-up in the
Designer and then crib off _its_ code... because I know that at least
what the Designer generated will work.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top