[C++,QT/Qml]23.Qml프로그래밍 리스트 스크롤바 만들기2(qml scrollbar 사용하기)
main.qml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
import QtQuick 2.9
import QtQuick.Controls 2.0
import QtQuick.Window 2.2
import ConnectEvent 1.0//등록한 클래스 타입을 import해준다.
import "."
Window {
id:mainWindow
property bool mbImageClicked : true
property int mCount : 0
property int mListClickIndex : 0//클릭한 리스트의 index를 담는 전역 변수
signal qmlSignalListUpdate();//리스트가 업데이트되었다는 것을 알려주기 위한 시그널 등록
visible: true
width: 800
height: 600
title: qsTr("Hello World")
ConnectEvent//클래스를 qml 타입으로 지정
{
id:connectEvent
}
Component.onCompleted://view가 처음 실행될때 제일 처음으로 불려지는곳
{
//조금 예쁘게 보이기 위해서 리스트를 많이 추가함 리스트가 너무 적을시 이미지 해상도가 작아서 이미지가 바둑판식으로 나옴
for(var i = 0; i < connectEvent.getListSize(); i++){//리스트의 개수만큼 for문을 돌린다.
listView.model.append({"list_text": connectEvent.getListTitle(i),//모델에 리스트의 데이터값을 넣어준다.
"list_button_text": connectEvent.getListButtonText(i)})//listview에 선언한 임의의 모델 안에 데이터를 넣어준다.
}
for(var i = 0; i < connectEvent.getListSize(); i++){//리스트의 개수만큼 for문을 돌린다.
listView.model.append({"list_text": connectEvent.getListTitle(i),//모델에 리스트의 데이터값을 넣어준다.
"list_button_text": connectEvent.getListButtonText(i)})//listview에 선언한 임의의 모델 안에 데이터를 넣어준다.
}
for(var i = 0; i < connectEvent.getListSize(); i++){//리스트의 개수만큼 for문을 돌린다.
listView.model.append({"list_text": connectEvent.getListTitle(i),//모델에 리스트의 데이터값을 넣어준다.
"list_button_text": connectEvent.getListButtonText(i)})//listview에 선언한 임의의 모델 안에 데이터를 넣어준다.
}
for(var i = 0; i < connectEvent.getListSize(); i++){//리스트의 개수만큼 for문을 돌린다.
listView.model.append({"list_text": connectEvent.getListTitle(i),//모델에 리스트의 데이터값을 넣어준다.
"list_button_text": connectEvent.getListButtonText(i)})//listview에 선언한 임의의 모델 안에 데이터를 넣어준다.
}
for(var i = 0; i < connectEvent.getListSize(); i++){//리스트의 개수만큼 for문을 돌린다.
listView.model.append({"list_text": connectEvent.getListTitle(i),//모델에 리스트의 데이터값을 넣어준다.
"list_button_text": connectEvent.getListButtonText(i)})//listview에 선언한 임의의 모델 안에 데이터를 넣어준다.
}
for(var i = 0; i < connectEvent.getListSize(); i++){//리스트의 개수만큼 for문을 돌린다.
listView.model.append({"list_text": connectEvent.getListTitle(i),//모델에 리스트의 데이터값을 넣어준다.
"list_button_text": connectEvent.getListButtonText(i)})//listview에 선언한 임의의 모델 안에 데이터를 넣어준다.
}
for(var i = 0; i < connectEvent.getListSize(); i++){//리스트의 개수만큼 for문을 돌린다.
listView.model.append({"list_text": connectEvent.getListTitle(i),//모델에 리스트의 데이터값을 넣어준다.
"list_button_text": connectEvent.getListButtonText(i)})//listview에 선언한 임의의 모델 안에 데이터를 넣어준다.
}
for(var i = 0; i < connectEvent.getListSize(); i++){//리스트의 개수만큼 for문을 돌린다.
listView.model.append({"list_text": connectEvent.getListTitle(i),//모델에 리스트의 데이터값을 넣어준다.
"list_button_text": connectEvent.getListButtonText(i)})//listview에 선언한 임의의 모델 안에 데이터를 넣어준다.
}
}
onQmlSignalListUpdate:{//시그널이 호출되면 실행하는 함수
console.log("onQmlSignalListUpdate called")
listView.model.clear();//리스트 초기화
for(var i = 0; i < connectEvent.getListSize(); i++){//리스트 초기화 후 다시 넣어줌
listView.model.append({"list_text": connectEvent.getListTitle(i),
"list_button_text": connectEvent.getListButtonText(i)})
}
}
Component {//리스트 뷰의 틀을 만든다.
id: contactDelegate
Item {
width: 800
height: 100
Text//리스트에 텍스트를 넣어주기 위해 텍스트 객체를 만들어준다.
{
id:listView_Text
anchors.left: parent.left
anchors.leftMargin: 50
anchors.verticalCenter: parent.verticalCenter
text:list_text//모델에 매칭이될 변수 listview에 원하는 값을 넣기위해서 설정하는 값
}
Rectangle//리스트의 구분선
{
id:line
width:parent.width
anchors.bottom:parent.bottom//현재 객체의 아래 기준점을 부모객체의 아래로 잡아주어서 위치가 아래로가게 설정
height:1
color:"black"
}
MouseArea
{
id:listMouseArea
anchors.fill: parent
onClicked:
{
mListClickIndex = index;//여기에서 사용하는 index는 클릭했을때의 index를 리턴해준다
//그래서 현재 선택한 리스트를 전역변수에 담고 다음 화면에서 그에 해당하는 정보를 보여준다.
stackView.push(Qt.resolvedUrl("qrc:/deleteList.qml"))
}
}
//버튼 객체를 mouseArea아래로 옮겼다 이유는 mouseArea가 부모의 영역을 포함하고 있는데
//버튼 영역도 부모의 영역 안에 있기 때문에 버튼클릭시 버튼클릭이 아닌 리스트의 클릭이 되어 버린다.
Button//리스트에 버튼을 넣어주기 위해 버튼 객체를 만들어준다.
{
id:listView_Button
width:120
height:40
anchors.rightMargin: 30
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
text: list_button_text//모델에 매칭이될 변수 listview에 원하는 값을 넣기위해서 설정하는 값
onClicked:
{
connectEvent.deleteListItem(index);//c++ 리스트의 데이터를 삭제
listView.model.remove(index);//리스트의 모델에 삭제하는 함수(실시간 삭제)
}
}
}
}
StackView{
id:stackView
anchors.fill: parent
initialItem: Item //제일 첫화면을 설정하는 것으로 설정을 안하면 되돌아오기가 안된다.
{
ListView {
id:listView
anchors.fill: parent
model: ListModel{}//임으로 만들 모델을 넣어준다.
delegate: contactDelegate//delegate란 리스트 한개의 틀(틀을 하나 만들어서 그것들을 여러개 붙여놓은것이 리스트 뷰이다.)
highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
focus: true
}
Flickable
{
id:flickable
x : 760
y: 0
width : 40
height : 600
Image
{
id: scrollBarImage
y: listView.visibleArea.yPosition * flickable.height //Flickable 의 전체 높이에서 yposition만큼의 비율을 곱해준다.(이미지의 y좌표는 스크롤이 높이만큼만 스크롤이 가능하기 때문에 Flickable 의 높이만큼)
width : 40
height:flickable.height - (flickable.height * (1 - listView.visibleArea.heightRatio))//스크롤바의 최대 높이는 flickable의 높이 입니다. 그렇기 때문에 flickable의 높이에서 높이 비율만큼 빼줍니다.
source:"./image/scrollbarimage.png"
onYChanged: {
console.log("listView.visibleArea.yPosition:" + listView.visibleArea.yPosition)
console.log("listView.visibleArea.heightRatio:" + listView.visibleArea.heightRatio)
}
}
}
}
}
}
|
|
|
|
위의 소스코드를 보시면 생소한 listView.visibleArea.yPosition 등과 같은 생소한 property들이
많이 있는 것을 확인할수 있습니다. 같이 하나하나 살펴보도록 하겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
|
Image
{
id: scrollBarImage
y: listView.visibleArea.yPosition * flickable.height //Flickable 의 전체 높이에서 yposition만큼의 비율을 곱해준다.(이미지의 y좌표는 스크롤이 높이만큼만 스크롤이 가능하기 때문에 Flickable 의 높이만큼)
width : 40
height:flickable.height - (flickable.height * (1 - listView.visibleArea.heightRatio))//스크롤바의 최대 높이는 flickable의 높이 입니다. 그렇기 때문에 flickable의 높이에서 높이 비율만큼 빼줍니다.
source:"./image/scrollbarimage.png"
onYChanged: {
console.log("listView.visibleArea.yPosition:" + listView.visibleArea.yPosition)
console.log("listView.visibleArea.heightRatio:" + listView.visibleArea.heightRatio)
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
|
첫번째로 listView.visibleArea.yPosition는 리스트의 visibleArea즉 리스트가 실제 보여지는 영역의 yposition의 비율입니다.
스크롤바는 리스트뷰를 스크롤했을때 그만큼 스크롤바의 위치도 움직여야 하기때문에 위와같이 구현 했는뎅
visibleArea.yPosition이란 즉 현재 리스트 뷰가 높이가 600인데 리스트가 위처럼 많기 때문에 실제 리스트 뷰의 높이는
동적으로 추가된 리스트의 개수 곱하기 리스트 하나의 개수 즉 100 이 됩니다.
즉 동적으로 추가된 리스트 * 100이 되는 거지요 그래서 이 실제 리스트 뷰의 높이에 설정된 리스트 뷰의 높이(600) 으로
비율이 맞춰지는 것입니다. 그래서 그 비율만큼으로 따졌을때의 yposition이 되는 것입니다.
그리고 visibleArea 의 heightRatio는 말그대로 높이 비율인데 이것도 리스트의 전체 높이 에서 리스트 뷰의 높이 600 의 비율을
나타낸 것으로 리스트가 많으면 많을수로 이값은 작아지고 비율은 고정이 됩니다.
yposition과 다른점은 heightRatio는 고정값이고 yposition은 리스트를 스크롤 하면 변경 됩니다.
그렇기 때문에 y좌표는 flickable 의 높이 만큼만 변하기 때문에 flickable높이의listview의visibleArea의yposition의
비율값을 곱하면 스크롤 바의 y좌가 되는 것이고
높이는 최대값이 flickable의 높이이고 여기서 1에서 listview의visibleArea의heightRatio만큼 뺀값에서
flickable의 높이 만큼 곱해서 빼주면 높이가 만들어 집니다. 그이유는 리스트의 개수가 많아지면 스크롤바의 높이는
작아져야하는데 리스트의 개수가 많아지면 listview의visibleArea의heightRatio만 가 작아지기 때문에 전체 비율 즉 1에서
빼주면 큰값이 되고 여기서 flickable의 높이만큼 곱해주면 flickable의 높이의listview의높이만큼의
비율만큼이기때문에 여기서 최대값에서 이값을 빼주면 리스트가 길어진만큼 스크롤바의 높이가 되게 됩니다.
여기까지 글로 설명드렸는데 글로 설명드리기 정말 어려운 부분이 많은것같네요
막상 설명 드리는데도 제가 무슨말을 하는지도 잘모르겠고 좀 많이 어려운 부분이었던것 같습니다.
이 내용을 조금더 이해하고 싶다면 여러번 구현 해보고 로그로 찍어보면서 어떤때에 어떠한 값이 변하고
어떠한 값은 고정인지 알아서 여려번 해보시는것이 도움이 많이 됩니다.
저도 처음 scrollbar를 구현할때 qt사이트의 문서를 많이 참고했습니다.
저의 블로그도 보면서 아래의 사이트 즉 qt에서 제공하는 문서도 많이 참고하면 구현하실때 도움도 많이되고 추후에는
쉽게 구현이 가능하실것 입니다.
https://doc.qt.io/qt-5/qml-qtquick-flickable.html
여기까지 고급개발자가 꿈인 코린이었구요
추후에 마우스로 스크롤까지 되는 scrollbar도 구현해서 포스팅하고 설명도 많이 준비해서 올리도록하겠습니다.
감사합니다!!
'QT and QML' 카테고리의 다른 글
[C++,QT/Qml]25.Qml프로그래밍 cpp qml 연동4(C++ 에서 qml 함수 호출하기 두번째 방법) (0) | 2019.10.13 |
---|---|
[C++,QT/Qml]24.Qml프로그래밍 qml 에서 Enum값 사용하기 (0) | 2019.09.29 |
[C++,QT/Qml]22.Qml프로그래밍 리스트 스크롤바 만들기1(qml scrollbar 사용하기) (0) | 2019.09.08 |
[C++,QT/Qml]21.Qml프로그래밍 동적 리스트 만들기7(체크박스 리스트 삭제) (0) | 2019.09.08 |
[C++,QT/Qml]20.Qml프로그래밍 동적 리스트 만들기6(체크박스 리스트 삭제) (0) | 2019.09.01 |