아래 뜨는 Download 나 PC App Store는 모두의 프린터와 상관없는 광고입니다!!
특히 PC App Store는 악성 소프트웨어이니 절대 클릭하지 마세요!!
모두의 프린터는 어떠한 경우에도 본인인증, 회원가입, 카드결제를 요구하지 않습니다.
다운로드를 유도하는 애드센스 광고를 피로곰이 배포하는 프로그램들의 다운로드 링크로 착각하지 않도록 주의하시기 바랍니다. 피로곰이 배포하는 모든 프로그램은 본인인증, 회원가입, 이용료 결제 없이 무료로 사용가능합니다.
많이 찾는 글들...
  1. PC App Store 제거 방법
  2. Ghostscript/GhostPCL 설치 안내
  3. 파일 다운로드가 차단되는 경우
  4. 내 컴퓨터의 32비트,64비트 여부 아는법
  5. 'Windows의 PC 보호' 문제
  6. 모두의 프린터 실행후 환경설정창 뜨지 않고 무반응
  7. Ghostscript PDF변환 불가. Can't load Ghostscript DLL
  8. 대법원 인터넷 등기소, 전자소송, 경매,전자공탁등 대법원계열 사이트관련
  9. 모두의 프린터 사용후 네트워크 장애가 발생하는경우. (대법원 인터넷등기소 등)
  10. 출력시 모두의 프린터가 강제종료 되는 경우.'지원하지 않는 PDF또는 가상 프린터입니다.'
  11. 오픽(OPic), 연결상태 확인 불가 프린터, 등록되지 않은 프린터(MarkAny e-PageSAFER)
  12. YBM 토익성적표 관련(정상적인 프린터로 출력을 진행하시기 바랍니다)
  13. 리포트뷰어(ReportViewer) 관련(특수목적프린터, 문서변환 프로그램을 제거해주세요)
  14. 인터넷증명발급센터 서트피아(Certpia) 관련 안내
  15. 인강사이트 관련 - 출력에 매우 오래 걸림, PDF파일 버벅거림, PDF여는데 오래걸림 등등
  16. '잘못된 프린터 데이터를 수신하였습니다.' 문제
  17. MS서피스, 삼성 갤럭시북 등 ARM기반 랩탑, '잘못된 프린터 데이터를 수신하였습니다.' 문제

[Go언어 윈도 GUI] walkmgr에 트리뷰(TreeView) 추가 1편

이번에 모두의 PDF에 책갈피 기능을 추가하면서 PDF의 책갈피 기능이 Parent, Children 을 이용한 무한 계층구조 인지라 이런 형태를 다루는데 가장 적합한 UI요소는 아무래도 트리뷰(TreeView)라서 관련 기능을 walkmgr 에 추가해 봅니다.

MFC나 윈도 API를 다루던 시절에도 사실 트리뷰는 진짜 쓰기 싫어라 하던 놈중 하나인데요 가능하면 리스트컨트롤로 대충 땜빵해서 쓰곤 했는데 .. 계층구조를 리스트 컨트롤로 다루는건 매우 비효율적인지라 미루고 미루다 추가해 봅니다.

이런놈을 보통 트리뷰라고 하지요.. 우리가 가장 흔히 접하는 경우를 보자면

윈도 탐색기의 폴더구조를 들 수 있겠습니다. 대표적인 계층구조의 트리뷰를 사용하고 있는 놈입니다.

기존에 pirogom/walk 나 pirogom/walkmgr 을 쓰시던 분들은 go get -u 명령으로 업데이트 하시면 업데이트된 패키지를 사용 가능하실꺼구요.

walkmgr 의 트리뷰 관련 코드는

위 링크를 참고하시면 되겠습니다.

언제나 그렇듯이 walkmgr 의 사용 예제는 walkmgr_example 저장소에서 확인 가능하십니다.

이번에 추가되는 트리뷰와 관련된 코드는

위 코드를 참고하시면 되겠습니다.

우선 가장 기본적인 사용법을 설명해봅니다.

Go
func TestTreeView(t *testing.T) {
	icon1, _ := walk.NewIconFromFile("./icon/icon1.ico")
	icon2, _ := walk.NewIconFromFile("./icon/icon2.ico")

	wm := walkmgr.NewWin("트리뷰 예제", 640, 480)

	treeView := wm.NewTreeView()
	item := treeView.AddItem("1", icon1)
	item2 := item.AddItem("1-1", icon2)
	item2.AddItem("1-1-1", icon1)
	item2.AddItem("1-1-2", icon2)
	item2.AddItem("1-1-3", icon1)
	item2.AddItem("1-1-4", icon2)
	item2.AddItem("1-1-5", icon1)
	item2.AddItem("1-1-6", icon2)

	item3 := item.AddItem("1-2", icon2)
	item3.AddItem("1-2-1", icon1)
	item3.AddItem("1-2-2", icon2)
	item3.AddItem("1-2-3", icon1)
	item3.AddItem("1-2-4", icon2)
	item3.AddItem("1-2-5", icon1)
	item3.AddItem("1-2-6", icon2)

	item4 := treeView.AddItem("2", icon1)
	item4.AddItem("2-1", icon2)

	treeView.UpdateItems()

	wm.Start()
}

