Delphi 12多设备表单ListView添加图片不显示问题求助
Delphi 12多设备ListView加载网络图片空白问题修复
问题说明
在Delphi 12多设备表单中使用ListView加载网络JPG图片时,仅显示空白区域。当前代码为了判空两次调用图片下载函数,尝试过表格、ImageList存储图片的示例但未解决问题。
现有代码
主逻辑代码
var jsa: TJSONArray; jso : TJsonObject; i: Integer; Name: String; LItem: TListViewItem; begin if Length(S) > 10 then begin jso := TJSonObject.ParseJSONValue(S) as TJsonObject; if jso <> nil then Try jsa := jso.GetValue('results') as TJSONArray; if Jsa.Count > 0 then begin for I := 0 to jsa.Count-1 do begin LItem := ListView1.Items.Add; if GetImageFromURL(jsa[i].GetValue<string>('image')) <> nil then LItem.Bitmap := GetImageFromURL(jsa[i].GetValue<string>('image')); LItem.Detail := jsa[i].GetValue<string>('text'); LItem.Text := jsa[i].GetValue<string>('expire'); end; end; Finally jso.Free; End; end;
获取网络图片函数
function TPromoForm.GetImageFromURL(const S: String): TBitmap; var ms : TMemoryStream; httpCli : TNetHTTPClient; resp : IHTTPResponse; url : String; Image: TBitmap; begin result := nil; httpCli := TNetHTTPClient.Create(nil); try httpCli.UserAgent := 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0'; ms := TMemoryStream.Create(); Image := TBitmap.Create; Image := nil; try url := S; resp := httpCli.Get(url, ms); if resp.StatusCode <> 200 then Showmessage(Format('HTTP Error=%d %s', [resp.StatusCode, resp.StatusText])) else begin try Image := TBitmap.Create; ms.Position := 0; Image.LoadFromStream(ms); result := Image; finally Image.Free; end; end; finally ms.Free; end; finally httpCli.Free; end; end;
问题分析与修复方案
1. 核心内存错误导致图片丢失
在GetImageFromURL函数中,加载好的Image赋值给result后,立刻在finally块执行Image.Free,导致返回的TBitmap指针指向已释放的内存,ListView无法正常显示图片。
修复后的GetImageFromURL函数:
function TPromoForm.GetImageFromURL(const S: String): TBitmap; var ms : TMemoryStream; httpCli : TNetHTTPClient; resp : IHTTPResponse; url : String; begin Result := nil; httpCli := TNetHTTPClient.Create(nil); try httpCli.UserAgent := 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0'; ms := TMemoryStream.Create(); try url := S; resp := httpCli.Get(url, ms); if resp.StatusCode = 200 then begin Result := TBitmap.Create; try ms.Position := 0; Result.LoadFromStream(ms); except Result.Free; Result := nil; raise; end; end else begin Showmessage(Format('HTTP Error=%d %s', [resp.StatusCode, resp.StatusText])); end; finally ms.Free; end; finally httpCli.Free; end; end;
2. 避免重复下载图片
原代码两次调用GetImageFromURL会重复发起HTTP请求,浪费资源且降低效率。修改主逻辑,仅调用一次并缓存结果:
var jsa: TJSONArray; jso : TJsonObject; i: Integer; LItem: TListViewItem; imgBitmap: TBitmap; begin if Length(S) > 10 then begin jso := TJSonObject.ParseJSONValue(S) as TJsonObject; if jso <> nil then Try jsa := jso.GetValue('results') as TJSONArray; if Jsa.Count > 0 then begin for I := 0 to jsa.Count-1 do begin LItem := ListView1.Items.Add; imgBitmap := GetImageFromURL(jsa[i].GetValue<string>('image')); if imgBitmap <> nil then LItem.Bitmap := imgBitmap else LItem.Bitmap := nil; // 可替换为默认占位图 LItem.Detail := jsa[i].GetValue<string>('text'); LItem.Text := jsa[i].GetValue<string>('expire'); end; end; Finally jso.Free; End; end;
3. 多设备下额外注意事项
- 确保ListView的
ItemAppearance设置为包含图片的样式(如DynamicAppearance并添加Image项) - 跨平台环境下需引用
Vcl.Imaging.jpeg单元以支持JPG格式加载 - 若图片尺寸过大,可在加载后缩放至ListView适配大小,避免显示异常
内容的提问来源于stack exchange,提问作者Kim HJ
相关产品推荐
相关产品推荐

