7

Delphi の VirtualStringTree を使用したことがある人なら誰でも、これが優れたコントロールであることに同意するでしょう。これは「仮想」コントロールです (データは別の場所に保持する必要があります) ので、そのようなタスクに最適なデータ構造を考えていました。データ構造が階層をサポートする必要があるというIMOは、高速で簡単に拡張できる必要があります。最も簡単な実装はレコードを使用することであり、それは見つけることができるほとんどのドキュメントが示唆していることです。しかし、高速なルックアップや合計の計算などを行う必要がある場合はどうすればよいでしょうか? VirtualStringTree と一緒に使用しているデータ構造は何ですか?

EDIT1 : Delphi 2010 を使用しています。

OK、私の要件についてもう少し詳しく説明します。データ サイズは、1 アイテムから数千アイテムまで非常に可変です。各アイテムは、複数の文字列、整数値を保持できます。ランダム アクセスが必要です。データは、アプリケーションの有効期間中に何度も変更される可能性があります。優れたパフォーマンスは非常に望ましいものです。データの保存と再読み込みも必要です。

EDIT2:1つの回答を得たので、私の意見をコメントしようと思います. Dorin さん、ご回答ありがとうございます。しかし、あなたの構造はあまり便利ではないと思います。1)階層を扱いません。2) ノードごとに個別の TStringList または TList を持つことは、あまり効果的ではありません。この実装では、現在のノードのデータしか検索できませんが、ツリー全体を効果的に検索することはできません。

このデータ構造は木のようなものでなければならないと思います。子を追加できるノードが必要です。次に、OnInitNode イベントでノードのデータを取得し、ノードに子があるかどうかを確認し、その場合は ivsHasChildren フラグを設定し、OnInitChildren イベントで正しい子の数を設定します。OnGetText イベントの後半で、必要なデータをノード構造からフェッチし、Column インデックスに基づいて CellText に設定することができました。私の考えは、別のデータ構造を持ち、必要なすべての操作を VirtualStringTree を使用せずに実行することです。誰かが私の主張を理解してくれることを願っています:)。

EDIT3:私が探しているものを達成するために一目で使用できる非常に興味深いJclTreesユニットを見つけました。JCLライブラリに属します。適切なドキュメントがないため、その機能を迅速に調査することが難しくなっています。もう少し時間があれば、もっと深く調べてみようと思います。

4

3 に答える 3

4

OK、与えられた回答では問題が解決しなかったので、TVirtualStringTree を模倣し、質問で言及したすべての問題を処理する独自のツリー データ構造を作成しました。これで、必要に応じてデータ構造のみを使用できるようになり、その中のすべての変更が VirtualStringTree を自動的に更新します。後でソースコードをどこかにアップロードして、ここにリンクを投稿すると思います。すべての答えをありがとう。

編集: ソースを Google コードにアップロードしました: svTrees。それがどのように機能するかを示す小さなデモがあります。

于 2011-01-21T07:40:17.580 に答える
3

Delphi のバージョンを指定していないため、次のようになります。

レコードを使用することをお勧めします(レコードのメソッドを追加した Delphi のバージョンはわかりません。D7 から D2010 に移動しました)。

type
  TMyRecordWithMethods = record
    function GetMeAResult: Integer;
    procedure DoSomething(const AInParam: Integer; var AOutParam: Integer);
  end;

お使いのバージョンの Delphi がメソッドを含むレコードをサポートしておらず、ノードのメソッドが本当に必要な場合は、オブジェクトを使用してこれを達成する必要があります。ジェネリックも調べてください。

数千のアイテムしか保持する必要がないため、ジェネリックを使用することをお勧めします(車輪のIMHOを再発明する必要はありません)。

uses ..., Generics.Collections;

type
  TMyNode = class(TObject)// you can leave this out if you like
    MyIntList: TList<Integer>; // you can do lookups, you have to implement your own saving/loading methods
    MyStringList: TStringList or TList<string>; // you can do lookups in both cases, use TStringList for save/load of data
  end;

ここで、仮想ツリーからすべてのアイテムを保存し、後でロードしたいと仮定します。これは、独自のファイル構造を定義することで実行できます。

type
  TMyFileHeader = record
    CountItems: Integer; // number of items in the tree
    ...
  end;

const
  szMyFileHeader = SizeOf(TMyFileHeader);

type
  TMyItemEntry = record
    CountInt: Integer; // number of integer values
    ...
  end;

const
  szMyItemEntry = SizeOf(TMyItemEntry);

次に、ロードと保存を実装する必要があります。TFileStream を使用して保存とロードを行うことをお勧めします。非常に簡単です。

疑似コード、申し訳ありませんが部分的なコードの時間ではありません:-\

a) コンテンツの保存:

  • 項目数を TMyFileHeader 変数に保存し、ファイルに書き込みます

  • ツリーの各項目について、整数リストを保存し、文字列リストを保存します

b) コンテンツのロード:

  • ファイル ヘッダーの読み取り -- ファイルから読み取る必要がある項目の数がわかるようにします。

  • for Index := 0 to Count -1 を実行し、ファイルからアイテムを読み取ります

注: 各項目の文字列リストをファイル ストリームの現在の位置に直接保存できますが、次を使用して直接保存することをお勧めします。

FileStream.WriteBuffer(PChar(AStringList.Text)^, Length(AStringList.Text) * SizeOf(Char));

これがお役に立てば幸いです。コードの実際の実装はあなた次第です。楽しんでください!!

于 2011-01-16T21:41:43.217 に答える
0

TXMLDocument を使用できます。

そこに入れるものをより細かく制御したい場合は、必要な構造を記述した xsd を作成し、XML データ バインディング ウィザードを使用して、使用できる Delphi コードを生成することをお勧めします。

このスキーマ

代替テキスト

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:complexType name="itemType">
        <xs:sequence>
            <xs:element name="id" type="xs:int"/>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="itemlist" type="itemlistType" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="itemlistType">
        <xs:sequence>
            <xs:element name="item" type="itemType" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
    <xs:element name="root">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="itemlist" type="itemlistType"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

Delphiで使用するこれらのインターフェースを提供します

  IXMLRoot = interface(IXMLNode)
    ['{16C6C960-58B7-400C-9E46-7ACC7BEF276F}']
    { Property Accessors }
    function Get_Itemlist: IXMLItemlistType;
    { Methods & Properties }
    property Itemlist: IXMLItemlistType read Get_Itemlist;
  end;

{ IXMLItemlistType }

  IXMLItemlistType = interface(IXMLNodeCollection)
    ['{59F80BAC-887E-48DF-8288-95276BF9DCE7}']
    { Property Accessors }
    function Get_Item(Index: Integer): IXMLItemType;
    { Methods & Properties }
    function Add: IXMLItemType;
    function Insert(const Index: Integer): IXMLItemType;
    property Item[Index: Integer]: IXMLItemType read Get_Item; default;
  end;

{ IXMLItemType }

  IXMLItemType = interface(IXMLNode)
    ['{1218DD35-C3EF-40E6-831A-1A4AA0782C36}']
    { Property Accessors }
    function Get_Id: Integer;
    function Get_Name: WideString;
    function Get_Itemlist: IXMLItemlistType;
    procedure Set_Id(Value: Integer);
    procedure Set_Name(Value: WideString);
    { Methods & Properties }
    property Id: Integer read Get_Id write Set_Id;
    property Name: WideString read Get_Name write Set_Name;
    property Itemlist: IXMLItemlistType read Get_Itemlist;
  end;
于 2011-01-18T10:16:20.650 に答える