제가 작업중인 walkmgr 이 대부분 그렇듯이 트리뷰가 배치될 코드상 위치에서 WalkUI의 NewTreeView() 메소드를 호출하면 해당 위치에 트리뷰 객체가 추가됩니다. Split이나 Composite, GroupBox같은 레이아웃요소로 감싸는 등의 행위는 똑같이 가능 합니다.

이 NewTreeView() 메소드의 리턴값으로 walkmgr.TreeView 객체를 반환하고 이 객체로 트리뷰에 아이템을 추가하고 관리할 수 있습니다.

Go
	treeView := wm.NewTreeView()
	item := treeView.AddItem("1", icon1)
	item2 := item.AddItem("1-1", icon2)

wm.NewTreeView() 메소드로 트리뷰를 생성하고 리턴받은 treeView객체의 AddItem 메소드를 호출하면 트리뷰의 맨 상위 루트에 아이템이 추가됩니다. 이 AddItem 메소드는 추가된 아이템의 객체를 반환하고 이렇게 반환된 아이템 객체에 존재하는 AddItem 메소드 또한 해당 아이템의 하위에 새로 아이템을 추가를 해주게 됩니다.

그러니 위의 경우 

트리뷰 최상단 루트에 1이라는 이름의 루트 아이템을 추가하고 이 추가된 루트아이템 하부에 1-1 이라는 이름의 서브 아이템을 추가를 하게 되는겁니다.

이 AddItem 의 파라미터는 화면에 표시될 이름.. 타이틀이라 해야 하나요.. 보여질 문자열을 첫번째 인자로 두번째 인자는 표시될 아이콘 객체를 전달하면 되고 두번째 인자를 nil로 전달하면 아이콘 자리는 빈채로 구성됩니다. 아이콘이 없는것 보다는 있는게 좋아요..

Go
	icon1, _ := walk.NewIconFromFile("./icon/icon1.ico")
	icon2, _ := walk.NewIconFromFile("./icon/icon2.ico")

그래서 함수 상단에 icon1, icon2 파일을 미리 로드해두고 사용하도록 예제가 구성되어 있습니다.

Go
	item := treeView.AddItem("1", icon1)
	item2 := item.AddItem("1-1", icon2)
	item2.AddItem("1-1-1", icon1)
	item2.AddItem("1-1-2", icon2)
	item2.AddItem("1-1-3", icon1)
	item2.AddItem("1-1-4", icon2)
	item2.AddItem("1-1-5", icon1)
	item2.AddItem("1-1-6", icon2)

최상단 루트에 1이라는 명칭으로 아이템을 추가하고 이 추가된 아이템에 1-1을 추가하고 1-1을 추가하고 리턴받은 item2에 1-1-1~1-1-6까지를 추가해 봤습니다.

위 코드의 결과가 이렇게 나오는 것이지요.

Go
	item3 := item.AddItem("1-2", icon2)
	item3.AddItem("1-2-1", icon1)
	item3.AddItem("1-2-2", icon2)
	item3.AddItem("1-2-3", icon1)
	item3.AddItem("1-2-4", icon2)
	item3.AddItem("1-2-5", icon1)
	item3.AddItem("1-2-6", icon2)

	item4 := treeView.AddItem("2", icon1)
	item4.AddItem("2-1", icon2)

같은 개념으로 코드를 구성하면 아래와 같은 결과가 됩니다.

AddItem으로 값을 추가한 뒤에는 입력된 값이 실제 트리뷰 UI에 적용되도록 NewTreeView() 메소드로 리턴받은 트리뷰 객체의 UpdateItems() 메소드를 호출하셔야 적용됩니다.

Go
	treeView.UpdateItems()

다음으로는 .. 동적으로 아이템을 추가하는 예제를 설명해 봅니다.

Go
func TestTreeView2(t *testing.T) {
	var itemCnt int
	icon1, _ := walk.NewIconFromFile("./icon/icon1.ico")
	icon2, _ := walk.NewIconFromFile("./icon/icon2.ico")

	wm := walkmgr.NewWin("트리뷰 예제", 640, 480)

	treeView := wm.NewTreeView()
	treeView.AddItem("1", icon1)

	treeView.UpdateItems()

	wm.PushButton("루트 추가", func() {
		itemCnt++
		newItem := treeView.AddItem(fmt.Sprintf("추가됨%d", itemCnt), icon2)
		treeView.UpdateItems()
		treeView.SetCurrentItem(newItem)
	})

	wm.PushButton("서브 추가", func() {

		currItem := treeView.CurrentItem()

		if currItem == nil {
			walkmgr.MsgBox("트리뷰 아이템을 선택하세요.")
			return
		}

		itemCnt++
		newItem := currItem.AddItem(fmt.Sprintf("추가된 서브아이템%d", itemCnt), icon2)
		treeView.UpdateItems()
		treeView.SetCurrentItem(newItem)
		treeView.SetExpanded(currItem, true)

	})

	wm.Start()
}

