[Delphi/Tip] TListView에서 ListItem 순서바꾸기/이동
[개발 실전에서 바로 활용 가능한 라이브 코드 만들기]
이번에는 기본 리스트뷰 컴포넌트인 TListView에서 등록된 아이템(TListItem)들간의 순서를 바꾸거나 이동 하는 방법에 대해 알아 보자.
이 프로젝트를 통해서 객체와 그 객체를 목록으로 가지고, 객체 목록을 리스트뷰와 연동하여 관리하는 방법을 덤으로 배울 수 있다.
또한 리스트아이템(ListItem) 또는 노드(TTreeView에서의 표현)간에 버튼을 이용하거나 드래그 드롭(Drag&Drop)을 이용해 이동할 때 궁극적으로 재사용이 가능한 위치 이동 함수를 만들어 보자
우리가 아마도 두개의 방을 바꾼는 알고리즘을 배웠을 것이다. 두개의 방을 바꾸기 위한 임시 방을 만드는 방법이 여기에 적용 된다.
리스트아이템(TListItem)간의 이동을 위한 중요한 핵심 코드는 다음과 같다.
//TListView에서 순서를 가진 두개의 TListItem의 위치를 교환 한다. procedure ExchangeListItems(ListView : TListView; const Idx1, Idx2: Integer); var tempLI: TListItem; begin ListView.Items.BeginUpdate; try tempLI := TListItem.Create(ListView.Items); tempLI.Assign(ListView.Items.Item[Idx1]); ListView.Items.Item[Idx1].Assign(ListView.Items.Item[Idx2]); ListView.Items.Item[Idx2].Assign(tempLI); ListView.Selected := ListView.Items[Idx2]; tempLI.Free; finally ListView.Items.EndUpdate; end; end; // 실 사용 방법은 다음과 같다. ExchangeListItems(ListView1, 1, 2); //TListView에서 두번째 아이템과 세번째 아이템을 서로 바꾼다
프로젝트 전체의 소스는 다음과 같으니 아이템간의 바꾸기 외에도 리스트뷰와 객체를 어떻게 효율적으로 연동해서 사용하는지 배울 수 있으니 코드를 살펴 보기를 권장한다.
unit uDemoExchangeListItem; {** 리스튜뷰의 아이템(TListItem)의 순서를 변경할 수 있는 샘플 프로젝트 Author : Dukwoo Lee(niceondal@gmail.com) Date : 2018-11-01 주요기능 : - 객체를 리스트로 관리하고 리스트뷰에 객체 목록을 연동하는 매커니즘을 이해한다. - 리스트뷰의 노드(아이템)의 순서를 바꿀 수 있다. *} interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, contnrs, Vcl.ComCtrls, Vcl.StdCtrls; type //데모 객체 클래스 TSite = class private //사이트명 FSiteName : String; //URL FURL : String; //대표자 FCeo : String; //주소 FAddress : String; end; //객체 리스트 클래스 //리스트가 해제 될 때 리스트에 담긴 객체도 자동 해제처리 하기 위해 TObjectList를 사용했으며 //TObjectList를 사용하려면 Uses절에 "contnrs" 유닛을 포함해 주어야 한다. //TList를 상속 받는다면 리스트에 포함된 모든 객체는 따로 해제해 주는 부분이 있어야 한다. TSiteList = class(TObjectList) private function _GetSite(nIdx: Integer): TSite; property Items[nIdx : Integer] : TSite read _GetSite; end; TfrmExchangeListItem = class(TForm) lvListView: TListView; btnUp: TButton; btnDown: TButton; procedure btnUpClick(Sender: TObject); procedure btnDownClick(Sender: TObject); procedure lvListViewCustomDrawItem(Sender: TCustomListView; Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean); private FSiteList: TSiteList; { Private declarations } //데모를 위한 샘플 데이터를 생성한다. procedure InitSampleData; //ListItem에 지정된 객체를 표시한다. procedure DrawListItem(Item : TListItem; ASite : TSite); //리스트 객체를 TListView에 적용한다. procedure DrawItems; public { Public declarations } property SiteList : TSiteList read FSiteList write FSiteList; constructor Create(AOwner : TComponent); override; destructor Destroy; override; end; var frmExchangeListItem: TfrmExchangeListItem; implementation {$R *.dfm} //TListView에서 순서를 가진 두개의 TListItem의 위치를 교환 한다. procedure ExchangeListItems(ListView : TListView; const Idx1, Idx2: Integer); var tempLI: TListItem; begin ListView.Items.BeginUpdate; try tempLI := TListItem.Create(ListView.Items); tempLI.Assign(ListView.Items.Item[Idx1]); ListView.Items.Item[Idx1].Assign(ListView.Items.Item[Idx2]); ListView.Items.Item[Idx2].Assign(tempLI); ListView.Selected := ListView.Items[Idx2]; tempLI.Free; finally ListView.Items.EndUpdate; end; end; { TfrmExchangeListItem } procedure TfrmExchangeListItem.btnDownClick(Sender: TObject); begin //선택된 아이템이 있고 첫번째 아이템이 마지막이 아닌경우만 실행 if (lvListView.Selected<>nil) and (lvListView.Selected.Index<lvListView.Items.Count-1) then ExchangeListItems(lvListView, lvListView.Selected.Index, lvListView.Selected.Index+1); end; procedure TfrmExchangeListItem.btnUpClick(Sender: TObject); begin //선택된 아이템이 있고 첫번째 아이템이 아닌 경우만 실행 if (lvListView.Selected<>nil) and (lvListView.Selected.Index>0) then ExchangeListItems(lvListView, lvListView.Selected.Index, lvListView.Selected.Index-1); end; constructor TfrmExchangeListItem.Create(AOwner: TComponent); begin inherited; //리스트객체 생성 FSiteList := TSiteList.Create; InitSampleData; DrawItems; end; destructor TfrmExchangeListItem.Destroy; begin //리스트객체 해제 FSiteList.Free; inherited; end; //SiteList 리스트 객체를 TListView에 할당 procedure TfrmExchangeListItem.DrawItems; var i : integer; lt : TListItem; siteObj : TSite; begin lvListView.Items.Clear; for i := 0 to SiteList.Count-1 do begin siteObj := SiteList.Items[i]; lt := lvListView.Items.Add; DrawListItem(lt, siteObj); end; end; //하나의 Site객체를 리스트아이템(ListItem)에 할당 procedure TfrmExchangeListItem.DrawListItem(Item: TListItem; ASite : TSite); begin if Item=nil then exit; if Item.SubItems.Count=0 then begin Item.SubItems.Add(''); Item.SubItems.Add(''); Item.SubItems.Add(''); Item.SubItems.Add(''); end; Item.SubItems[0] := ASite.FSiteName; Item.SubItems[1] := ASite.FURL; Item.SubItems[2] := ASite.FCeo; Item.SubItems[3] := ASite.FAddress; Item.Data := ASite; end; //데모를 위한 초기 샘플 데이터 생성 procedure TfrmExchangeListItem.InitSampleData; var site : TSite; begin SiteList.Clear; site := TSite.Create; site.FSiteName := '네이버'; site.FUrl := 'http://www.naver.com'; site.FCeo := '한성숙'; site.FAddress := '경기도 성남시 분당구 불정로 6 NAVER그린팩토리'; SiteList.Add(site); site := TSite.Create; site.FSiteName := '다음'; site.FUrl := 'http://www.daum.net'; site.FCeo := '여민수'; site.FAddress := '제주특별자치도 제주시 첨단로 242 '; SiteList.Add(site); site := TSite.Create; site.FSiteName := '조선일보'; site.FUrl := 'http://www.chosun.com/'; site.FCeo := '방우영'; site.FAddress := '서울특별시 중구 세종대로21길 30'; SiteList.Add(site); site := TSite.Create; site.FSiteName := '경향신문'; site.FUrl := 'http://www.khan.co.kr'; site.FCeo := '이동현'; site.FAddress := '서울시 중구 정동길 3 경향신문사'; SiteList.Add(site); site := TSite.Create; site.FSiteName := '한겨레신문'; site.FUrl := 'http://www.hani.co.kr/'; site.FCeo := '양상우'; site.FAddress := '서울특별시 마포구 효창목길 6'; SiteList.Add(site); end; procedure TfrmExchangeListItem.lvListViewCustomDrawItem(Sender: TCustomListView; Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean); begin if Item=nil then exit; Item.Caption := IntToStr(Item.Index+1); end; { TSiteList } function TSiteList._GetSite(nIdx: Integer): TSite; begin result := TSite(Get(nIdx)); end; end.
도움이 되셨다면 광고 한 번만 클릭 매너^^
프로젝트 소스 다운로드 : demoExchangeListItem.zip
'프로그래밍 > Delphi' 카테고리의 다른 글
MS Excel 데이터 읽고 쓰기 (0) | 2020.08.07 |
---|---|
[델파이/Tips] 관리자 권한으로 실행하기 (2) | 2019.02.20 |
[Delphi/Tip] 웹페이지 URL 유효성 검토 (0) | 2018.11.01 |
[Demo-Delphi]웹브라우저에서 자바스크립트로 델파이 코드 실행하기 (0) | 2018.10.30 |
[Delphi/Tip] 디렉토리 선택 다이얼로그 호출하기 (0) | 2018.10.18 |