【问题标题】:How to create an array of buttons on Borland C++ Builder and work with it?如何在 Borland C++ Builder 上创建一组按钮并使用它?
【发布时间】:2012-09-07 21:56:53
【问题描述】:

具体问题

如何在 Borland C++ Builder 上创建一组按钮并使用它?

我正在使用 Borland C++ Builder 6 和 Borland Developer Studio 2006 (Turbo C++ 2006)。

目的

仅使用带有索引的 for 循环来处理表单上的大量按钮,例如,更改它们的标题、大小和位置。

我知道我是否有一个名为Button1 的按钮,如果我创建另一个按钮(通过TButton *Button2 = new TButton(Form1))在该按钮的点击事件中,我可以将Button1 分配给Button2Button2 = Button1)和他们我可以简单地用Button2->Caption修改Button1的标题。所以我想扩展它,将真实组件的指针分配给数组的元素,让它们通过for 循环与所有这些元素一起工作。

好吧,如果有人找到一种方法将所有按钮作为数组添加到表单上,那就更好了:)

尝试

在 TForm1::Button1Click() 上进行了以下测试,这是窗体上的按钮事件:

  • 测试 1

    • 说明:直接创建数组
    • 代码:

      TButton Buttons[3];
      
    • 结果:编译错误:

      > [C++ Error] Unit1.cpp(23): E2248 Cannot find default constructor
      > to initialize array element of type 'TButton'
      
    • 评论:
      • 我测试了这个测试的一些变体(例如TButton Buttons = new TButton[3],使用calloc函数等),但它们都指向TButton没有没有参数的构造函数的问题,即@987654334 @,但只有TButton (TComponent *AOwner)TButton(void *ParentWindow)TButton(const TButton &)
      • 有什么方法可以将运算符 newTButton 构造函数原型的参数一起用于数组?
  • 测试 2

    • 说明:创建向量
    • 代码:还要在单元标题上添加#include "vector.h"...

      vector<TButton> Buttons;
      Buttons[0].Caption="it is ok";
      Buttons[1].Caption="mayday, mayday";
      
    • 结果:第 3 行的调试器异常:

      > 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.
      
    • 评论:
      • 是的,我希望它会被提升,但我把它放在这里给某人说如何在创建后为该向量上的更多元素分配内存,因为 vector&lt;TButton&gt; Buttons(3); 不工作的原因与 test1 失败的原因相同 :(

一般问题

如何为任何可视化组件做到这一点?

【问题讨论】:

    标签: c++builder


    【解决方案1】:

    出于同样的原因,您的所有尝试都失败了 - 您正在尝试创建实际 TButton 对象实例的数组/向量,而不是 指针TButton 实例的数组/向量。

    创建一个固定长度的按钮数组指针

    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...
    }
    

    创建一个动态长度的按钮数组指针

    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;
    

    创建一个按钮向量指针

    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】:

      所有这一切都非常好,而且是正确的。但我的意思是用户的问题是其他意图。如果对于我们得到的所有按钮,每个索引都没有特别的好处——这只是一种真正的方法:目的是通过单击来控制所有组件(按钮、面板、形状等......)并且不要为每个索引一个新代码, 这就是为什么我改变了一些程序的代码:

      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);
      
      }  
      

      正如大家所见,这里不是index,而是count。当然不要忘记将randomize()插入TForm1

      【讨论】:

        【解决方案3】:

        神奇的 Typedef + 伪数组 = 解决方案

        • 神奇的Typedef:

          • 经过几个小时的搜索,我在 Stack Overflow 和 Google 搜索过程中看到了 typedef,并想为什么不这样做:

            typedef TButton* TButtons;
            
          • 嗯,它改变了一切,因为我可以表演:

            TButtons Buttons[3];
            
        • 伪数组:

          • 问题仍然存在于如何为存储在该 Buttons[3] 数组中的数据分配内存,但是根据我问题的目的部分的第二段的知识,我想:忘记新数据,数据在那里,指向那里(所以我称之为构建一个伪数组,因为我只创建一个指向现有数据的指针数组):

            TButtons Buttons[3] = {Button1, Button2, Button3};
            
          • Button1Button2Button3 在我正常(通过鼠标)放在表单上时已经创建。

        工作示例

        1. 创建一个新的 vcl/forms 应用程序项目;
        2. 如下图左侧的3个按钮(Button1Button2Button3)来演示该解决方案,1个大按钮(Button4)也如下图所示执行操作;
        3. 在第四个按钮的点击事件上插入以下代码,伟大的按钮 (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);
          }
          
        4. 执行“沙赞!”一边跑一边玩……

        【讨论】:

        • 你不需要TButtons typedef,因为你创建的是一个单独的按钮指针数组,而不是按钮列表数组:TButton* Buttons[3];。至于vector AV,那是因为您在访问其元素之前没有在vector 中放置任何内容。您必须先将指针 push_back() 指向 vector,然后才能使用 [] 运算符访问它们。
        • @RemyLebeau,我以为我之前尝试过TButton* Buttons[3];,但我发现我没有......所以为该数组元素分配地址完成它并带来一个清晰的解决方案。再次感谢:)
        • 嘿,@RemyLebeau,用你很明显的干净答案回答我的问题 :) 解决方案,然后我给你分配正确的答案(让你获得一些 SO 积分)。
        • 关于你使用push_back()的建议,我也试过了,但是TButton可能会出现同样的错误信息new操作符出现...我没有成功创建新实体,仅使用现有地址中的地址...我想如果我创建一个基于 TButton 的新类,并使用不带参数的构造函数来解决这个问题,但我还没有尝试过...
        • 不需要新建类。如果您不希望为新按钮对象分配所有者,只需将 NULL 传递给现有的 TButton 构造函数(当所有者本身被释放时,所有者将为您释放新对象)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-02
        相关资源
        最近更新 更多