【问题标题】:Firemonkey: TGrid usage on Embarcadero C++ Builder XE3Firemonkey:在 Embarcadero C++ Builder XE3 上使用 TGrid
【发布时间】:2013-03-10 17:41:08
【问题描述】:

我正在尝试构建一个从数据库读取数据并使用 Firemonkey 中的 TGrid 将其显示为表格的工具。我需要使用不同类型的列,例如 TCheckColumn 和 TPopupColumn,但找不到任何关于如何在 C++ Builder 中使用它们的好的指南或示例。

无论如何,我设法理解了在 TGrid 的事件 onGetValue 中设置单元格值的 TStringColumn、TProgressColumn 的用法。

有谁知道如何为 TCheckColumn、TImageColumn 和 TPopupColumn 类型的列设置 Value?

谢谢 丹尼尔

---更新---

我设法使用了 TProgressColumn。这就是我在表单的构造函数中所做的:

// TStringColumn
Grid1->AddObject(new TStringColumn(this));
// TCheckColumn
TCheckColumn* c = new TCheckColumn(this);
Grid1->AddObject(c);
// TPopupColumn
// list of values
TStringList * l = new TStringList(NULL);
l->Add(L"First");
l->Add(L"Second");
l->Add(L"Third");
TPopupColumn* p = new TPopupColumn(this);
// adding the list to the PopupColumn
p->Items = l;
Grid1->AddObject(p);
// TProgressColumn
Grid1->AddObject(new TProgressColumn (this));
Grid1->RowCount = 3 ;

这是 Grid1GetValue 方法:

// TStringColumn
if(Col == 0) Value = TValue::From<String>(Row);
// TCheckColumn  !! Can't make it work
if(Col == 1) Value = TValue::From<Boolean>(true);
// TPopupColumn
if(Col == 2)    Value = TValue::From<int>(2);
// TProgressColumn
if(Col == 3)    Value = TValue::From<double>(50.0);

---更新---

如果我使用 OnSetValue 方法保存列的值

void __fastcall TForm1::Grid1SetValue(...)
{
if(Col == 1) check = Value;
}

然后用 OnGetValue 方法设置:

void __fastcall TForm1::Grid1GetValue(...)
{
// TCheckColumn  !! Can't make it work
if(Col == 1) Value = check;// TValue::From<Boolean>(true);
}

单击一个复选框后,所有其他复选框都会更改状态。所以组件可以正常工作...现在的重点是如何以正确的方式将 Value 设置为 true 或 false。

