我正在delphi(RAD Studio)创建一个项目。在某些行的数据库表中存储了图像。我想在运行时提取图像(我使用的是TMemoryStream数组)并在frxReport中显示它们。
我的代码段如下
公共变量TStream声明为
Stream2 : Array of TStream; i,k: integer
视图按钮点击事件的代码段,该事件放在MainForm上,预计显示为frxReport。
`
procedure TFrmMain.btnViewClick(Sender: TObject);
begin
i := 0;
k := 0;
UniTable1.SQL.Text := 'Select * from userplays order by id';
UniTable1.Execute;
rowcount := UniTable1.RecordCount;
SetLength(myid, rowcount);
SetLength(mydesc, rowcount);
SetLength(myimg, rowcount);
SetLength(Stream2, rowcount);
while not UniTable1.Eof do
begin
try
Stream2[k] := TMemoryStream.Create;
myid[k] := UniTable1.FieldByName('id').Value;
Stream2[k] := UniTable1.CreateBlobStream(TBlobField(UniTable1.FieldByName('image')), bmRead);
mydesc[k] := UniTable1.FieldByName('description').Value;
UniTable1.Next;
inc(k);
finally
//Stream2[k].Free;
end;
end;
frxUserDataSet1.RangeEnd := reCount;
frxUserDataSet1.RangeEndCount := rowcount;
frxReport1.ShowReport;
i := 0;
end;
`
但是,此方法未将任何图像加载到Stream2阵列。有一个选项可以使用JPEGImage数组但是如果使用了JPEGImage数组,那么在frxRaport上显示它会有问题
procedure TFrmMain.frxReport1GetValue(const VarName: string; var Value: Variant);
`
Graphic := TJPEGImage.Create;
Graphic.LoadFromStream(Stream2[j]);
TfrxPictureView(frxreport1.FindObject('Picture1')).Picture.Graphic := Graphic;
` 请告诉我如何做到这一点。
答案 0 :(得分:3)
但是,此方法未将任何图像加载到Stream2数组
在您当前的代码中,您首先将新创建的TMemoryStream
分配给Stream2[k]
:
Stream2[k] := TMemoryStream.Create;
然后你抛弃TMemoryStream
(创建内存泄漏)并用你创建的blob流替换它:
Stream2[k] := UniTable1.CreateBlobStream(TBlobField(UniTable1.FieldByName('image')), bmRead);
但你从未读过blob流。
这里重写while
循环(未经测试)
var
blobstream: TStream;
Stream2: array of TMemoryStream;
....
// read 'id', 'description' and 'image' fields to respective arrays
while not UniTable1.Eof do
begin
myid[k] := UniTable1.FieldByName('id').Value;
mydesc[k] := UniTable1.FieldByName('description').Value;
blobstream := UniTable1.CreateBlobStream(TBlobField(UniTable1.FieldByName('image')), bmRead);
try
Stream2[k] := TMemoryStream.Create;
Stream2[k].LoadFromStream(blobstream);
finally
blobstream.Free;
end;
UniTable1.Next;
inc(k);
end;
顺便说一句,我建议定义一条记录,将id
,description
和image
放在一起,然后是一组记录,而不是三个独立的数组。更简单的是只管理一个数组而不是三个。
答案 1 :(得分:2)
我认为在你的情况下最明显的事情就是将现有的DataSet(Unitable1)直接连接到frxReport中的DataBand。我不明白为什么你需要使用frxUserDataset而不是frxDBDataset,因为你的DataSet属性设置为Unitable1,无论如何都是这样。
如果你真的需要一个对象列表,那么我会采取不同的方法。 你的多个全局变量看起来很丑陋并且很危险(i,k ......)
我会创建一个包含数据的类,并将这些数据填充到一个 来自System.Generics.Collection的TObjectList:
unit DataPack;
interface
uses ExtCtrls...System.SysUtils;
type
TMyDataPack = class(TObject)
private
Query: TFDQuery; //O r TUniQery
_MyId: Integer;
_MyDescription: String;
_MyImage: TImage;
_Loaded: Boolean;
function LoadData: boolean;
protected
public
constructor Create(Data: TFDQuery); //Or Uniquery
property MyId: Integer read _MyId;
property MyDescription: String read _MyDescription;
property MyImage: TImage read _MyImage;
property Loaded: Boolean read _Loaded;
end;
implementation
{ TMyDataPack }
constructor TMyDataPack.Create(Data: TFDQuery);
begin
Inherited Create;
Query:=Data;
_Loaded:=true;
if not (LoadData) then
_Loaded:=false;
end;
function TMyDataPack.LoadData: boolean;
var
Stream: TStream;
begin
Stream:= TStream.Create;
Stream:=Query.CreateBlobStream(TBlobField(Query.FieldByName('image')), bmRead);
try
_MyImage:=TImage.Create(nil);
_MyImage.Picture.Bitmap.LoadFromStream(Stream);
_MyDescription:=Query.FieldByName('description').AsString;
_MyId:=Query.FieldByName('CategoryId').AsInteger;
except on E: Exception do
begin
FreeAndNil(Stream);
FreeAndNil(_MyImage);
Exit(false);
end;
end;
FreeAndNil(Stream);
Result:=true;
end;
end.
然后在你的主要代码中:
procedure TMain.Button2Click(Sender: TObject);
var
DataRow: TMyDataPack;
List: TObjectList<TMyDataPack>;
Num: integer;
CurrentImage: TImage;
CurrentDescription: String;
CurrentId: integer;
begin
UniTable1.SQL.Text:='SELECT * FROM Userplays';
UniTable1.Open();
List:=TObjectList<TMyDataPack>.Create;
while not (UniTable1.Eof) do
begin
DataRow:=TMyDataPack.Create(UniTable1);
if(DataRow.Loaded) then
List.Add(DataRow);
UniTable1.Next;
End;
for Num:=0 to List.Count do
begin
CurrentDescription:=List[Num].MyDescription;
CurrentImage:=List[Num].MyImage;
CurrentId:=List[Num].MyId;
//List[Num].MyImage.Picture.SaveToFile('Some'+IntToStr(Num)+'.bmp');
// You might save it to file then...
end;
end;
end.
然后再传递一个ObjectList,记得最后释放它。
如果您需要使用具有相同数据的不同数据库,可以通过创建类工厂来创建不同的对象来进一步扩展它, 执行检查图像是否实际是Bmp或Jpg等。 您甚至可以在不设置SQL的情况下传递查询,并将TobjectList作为属性。