루트 추가의 경우에는 하위로 추가되는게 아니기 때문에 그냥 NewTreeView()에서 리턴받은 객체의 AddItem 메소드를 호출하면 그만입니다. 추가후 UpdateItems()만 호출해주시면 추가된 사항이 바로 적용 됩니다.

Go
	wm.PushButton("루트 추가", func() {
		itemCnt++
		newItem := treeView.AddItem(fmt.Sprintf("추가됨%d", itemCnt), icon2)
		treeView.UpdateItems()
		treeView.SetCurrentItem(newItem)
	})

SetCurrentItem 메소드는 파라미터로 전달된 트리뷰 아이템을 현재 선택된 아이템으로 만들어 줍니다. 아이템이 많은 경우 추가된 놈이 어디 있는지 알아보기 힘들수 있음으로 제 경우 보통 이런식으로 처리합니다.

Go
	wm.PushButton("서브 추가", func() {

		currItem := treeView.CurrentItem()

		if currItem == nil {
			walkmgr.MsgBox("트리뷰 아이템을 선택하세요.")
			return
		}

		itemCnt++
		newItem := currItem.AddItem(fmt.Sprintf("추가된 서브아이템%d", itemCnt), icon2)
		treeView.UpdateItems()
		treeView.SetCurrentItem(newItem)
		treeView.SetExpanded(currItem, true)

	})

서브에 추가는 루트와 달리 특정 아이템의 서브 아이템으로 추가되는거라 선택된 현재 아이템 객체를 얻어와야 합니다. 이 짓을 해주는게 트리뷰 객체의 CurrentItem() 메소드 입니다. 현재 선택된 아이템이 없으면 이 메소드의 리턴값은 nil을 리턴합니다. 예외처리는 반드시 하셔야 겠구요.

루트에 추가시에는 트리뷰 객체에 직접 하면 되지만 서브 아이템으로 추가는 부모아이템이 있어야 함으로 현재 선택된 아이템을 부모로 서브로 생성하게 됩니다.

고로 CurrentItem 메소드로 리턴받은 아이템 객체의 AddItem 메소드로 추가를 하면 됩니다.

루트에 추가에선 안보이던 메소드가 하나 있습니다. SetExpanded .. 이놈은 첫번째 인자로 전달된 아이템의 서브 아이템들을 펼쳐놓을지 접어놓을지를 두번째 인자로 전달하시면 됩니다.

두번째 인자가 true 이면 펼쳐진 상태, false 이면 접힌상태가 되겠습니다.

트리뷰의 예는 좀더 심화 과정이 필요할것 같아서 이후에 한두개 정도 예제코드를 더 만들고 설명을 하도록 하겠습니다.

이상입니다.

많이 찾는 글들...
  1. PC App Store 제거 방법
  2. Ghostscript/GhostPCL 설치 안내
  3. 파일 다운로드가 차단되는 경우
  4. 내 컴퓨터의 32비트,64비트 여부 아는법
  5. 'Windows의 PC 보호' 문제
  6. 모두의 프린터 실행후 환경설정창 뜨지 않고 무반응
  7. Ghostscript PDF변환 불가. Can't load Ghostscript DLL
  8. 대법원 인터넷 등기소, 전자소송, 경매,전자공탁등 대법원계열 사이트관련
  9. 모두의 프린터 사용후 네트워크 장애가 발생하는경우. (대법원 인터넷등기소 등)
  10. 출력시 모두의 프린터가 강제종료 되는 경우.'지원하지 않는 PDF또는 가상 프린터입니다.'
  11. 오픽(OPic), 연결상태 확인 불가 프린터, 등록되지 않은 프린터(MarkAny e-PageSAFER)
  12. YBM 토익성적표 관련(정상적인 프린터로 출력을 진행하시기 바랍니다)
  13. 리포트뷰어(ReportViewer) 관련(특수목적프린터, 문서변환 프로그램을 제거해주세요)
  14. 인터넷증명발급센터 서트피아(Certpia) 관련 안내
  15. 인강사이트 관련 - 출력에 매우 오래 걸림, PDF파일 버벅거림, PDF여는데 오래걸림 등등
  16. '잘못된 프린터 데이터를 수신하였습니다.' 문제
  17. MS서피스, 삼성 갤럭시북 등 ARM기반 랩탑, '잘못된 프린터 데이터를 수신하였습니다.' 문제

모두의프린터에서 더 알아보기

지금 구독하여 계속 읽고 전체 아카이브에 액세스하세요.

계속 읽기