【问题讨论】:

    标签: c++builder firemonkey c++builder-xe firemonkey-fm2 tgrid


    【解决方案1】:

    TGris 不存储任何数据,您应该创建自己的数据存储。

    示例:带有 TCheckColumn、TStringColumn 和 TPopupColumn 的 TGrid

    type
      TField = record
        Checked:  Boolean;
        Name:     string;
        Column:   Byte;
      end;
    
    var
      Fields: TList<TField>;
    
    function SetField(const AChecked: Boolean; const AName: string; const AColumn: Byte): TField;
    begin
      with Result do begin
        Checked := AChecked;
        Name    := AName;
        Column  := AColumn;
      end;
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    var
      I: Integer;
    begin
      Fields := TList<TField>.Create;
      Fields.Add(SetField(True, 'Name', 1));
      Fields.Add(SetField(True, 'Login', 2));
      Fields.Add(SetField(True, 'Password', 3));
      for I := 1 to Fields.Count do
        PopupColumn1.Items.Add('Column ' + IntToStr(I));
      gdFields.RowCount := Fields.Count;
    end;
    
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      Fields.Free;
    end;
    
    procedure TFormExport.gdFieldsGetValue(Sender: TObject; const Col, Row: Integer; var Value: TValue);
    begin
      case gdFields.Columns[Col].TabOrder of
        0:  Value := Fields[Row].Checked;
        1:  Value := Fields[Row].Name;
        2:  Value := Fields[Row].Column - 1;
      end;
    end;
    
    procedure TFormExport.gdFieldsSetValue(Sender: TObject; const Col, Row: Integer; const Value: TValue);
    var
      FRec: TField;
    begin
      FRec := Fields[Row];
      case gdFields.Columns[Col].TabOrder of
        0:  FRec.Checked := Value.AsBoolean;
        1:  FRec.Name    := Value.AsString;
        2:  FRec.Column  := Value.AsInteger + 1;
      end;
      Fields[Row] := FRec;
    end;
    

    现在,您的数据存储中的所有数据将在编辑 TGrid 后更改,但 TGrid 中可能存在错误 - 更改 PopupColumn 后从未收到 OnSetValue

    【讨论】:

      【解决方案2】:

      我无法提供 C++ 代码,但 Delphi 示例应该很容易翻译。

      您以相同的方式获取和设置所有单元格值,通过侦听 OnGetData 和 OnSetData 事件,获取 TValue 类型(XE3 及更高版本)的获取/提供值。这只是在 TValue 中返回适当类型的情况:

      uses System.RTTI;
      
      procedure Form1.Grid1GetValue(Sender: TObject;const Col, Row: Integer;var Value: TValue);
      begin
        if Col = 1 then
          Value := TValue.From<Integer>(1)
        else if Col = 2 then
          Value := TValue.From<String>('Hello')
        else if Col = 3 then
          Value := Tvalue.From<Single>(1.0);
      end;
      
      procedure Form1.Grid1SetValue(Sender: TObject;const Col, Row: Integer;const Value: TValue);
      begin
        if Col = 1 then
          I := Value.As<Integer>
        else if Col = 2 then
          St := Value.As<String>
        else if Col = 3 then
          Si := Value.As<Single>;
      end;
      

      据我所知,弹出菜单不能接受或提供数据。

      【讨论】:

      • 实际上代码非常相似(我已将我的代码放在帖子的更新中)。你用过 TCheckColumn 吗?
      • 您在设置值时遇到问题,还是 CheckColumn 忽略了您设置的值?
      • 其实我刚刚发现,如果我在 OnSetValue 方法中保存单元格的值,然后在 OnGetValue 方法中将其分配给单元格,其他行会改变它的状态。
      • 您是在谈论保存 TValue 还是从中提取的内容?
      【解决方案3】:

      为了解决您的问题,请按以下方式重新定义TCheckCell 类:

      #include <FMX.Grid.hpp>
      #include <boost/dynamic_bitset.hpp>
      
      class CheckCellClass:public TCheckCell
      {
      public:
       __fastcall virtual CheckCellClass(System::Classes::TComponent*AOwner):TCheckCell(AOwner)
       {
       };
      
       virtual System::Rtti::TValue __fastcall GetData(void)
       {
        return TValue::From<bool>(this->IsChecked);
       };
      
       virtual void __fastcall SetData(const TValue&Value)
       {
        TValue V(Value);
        this->IsChecked=V.AsBoolean();
       };
      };
      
      //Redifine TCheckColumn class
      class CheckColumnClass:public TCheckColumn
      {
      private:
       virtual Fmx::Controls::TStyledControl*__fastcall CreateCellControl(void)
       {
        CheckCellClass*Cell=new CheckCellClass(this);
        Cell->OnChange     =&(this->DoCheckChanged);
        return Cell;
       };
      
      public:
      __fastcall CheckColumnClass(System::Classes::TComponent*AOwner):TCheckColumn(AOwner)
       {
       };
      };
      
      //global Data for Save curent State Cell
      
      boost::dynamic_bitset<unsigned char>FullDiscreteInputs;
      
      Add To Grid In Constuctor
       FullDiscreteInputs.resize(100);
       DiscreteInputsGrid->RowCount=FullDiscreteInputs.size();    
       CheckColumnClass* DiscreteInPutsCheckColumn        =new CheckColumnClass(DiscreteInputsGrid);
       DiscreteInputsGrid->AddObject(CoilsCheckColumn);
      
      void __fastcall TForm1::DiscreteInputsGridGetValue(TObject*Sender, const int Col, const int Row,TValue&Value)
      {
       //...
      
       if(DiscreteInputsGrid->ColumnByIndex(Col)==DiscreteInPutsCheckColumn)
       {
       Value=TValue::From<bool>(FullDiscreteInputs[Row]);
       }
       //...
      }
      
      //---------------------------------------------------------------------------
      void __fastcall TForm1::DiscreteInputsGridSetValue(TObject*Sender, const int Col, const int Row, const TValue&Value)
      {
       TValue V(Value);
       if(DiscreteInputsGrid->ColumnByIndex(Col)==DiscreteInPutsCheckColumn)
       {
       FullDiscreteInputs[Row]=V.AsBoolean();
       }
      }
      //---------------------------------------------------------------------------
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-10
        • 1970-01-01
        相关资源
        最近更新 更多