问题
Specific question
How to create an array of buttons on Borland C++ Builder and work with it?
I'm using Borland C++ Builder 6 and Borland Developer Studio 2006 (Turbo C++ 2006).
Purpose
To work with a lot of buttons on a form just using a for loop with an index, for example, changing their caption, size and position.
I know if I have a button called Button1
and inside a click event of this button if I create another button (through TButton *Button2 = new TButton(Form1)
), I can assign Button1
to Button2
(Button2 = Button1
) and them I can simply modify caption of Button1
with Button2->Caption
. So I would like to extend it assigning pointers of real components to elements of an array to them work with all of them with a for
loop.
Well, if someone found an way to add all buttons as an array on a form, it's better :)
Tries
Following tests were made putting respective code on TForm1::Button1Click(), an event of a button on a form:
Test 1
- Description: Creating an array directly
Code:
TButton Buttons[3];
Result: Compile error:
> [C++ Error] Unit1.cpp(23): E2248 Cannot find default constructor > to initialize array element of type 'TButton'
- Comments:
- I tested some variants of this test (e.g.
TButton Buttons = new TButton[3]
, working withcalloc
function and others), but all of them points to the issue thatTButton
does not have a constructor without arguments, i.e.,TButton()
, but onlyTButton (TComponent *AOwner)
,TButton(void *ParentWindow)
andTButton(const TButton &)
; - Any way to use operator
new
with arguments forTButton
constructor prototypes, for an array?
- I tested some variants of this test (e.g.
Test 2
- Description: Creating a vector
Code: Also add
#include "vector.h"
on unit header...vector<TButton> Buttons; Buttons[0].Caption="it is ok"; Buttons[1].Caption="mayday, mayday";
Result: Debugger exception on 3rd line:
> Project Project1.exe raised exception class EAccessViolation > with message 'Acceess violation at address 401075B9 in module > 'vcl60.bpl'. Read of address 00000254'. Proccess stopped. Use > Step or Run to continue.
- Comments:
- Yeah, I expected that it would be raised, but I put it here to someone say how to allocate memory for more elements on that vector after created, since
vector<TButton> Buttons(3);
does not work for the same reason test1 failed :(
- Yeah, I expected that it would be raised, but I put it here to someone say how to allocate memory for more elements on that vector after created, since
General question
How to do it for any visual component?
回答1:
All of your attempts failed for the same reason - you are trying to create an array/vector of actual TButton
object instances instead of an array/vector of pointers to TButton
instances.
To create a fixed-length array of button pointers:
TButton* Buttons[3];
...
Buttons[0] = Button1;
Buttons[1] = Button2;
Buttons[2] = Button3;
...
for(index = 0; index < 3; ++index)
{
TButton *Btn = Buttons[index];
// use Btn as needed...
}
To create a dynamic-length array of button pointers:
TButton** Buttons;
...
Buttons = new TButton*[3];
Buttons[0] = Button1;
Buttons[1] = Button2;
Buttons[2] = Button3;
...
for(index = 0; index < 3; ++index)
{
TButton *Btn = Buttons[index];
// use Btn as needed...
}
...
delete[] Buttons;
To create a vector of button pointers:
std::vector<TButton*> Buttons;
...
Buttons.push_back(Button1);
Buttons.push_back(Button2);
Buttons.push_back(Button3);
...
for(index = 0; index < 3; ++index)
{
TButton *Btn = Buttons[index];
// use Btn as needed...
}
/*
Or:
for(std::vector<TButton*>::iterator iter = Buttons.begin(); iter != Buttons.end(); ++iter)
{
TButton *Btn = *iter;
// use Btn as needed...
}
*/
回答2:
All this is very nice and correctly true. But I mean the user’s question was some other intention. If for all the buttons we get each of them index does no special benefit - this is only a true method: the aim is to control all components with a click (button, panels, shapes and so on…) and don’t write for each index a new code, That why I changed a few program’s code:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
typedef TPanel* TPanels;
TPanels Panels[3] = {Panel1, Panel2, Panel3};
int count;
for(count=0;count<3;count++)
Panels[count]->Left=random(100);
}
As one can see instead of index
here is count
. Certainly don’t forget insert randomize()
to TForm1
回答3:
Miraculous Typedef + Pseudo Array = Solution
Miraculous Typedef:
After hours searching a way, I saw a
typedef
on that Stack Overflow and Google search journey and thought why not to:typedef TButton* TButtons;
Well, it changes all the things, because I could perform:
TButtons Buttons[3];
Pseudo Array:
The issue remained on how to allocate memory for data stored on that
Buttons[3]
array, but with knowledge of 2nd paragraph of Purpose section of my question, I thought: forget new data, data is there, point to there (so I call that to build a pseudo array, because I create only an array of pointers to existing data):TButtons Buttons[3] = {Button1, Button2, Button3};
- Where
Button1
,Button2
andButton3
were already created when I put them on the form normally (through my mouse).
Working example
- Create a new vcl/forms application project;
- Put 3 buttons as those on the left on figure bellow (
Button1
,Button2
,Button3
) to demonstrate that solution, and 1 great button (Button4
) also as figure bellow to do the actions; Insert following code on click event of the fourth button, the great one (
Button4
);typedef TButton* TButtons; TButtons Buttons[3] = {Button1, Button2, Button3}; int index; for(index=0;index<3;index++) { Buttons[index]->Caption=(AnsiString)"teste "+index+" - "+(1+random(100)); Buttons[index]->Left=25+4*random(100); Buttons[index]->Top=25+4*random(100); }
- Perform a "shazam!" run and play with that...
来源:https://stackoverflow.com/questions/12325918/how-to-create-an-array-of-buttons-on-borland-c-builder-and-work-with-it