[C++,QT/Qml]22.Qml프로그래밍 리스트 스크롤바 만들기1(qml scrollbar 사용하기)
안녕하세요 고급 개발자가 꿈인 코린이 입니다.
스크롤 바를 만드는 방법은 qml자체에서 제공하는 스크롤 바를 이용해서 만드는 방법이 있고 qml에서 제공하는
스크롤 바를 이용하지 않고 coustom화 해서 만드는 방법 이있습니다. 이 두가지의 방법에는 만드는 상황에따라
디자인을 적용하는지 안하는지에 따라서 선택해서 만들면 됩니다.
qml에서 제공하는 스크롤 바를 이용하면 웬만큼은 모두 구현이 가능하지만 한계가 있습니다.
그러니 만드시는 내용에 따라서 제공하는 것을 사용할지 아니면 따로 coustom화 하여 만들지를 선택해서
필자가 만든 스크롤 바를 잘따라서 만들어 보기시 바랍니다.
오늘은 qml자체에서 제공하는 Scrollbar를 사용해서 스크롤 바를 만들어보고 다음 포스팅에서는
custom으로 스크롤 바를 만들어서 리스트에 적용하는 식으로 하겠습니다.
리스트에 스크롤 바를 만들기 위해서는 listview에 스크롤 바를 추가해 줍니다.
아래 코드를 보겠습니다.
소스코드는 지난 포스팅에서 사용한 동적리스트 만드는 소스코드를 이용해서 만들어 보겠습니다.
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
|
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에 선언한 임의의 모델 안에 데이터를 넣어준다.
}
}
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
ScrollBar.vertical: ScrollBar{
width:20
policy:ScrollBar.AlwaysOn//스크롤바가 항상 출력되게함//ScrollBar.AlwaysOff:스크롤바가 항상 출력이 안되게 함
//ScrollBar.AsNeeded:스크롤바가 필요할때만 출력됨(리스트를 스크롤 하거나 마우스는 올려두면 스크롤바가 출력됨)
}
}
}
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
|
위의 소스코드를 보겠습니다.
리스트의 view에 scrollbar를 추가한것을 볼수 있습니다.
여기서 policy 설정은 스크롤 바를 항상 보여줄지 아예안보여줄지 필요할때만 보여줄지를 설정할수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
ListView {
id:listView
anchors.fill: parent
model: ListModel{}//임으로 만들 모델을 넣어준다.
delegate: contactDelegate//delegate란 리스트 한개의 틀(틀을 하나 만들어서 그것들을 여러개 붙여놓은것이 리스트 뷰이다.)
highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
focus: true
ScrollBar.vertical: ScrollBar{
width:20
policy:ScrollBar.AlwaysOn//스크롤바가 항상 출력되게함//ScrollBar.AlwaysOff:스크롤바가 항상 출력이 안되게 함
//ScrollBar.AsNeeded:스크롤바가 필요할때만 출력됨(리스트를 스크롤 하거나 마우스는 올려두면 스크롤바가 출력됨)
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
|
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs |
그렇다면 qml에서 제공하는 scrollbar를 이용해서 custom화는 어떻게 해야할까요??
이번 포스팅에서는 qml에서 제공하는 scrollbar를 이용해서 custom화 시키는 방법을 소개할 예정이고
다음 포스팅에서는 qml에서 제공하는 scrollbar를 이용하지 않고 custom화를 시킬 예정입니다.
qml에서 제공하는 scrollbar를 이용하면 스크롤 바를 구현하기 쉽게 되지만 구현상의 한계가 있습니다.
예를 들어 리스트가 많아지면 스크롤 바도 그만큼 작아지겠죠?? 그러다보니 어느정도 이상되면 스크롤바가
너무 작아져서 선이 되버리는 경우가 있습니다. 특정하게 작아졌을때 스크롤바의 높이를 유지해주기 위해서는
위의 qml에서 제공하는 스크롤 바를 사용해서 만들기에는 한계가 있습니다. qml제공하는 스크롤 바를 리스트의
크기에 따라 스크롤바의 크기를 일정한 비율로 지정하기 때문이죠 그리고 리스트의 전체 크기는 100이고
스크롤바는 리스트의 전체 크기에서 10퍼센트 지점에서 부터 시작되는 스크롤 바를 만들때도 한계가 있습니다.
스크롤 바의 위치를 지정할수는 있으나 y만큼 내려서 지정하면 맨 밑으로 내렸을때도 끝부분이 지정한 y만큼 넘어가기
때문입니다.
그렇기 때문에 필요한 경우에는 스크롤 바 자체를 custom화 해서 만들어주는 것이 필요합니다.
아래 코드를 보겠습니다.
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
|
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
ScrollBar.vertical: ScrollBar{
width:40
policy:ScrollBar.AlwaysOn//스크롤바가 항상 출력되게함//ScrollBar.AlwaysOff:스크롤바가 항상 출력이 안되게 함
//ScrollBar.AsNeeded:스크롤바가 필요할때만 출력됨(리스트를 스크롤 하거나 마우스는 올려두면 스크롤바가 출력됨)
contentItem: Rectangle{
color:"transparent"
Image
{
anchors.fill: parent
source:"./image/scrollbarimage.png"
}
}
}
}
}
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
|
qml에서 제공하는 스크롤바로 custom스크롤바를 만들기 위해서 위와같은 이미지를 추가하였습니다.
이미지 추가하는 내용은 이전에 포스팅한 내용을 보시면 됩니다.
https://youonlyliveonce1.tistory.com/9?category=712090
1
2
3
4
5
6
7
8
9
10
11
12
13
|
ScrollBar.vertical: ScrollBar{
width:40
policy:ScrollBar.AlwaysOn//스크롤바가 항상 출력되게함//ScrollBar.AlwaysOff:스크롤바가 항상 출력이 안되게 함
//ScrollBar.AsNeeded:스크롤바가 필요할때만 출력됨(리스트를 스크롤 하거나 마우스는 올려두면 스크롤바가 출력됨)
contentItem: Rectangle{
color:"transparent"
Image
{
anchors.fill: parent
source:"./image/scrollbarimage.png"
}
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
|
custom 스크롤 바를 만들기 위해서 rectangle을 추가하고 rectangle의 배경색을 투명으로 지정한 후
안사각형 안에 이미지를 추가하기위해서 이미지를 넣고 다른 사이트에서 무료료 다운 받은 이미지를 넣어줍니다.
이렇게 하면 custom 스크롤 바를 만들수 있습니다.
하지만 만약 이미지의 크기는 그대로 하고 스크롤은 되게끔 하려면 어떻게 해야할까요??
현재 위의 스크롤바는 이미지의 크기가 리스트의 개수만큼 일정한 비율로 늘어나거나 줄어들거나 하지만
스크롤바 자체를 custom으로 만들어주면 이미지크기를 고정으로 만들어 줄수 있습니다.
다음번 포스팅에는 custom으로 스크롤바를 만드는 방법에 대해서 포스팅 하겠습니다.
custom으로 만드는 만큼 내용이 어려운 부분이 많으니 잘 이해하고 따라와 주시면 이글을 읽으시는 분들의
실력은 엄청 늘 것입니다.
여기까지 읽어주셔서 감사합니다.!!
'QT and QML' 카테고리의 다른 글
[C++,QT/Qml]24.Qml프로그래밍 qml 에서 Enum값 사용하기 (0) | 2019.09.29 |
---|---|
[C++,QT/Qml]23.Qml프로그래밍 리스트 스크롤바 만들기2(custom scrollbar 만들기) (0) | 2019.09.22 |
[C++,QT/Qml]21.Qml프로그래밍 동적 리스트 만들기7(체크박스 리스트 삭제) (0) | 2019.09.08 |
[C++,QT/Qml]20.Qml프로그래밍 동적 리스트 만들기6(체크박스 리스트 삭제) (0) | 2019.09.01 |
[C++,QT/Qml]19.Qml프로그래밍 동적 리스트 만들기5(리스트 삭제기능,listview Delete) (2) | 2019.08.17 |