QMLプログラミングでFlickableを極める:flick()メソッドと応用
Flickable
は、タッチデバイスなどでコンテンツをドラッグしたりフリックしたりしてスクロールさせるためのQMLアイテムです。通常、ユーザーが指で画面を素早く払う(フリックする)と、その勢いに応じてコンテンツが滑らかにスクロールし、徐々に減速して停止します。
Flickable.flick(xVelocity, yVelocity)
メソッドは、このユーザーによるフリック操作をコードからシミュレートするものです。
flick(qreal xVelocity, qreal yVelocity)
:xVelocity
: 水平方向の初速度(ピクセル/秒)を指定します。正の値は右方向へのフリック、負の値は左方向へのフリックを表します。yVelocity
: 垂直方向の初速度(ピクセル/秒)を指定します。正の値は下方向へのフリック、負の値は上方向へのフリックを表します。
このメソッドを呼び出すと、指定された速度でFlickable
のコンテンツが動き出し、自然な減速アニメーションが適用されて停止します。
使用例
例えば、ボタンを押したときにFlickable
を特定の方向にフリックさせたい場合などに利用できます。
import QtQuick 2.0
import QtQuick.Controls 2.0
Rectangle {
width: 300
height: 200
color: "lightgray"
Flickable {
id: myFlickable
anchors.fill: parent
contentWidth: 600 // コンテンツの幅をFlickableの幅より大きくする
contentHeight: 400 // コンテンツの高さをFlickableの高さより大きくする
clip: true // はみ出たコンテンツをクリップする
Rectangle {
width: 500
height: 300
color: "lightblue"
Text {
anchors.centerIn: parent
text: "長いコンテンツ"
font.pointSize: 24
}
}
Button {
text: "右にフリック"
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
onClicked: {
myFlickable.flick(200, 0); // 水平方向に200ピクセル/秒でフリック
}
}
}
}
この例では、myFlickable
というFlickable
アイテムの中に大きなRectangle
があり、"右にフリック"
ボタンを押すと、myFlickable.flick(200, 0)
が呼び出され、コンテンツが右方向にフリックされます。
Flickable.flick()
メソッドは、以下のようなシナリオで役立ちます。
- デモンストレーション: アプリケーションのデモンストレーションやチュートリアルで、フリックの動作を視覚的に示したい場合。
- ナビゲーション: ユーザーの操作によらず、特定のセクションにフリックで移動させたい場合。
- 自動スクロール: 特定のイベント発生時にコンテンツを自動的にスクロールさせたい場合(例: 新しいアイテムが追加されたときに一番下までスクロールする)。
フリックしても何も起こらない、または動きが小さい
考えられる原因と解決策
-
flickableDirection の制限
flickableDirection
プロパティは、フリックが許可される方向を制限します。例えば、Flickable.HorizontalFlick
に設定されているのにyVelocity
に値を与えても垂直方向には動きません。 解決策: 意図するフリック方向がflickableDirection
で許可されているか確認してください。デフォルトはFlickable.AutoFlickDirection
で、コンテンツサイズに基づいて自動的に方向が決定されます。 -
interactive プロパティが false に設定されている
Flickable.interactive
がfalse
の場合、ユーザーインタラクションが無効になり、flick()
も機能しません。 解決策:Flickable.interactive: true
であることを確認してください。 -
flickDeceleration の影響
Flickable
にはflickDeceleration
というプロパティがあり、フリックの減速度合いを制御します。この値が大きいと、フリックが早く停止します。 解決策: 必要であれば、flickDeceleration
の値を小さくして、フリックがより長く続くように調整してみてください。一時的にflick()
を呼び出す前にflickDeceleration
を0に設定し、フリック後に元の値に戻すというアプローチもあります(ただし、ユーザーによるフリック操作に影響を与える可能性があるため注意が必要です)。 -
xVelocity / yVelocity の値が小さすぎる
flick()
メソッドに渡す速度は、ピクセル/秒単位です。非常に小さい値を指定すると、フリックがほとんど視認できないか、すぐに停止してしまいます。 解決策: 適切なフリック感を出すために、xVelocity
やyVelocity
には十分に大きな値(例: 200〜1000 ピクセル/秒など)を設定してみてください。 -
contentWidth / contentHeight の設定不足
Flickable
は、そのwidth
/height
に対してcontentWidth
/contentHeight
が大きい場合にのみスクロール可能です。flick()
を呼び出してもコンテンツが動かない場合、コンテンツのサイズがFlickable
の表示領域と同じか、それより小さい可能性があります。 解決策:Flickable
内のコンテンツがその表示領域よりも大きいことを確認し、contentWidth
とcontentHeight
を適切に設定してください。Flickable { width: 300 height: 200 contentWidth: 600 // Flickableの幅より大きくする contentHeight: 400 // Flickableの高さより大きくする // ... }
フリックが途中で止まる、またはバウンドする
考えられる原因と解決策
-
コンテンツのサイズ変更と contentWidth/contentHeight の更新不足
動的にコンテンツのサイズが変わる場合(例: 画像のロード後、テキスト量の変更など)、Flickable
のcontentWidth
やcontentHeight
が適切に更新されていないと、フリック可能な範囲が正しく認識されません。 解決策: コンテンツのサイズが変更されたときに、Flickable
のcontentWidth
およびcontentHeight
を更新するロジックを実装してください。特にImage
やText
など、ロードやレイアウトによってサイズが確定する要素の場合、onLoaded
やonContentWidthChanged
/onContentHeightChanged
などのシグナルを利用して更新すると良いでしょう。Image { id: myImage source: "largeImage.png" onStatusChanged: { if (status === Image.Ready) { myFlickable.contentWidth = myImage.width; myFlickable.contentHeight = myImage.height; } } }
-
boundsBehavior の設定
Flickable
のboundsBehavior
プロパティは、コンテンツが境界に到達したときの挙動を制御します。Flickable.StopAtBounds
(デフォルト): 境界でフリックが停止します。Flickable.DragOverBounds
: 境界を越えてドラッグできますが、フリックは境界で停止します。Flickable.DragAndOvershootBounds
: 境界を越えてドラッグでき、フリックも境界をオーバーシュート(飛び出し)します。 解決策: 想定する挙動に合わせてboundsBehavior
を調整してください。オーバーシュートさせたい場合はFlickable.DragAndOvershootBounds
を使用します。
flick() を呼び出しても見た目の変化がない
考えられる原因と解決策
-
他の要素が Flickable の上に重なっている
Flickable
の上に他のItem
やRectangle
などが重なっていて、それがフリック対象のコンテンツを覆い隠している可能性があります。 解決策: Zオーダー(z
プロパティ)を確認し、Flickable
が適切に表示されるように調整してください。 -
clip プロパティが false
Flickable
はデフォルトではコンテンツをクリップしません。つまり、Flickable
の表示領域からはみ出したコンテンツも表示され続けます。この場合、フリックしても見た目に変化がないように見えることがあります。 解決策:Flickable
のclip
プロパティをtrue
に設定して、表示領域外のコンテンツを非表示にしてください。Flickable { clip: true // これを設定しないと、コンテンツがFlickableの枠外にはみ出して表示される // ... }
flick() とユーザー操作の競合
考えられる原因と解決策
- flick() の呼び出しタイミング
ユーザーがコンテンツをドラッグしている最中や、別のフリックアニメーションが実行されている最中にflick()
を呼び出すと、予期せぬ挙動になることがあります。 解決策:flick()
を呼び出す前に、flicking
やdragging
プロパティを確認し、Flickable
がアイドル状態であることを確認すると良いでしょう。flickEnded
シグナルを利用して、前回のフリックが終了したことを検知してから次のflick()
を呼び出すようにすることもできます。
Flickable の子要素に関する問題
考えられる原因と解決策
-
MouseArea との競合
Flickable
内にMouseArea
がある場合、MouseArea
がマウスイベントを消費してしまい、Flickable
のフリック動作が阻害されることがあります。 解決策:MouseArea
のpropagateComposedEvents
プロパティをtrue
に設定することで、イベントを親要素に伝播させることができます。または、MouseArea
のhoverEnabled
やacceptedButtons
を適切に設定して、必要なイベントのみを処理するように制限します。 -
Flickable の子要素は contentItem の子になる
QMLのFlickable
に直接配置された子要素は、実際にはFlickable
のcontentItem
の子として追加されます。このため、子要素のプロパティ(x
,y
など)を直接操作しても、フリックによるスクロール量には影響されない場合があります。 解決策:flick()
はFlickable
自体のcontentX
,contentY
プロパティを操作することでスクロールを実現します。子要素を相対的に移動させたい場合は、contentX
,contentY
の値に基づいて子要素の位置を調整するか、Flickable
の外部からflick()
を呼び出すことで全体をスクロールさせます。
-
最小限の再現コードを作成する
複雑なアプリケーションで問題が発生した場合、Flickable.flick()
のみに焦点を当てた最小限のQMLファイルを作成し、そこで問題が再現するかどうかを確認します。これにより、問題の原因がFlickable
自体にあるのか、それともアプリケーションの他の部分との相互作用にあるのかを切り分けやすくなります。 -
Qt Creator の QML Debugger を使用する
Qt Creator には強力な QML Debugger が搭載されており、QMLツリーの要素のプロパティ値をリアルタイムで確認したり、デバッグメッセージをチェックしたりできます。これは問題の特定に非常に役立ちます。 -
console.log() を活用する
Flickable
のcontentX
,contentY
,contentWidth
,contentHeight
,width
,height
,flicking
,dragging
などのプロパティをconsole.log()
で出力し、期待通りの値になっているか確認してください。 特にonFlickStarted
やonFlickEnded
シグナル内でログを出力すると、フリックのライフサイクルを追跡できます。
基本的なフリック操作
最も基本的な例として、ボタンをクリックしたときにFlickable
を特定の方向にフリックさせるコードです。
// main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
visible: true
width: 400
height: 300
title: "Flickable.flick() の基本"
Flickable {
id: myFlickable
anchors.fill: parent
clip: true // コンテンツをFlickableの境界内でクリップする
// Flickable のコンテンツは、そのcontentWidth/contentHeightがFlickable自身のwidth/heightより大きい場合にのみスクロール可能
contentWidth: myContent.width
contentHeight: myContent.height
Rectangle {
id: myContent
width: 800 // Flickableの幅より広いコンテンツ
height: 600 // Flickableの高さより高いコンテンツ
color: "lightblue"
Text {
anchors.centerIn: parent
text: "このコンテンツをフリックします"
font.pointSize: 20
}
}
// コントロール
Column {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: 10
width: 100 // ボタンの幅
Button {
text: "右へフリック"
width: parent.width
onClicked: {
// 水平方向に2000ピクセル/秒でフリック (右方向)
myFlickable.flick(2000, 0);
}
}
Button {
text: "左へフリック"
width: parent.width
onClicked: {
// 水平方向に-2000ピクセル/秒でフリック (左方向)
myFlickable.flick(-2000, 0);
}
}
Button {
text: "下へフリック"
width: parent.width
onClicked: {
// 垂直方向に2000ピクセル/秒でフリック (下方向)
myFlickable.flick(0, 2000);
}
}
Button {
text: "上へフリック"
width: parent.width
onClicked: {
// 垂直方向に-2000ピクセル/秒でフリック (上方向)
myFlickable.flick(0, -2000);
}
}
}
}
}
この例では、Flickable
内に大きなRectangle
(コンテンツ)を配置し、Button
をクリックすると、それぞれの方向へ flick()
メソッドが呼び出されてスクロールします。速度の値は、フリックの勢いを表します。
コンテンツの端まで自動スクロール
チャットアプリケーションなどで、新しいメッセージが追加されたときに自動的に一番下までスクロールさせたい場合などに役立ちます。
// main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
ApplicationWindow {
visible: true
width: 400
height: 500
title: "チャット風自動スクロール"
Flickable {
id: chatFlickable
anchors.fill: parent
clip: true
contentWidth: chatColumn.width
contentHeight: chatColumn.height
ColumnLayout {
id: chatColumn
width: chatFlickable.width - 20 // 左右に余白
spacing: 5
leftPadding: 10
rightPadding: 10
topPadding: 10
bottomPadding: 10
// チャットメッセージをここに追加
}
// 新しいメッセージ追加ボタン
Button {
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
text: "メッセージを追加"
onClicked: {
var newRect = Qt.createQmlObject(`
import QtQuick 2.15
Rectangle {
width: parent.width
height: 40
color: Qt.random() > 0.5 ? "lightgreen" : "lightblue"
radius: 5
Text {
anchors.centerIn: parent
text: "メッセージ " + chatFlickable.contentItem.children.length
font.pointSize: 14
}
}`, chatColumn);
newRect.parent = chatColumn;
// 新しいメッセージが追加されたら、一番下までフリック
// contentYが最大値になるようにフリック速度を調整
// -chatFlickable.contentHeight を使うことで、コンテンツの高さに基づいて計算
// (contentHeight - height) がスクロール可能な最大値
// 例えば、contentHeight = 600, height = 300 なら 300 が最大
var targetY = chatFlickable.contentHeight - chatFlickable.height;
if (targetY < 0) targetY = 0; // コンテンツがFlickableより小さい場合は0
// 現在のcontentYから目標contentYまでの距離に比例した速度を与える
// 例えば、目標まで100pxあるなら、それに応じた速度を計算
// この例では、単純に負の大きな速度を与えて下方向にフリック
chatFlickable.flick(0, 5000); // 下方向へ勢いよくフリック
}
}
// contentHeightが変更されたときに自動スクロール
// ユーザーが手動でスクロールしている場合は邪魔しないようにする
onContentHeightChanged: {
// flicking, dragging, moving は、Flickableが現在アニメーション中か、
// ユーザーが操作中かを示すプロパティ
if (!chatFlickable.flicking && !chatFlickable.dragging && !chatFlickable.moving) {
// コンテンツの一番下が見える位置までフリック
var targetY = chatFlickable.contentHeight - chatFlickable.height;
if (targetY < 0) targetY = 0;
chatFlickable.flick(0, targetY - chatFlickable.contentY > 0 ? 5000 : 0); // 下方向へ
}
}
}
}
この例では、"メッセージを追加"
ボタンを押すたびに新しいRectangle
(メッセージ)が追加され、chatFlickable.flick(0, 5000)
を呼び出すことで自動的に一番下までスクロールします。onContentHeightChanged
ハンドラは、コンテンツの高さが変わる(新しいメッセージが追加される)たびに、Flickable
がユーザーによって操作されていない場合に限り、自動スクロールを実行します。
特定の要素までフリックしてスクロール位置を調整
多数のアイテムがあるFlickable
内で、特定のアイテムが見える位置までスクロールさせたい場合に便利です。
// main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
ApplicationWindow {
visible: true
width: 400
height: 500
title: "特定のアイテムへフリック"
Flickable {
id: itemFlickable
anchors.fill: parent
clip: true
contentWidth: contentColumn.width
contentHeight: contentColumn.height
ColumnLayout {
id: contentColumn
width: itemFlickable.width
spacing: 5
Repeater {
model: 20 // 20個のアイテム
delegate: Rectangle {
id: itemRect
width: parent.width
height: 50
color: index % 2 === 0 ? "#E0E0E0" : "#F0F0F0"
border.color: "gray"
border.width: 1
Text {
anchors.centerIn: parent
text: "アイテム " + (index + 1)
font.pointSize: 16
}
// このアイテムをクリックすると、そのアイテムまでフリック
MouseArea {
anchors.fill: parent
onClicked: {
// クリックされたアイテムのグローバル座標を取得
var itemGlobalPos = itemRect.mapToItem(itemFlickable.contentItem, 0, 0);
// 目標のcontentXとcontentYを計算
// ここでは、アイテムの先頭がFlickableの先頭に来るように調整
var targetX = itemGlobalPos.x;
var targetY = itemGlobalPos.y;
// flick() は相対的な速度なので、ターゲットまでの距離を速度に変換する
// 単純に一定の速度でフリックさせる例
// 速度の方向と大きさは、現在の位置と目標位置の差から計算
var deltaX = targetX - itemFlickable.contentX;
var deltaY = targetY - itemFlickable.contentY;
var velocityMagnitude = 2000; // 速度の大きさ
var angle = Math.atan2(deltaY, deltaX);
var xVel = velocityMagnitude * Math.cos(angle);
var yVel = velocityMagnitude * Math.sin(angle);
itemFlickable.flick(xVel, yVel);
console.log("アイテム " + (index + 1) + " にフリック中...");
}
}
}
}
}
}
// 特定のアイテムにジャンプするための入力
Row {
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
spacing: 10
z: 100 // Flickableの上に表示されるようにする
TextField {
id: itemIndexInput
placeholderText: "アイテム番号を入力"
width: 150
validator: IntValidator { bottom: 1; top: 20 }
}
Button {
text: "ジャンプ"
onClicked: {
var indexToJump = parseInt(itemIndexInput.text) - 1; // 0ベースインデックスに変換
if (indexToJump >= 0 && indexToJump < itemFlickable.contentItem.children.length) {
var targetItem = itemFlickable.contentItem.children[indexToJump];
var targetY = targetItem.y;
// 現在のcontentYから目標contentYまでの距離に応じてフリック速度を調整
var deltaY = targetY - itemFlickable.contentY;
var velocity = deltaY * 5; // 距離に応じて速度を調整(適当な係数)
itemFlickable.flick(0, velocity);
console.log("アイテム " + (indexToJump + 1) + " へジャンプ中...");
}
}
}
}
}
この例では、Repeater
で20個のRectangle
(アイテム)を作成しています。各アイテムをクリックすると、そのアイテムがFlickable
の表示領域の先頭に来るように自動的にフリックします。また、上部にテキストフィールドとボタンを設け、番号を入力してジャンプすることもできます。
- ユーザー操作との競合
flick()
を呼び出すタイミングには注意が必要です。ユーザーがドラッグ操作をしている最中や、他のフリックアニメーションが実行されている最中にflick()
を呼び出すと、意図しない挙動になることがあります。flicking
,dragging
,moving
といったプロパティや、flickStarted
,flickEnded
などのシグナルを利用して、安全なタイミングで呼び出すように制御すると良いでしょう。 - 速度の調整
xVelocity
とyVelocity
の値は、フリックの勢いを決定します。小さい値だとすぐに止まり、大きすぎると画面外に飛び出しすぎてしまう可能性があります。アプリケーションの要件に応じて適切な値を試行錯誤して見つける必要があります。 - clip: true
Flickable
のclip
プロパティをtrue
に設定すると、Flickable
の境界からはみ出たコンテンツがクリップされ、スクロールしていることが視覚的に分かりやすくなります。 - contentWidth/contentHeight の設定
Flickable
のwidth
/height
よりコンテンツのサイズ (contentWidth
/contentHeight
) が大きい場合にのみフリックが可能です。これらを適切に設定しないと、flick()
を呼び出しても何も起こりません。
contentX / contentY プロパティの直接操作
Flickable
の contentX
および contentY
プロパティは、Flickable 内のコンテンツの現在のオフセットを表します。これらの値を直接設定することで、コンテンツを特定の位置に即座に移動させることができます。
特徴
- アニメーションなし
滑らかな移動が必要な場合は、別途アニメーションを追加する必要があります。 - 直接的
スクロール位置をピクセル単位で正確に制御できます。 - 即時性
値を設定すると、アニメーションなしでコンテンツがすぐに指定された位置にジャンプします。
使用例
特定のアイテムの先頭にスクロールしたい場合など、瞬間的な移動が必要な場合に利用できます。
// main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
visible: true
width: 400
height: 300
title: "contentX / contentY の直接操作"
Flickable {
id: myFlickable
anchors.fill: parent
clip: true
contentWidth: contentRect.width
contentHeight: contentRect.height
Rectangle {
id: contentRect
width: 800
height: 600
color: "lightblue"
Text { anchors.centerIn: parent; text: "広いコンテンツ"; font.pointSize: 24 }
}
Row {
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
spacing: 10
Button {
text: "左上へリセット"
onClicked: {
myFlickable.contentX = 0;
myFlickable.contentY = 0;
}
}
Button {
text: "中央へ移動"
onClicked: {
// コンテンツの中央をFlickableの中心に合わせる
myFlickable.contentX = (myFlickable.contentWidth - myFlickable.width) / 2;
myFlickable.contentY = (myFlickable.contentHeight - myFlickable.height) / 2;
}
}
}
}
}
PropertyAnimation を使った contentX / contentY のアニメーション
contentX
や contentY
を直接設定すると瞬間的な移動になりますが、PropertyAnimation
を使うことで、これらのプロパティの変化を滑らかにアニメーションさせることができます。これにより、flick()
と同様に視覚的に心地よいスクロールを実現できます。
特徴
- 停止・一時停止・再開
アニメーションをプログラム的に制御できます。 - 柔軟性
速度、継続時間、イージング(動きの加速/減速パターン)を細かく制御できます。 - 滑らかな移動
指定した時間とイージングカーブでスクロールをアニメーションできます。
使用例
「一番下までゆっくりスクロールする」や「特定のセクションまで滑らかに移動する」といった場合に適しています。
// main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
visible: true
width: 400
height: 500
title: "PropertyAnimation によるスクロール"
Flickable {
id: myFlickable
anchors.fill: parent
clip: true
contentWidth: contentColumn.width
contentHeight: contentColumn.height
Column {
id: contentColumn
width: myFlickable.width
spacing: 5
Repeater {
model: 30
delegate: Rectangle {
width: parent.width
height: 50
color: index % 2 === 0 ? "#E0E0E0" : "#F0F0F0"
Text { anchors.centerIn: parent; text: "アイテム " + (index + 1); font.pointSize: 16 }
}
}
}
Button {
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
text: "一番下までスクロール (アニメーション)"
onClicked: {
// PropertyAnimation を使って contentY をアニメーションさせる
scrollAnimation.to = myFlickable.contentHeight - myFlickable.height;
if (scrollAnimation.to < 0) scrollAnimation.to = 0; // コンテンツがFlickableより小さい場合は0
scrollAnimation.start();
}
}
PropertyAnimation {
id: scrollAnimation
target: myFlickable
property: "contentY"
duration: 1000 // 1秒かけてスクロール
easing.type: Easing.OutCubic // 滑らかな減速アニメーション
}
}
}
この例では、ボタンをクリックすると scrollAnimation
が開始され、Flickable
が滑らかに一番下までスクロールします。easing.type
を変更することで、動きの挙動を調整できます。
ListView / GridView の positionViewAtBeginning() / positionViewAtEnd()
ListView
や GridView
は Flickable
をベースにしていますが、リストやグリッドに特化した便利なスクロールメソッドを提供しています。
特徴
- アニメーション制御
通常、内部的にアニメーションを伴います。 - シンプル
positionViewAtBeginning()
やpositionViewAtEnd()
のように、目的が明確なメソッド。 - コンテキスト依存
リストやグリッドの構造に最適化されたスクロール。
使用例
チャットリストやフィードのように、コンテンツの先頭や末尾に移動したい場合に非常に便利です。
// main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15
ApplicationWindow {
visible: true
width: 400
height: 500
title: "ListViewによるスクロール制御"
ListView {
id: myListView
anchors.fill: parent
clip: true
spacing: 5
model: 30 // 30個のアイテム
delegate: Rectangle {
width: parent.width
height: 50
color: index % 2 === 0 ? "#E0E0E0" : "#F0F0F0"
Text { anchors.centerIn: parent; text: "リストアイテム " + (index + 1); font.pointSize: 16 }
}
}
Column {
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
spacing: 10
Button {
text: "先頭へスクロール"
onClicked: {
myListView.positionViewAtBeginning();
}
}
Button {
text: "末尾へスクロール"
onClicked: {
myListView.positionViewAtEnd();
}
}
Button {
text: "10番目のアイテムへ"
onClicked: {
// positionViewAtIndex(index, mode)
// ListView.Beginning: アイテムをビューの先頭に
// ListView.Center: アイテムをビューの中央に
// ListView.End: アイテムをビューの末尾に
// ListView.Visible: アイテムが見える範囲に移動(最低限のスクロール)
myListView.positionViewAtIndex(9, ListView.Center); // 0-based indexなので9は10番目
}
}
}
}
ScrollView
は、Flickable
の上にスクロールバーなどのUI要素を自動的に追加してくれる高レベルなコントロールです。内部的には Flickable
を使用していますが、ユーザーインターフェースとしての完全なスクロールビューを提供します。スクロールバーの表示/非表示や、ユーザー操作への応答などを自動的に処理してくれます。
特徴
- 内部はFlickable
内部的にはFlickable
の機能を利用しているため、ScrollView.flickable.flick()
のようにアクセスすることも可能です。 - 簡潔な記述
多くのケースでFlickable
を直接使うよりもコード量が減ります。 - 高レベルの抽象化
スクロールバーの表示など、複雑なUIを自動的に処理。
使用例
通常のドキュメントビューアや設定画面など、標準的なスクロール動作とスクロールバーが必要な場合に最適です。
// main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
visible: true
width: 400
height: 300
title: "ScrollViewの使用"
ScrollView {
id: myScrollView
anchors.fill: parent
// ScrollView のコンテンツは、子要素として直接配置
Rectangle {
width: 800 // ScrollViewの幅より広いコンテンツ
height: 600 // ScrollViewの高さより高いコンテンツ
color: "lightcoral"
Text { anchors.centerIn: parent; text: "ScrollView のコンテンツ"; font.pointSize: 24 }
}
// ScrollView内部のFlickableにアクセスしてflick()を呼び出す
Button {
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
text: "ScrollViewをフリック"
onClicked: {
myScrollView.flickable.flick(2000, 0); // ScrollViewの内部のFlickableをフリック
}
}
}
}
ScrollView
: スクロールバー付きの標準的なスクロールビューを簡単に実現したい場合に利用します。内部のflickable
プロパティを通じてflick()
などにアクセスすることも可能です。ListView
/GridView
のメソッド: リストやグリッドの特定のアイテムにスクロールしたい場合に最も適した高レベルなメソッドです。PropertyAnimation
+contentX
/contentY
:flick()
よりもきめ細かくスクロールアニメーションを制御したい場合(時間、イージング、停止/再開など)に強力です。contentX
/contentY
直接操作: 即座にスクロール位置を移動させたい場合に便利です。アニメーションは提供されません。Flickable.flick()
: ユーザーのフリック操作をプログラム的にシミュレートしたい場合に最適です。減速アニメーションが組み込まれています。