Qt Quick Image Viewer/bg

From Qt Wiki
Jump to navigation Jump to search
This article may require cleanup to meet the Qt Wiki's quality standards. Reason: Auto-imported from ExpressionEngine.
Please improve this article if you can. Remove the {{cleanup}} tag and add this page to Updated pages list after it's clean.

[toc align_right="yes" depth="3"]

Български English

Плавно приплъзване на изображенията в Qt Quick

[YouTubeID:zg6GxFpQeWU]

Въведение

Тази къса статия показва как да създадете програма за разглеждане на картинки с плавен и приятен интерфейс, като използвате Qt Quick. Ще използваме ListView и FolderListModel за да създадем програма за разглеждане на картинки на 25 реда код. Въпреки, че може да изглежда като доста лесен проблем, трябва да знаете няколко концепции. Стъпка по стъпка, ще покажем, че ListView може да служи като такава програма.

За да следвате тези напътствия, вие се нуждаете от инструмента qmlviewer и допълнителният qtquick компонент folderlistmodel. Ако използвате някоя от последните версии на Убунту Линукс, просто инсталирайте пакетите qt4-qmlviewer, libqt4-declarative-folderlistmodel и libqt4-dev packages. Също така всички файлове в този урок могат да бъдат свалени от gitorious.

Минималните изисквания за Qt Quick са версия 1.0, която идва с Qt от версия 4.7.1.

Създаване на приложението

Създайте една папка, сложете в нея някакви картинки и нека да започнем със следният код:

import QtQuick 1.0
import Qt.labs.folderlistmodel 1.0

ListView {
 id: view
 width: 640
 height: 360
 model: FolderListModel {
 nameFilters: [ "'''.JPG", "'''.jpg" ]
 folder: "images"
 sortField: FolderListModel.Name
 }
 delegate: Image {
 source: filePath
 width: view.width
 height: view.height
 smooth: true
 }
 orientation: ListView.Horizontal
 snapMode: ListView.SnapToItem
}

Запазете кода в същата директория като картинките с име FlickScroller.qml. Нашият подход е тривиален: Създаване на хоризонтално ListView, използване на FolderListModel, за да получим имената на картинките и използване на Image компонента, за да покажем картинките. Докато това изглежда като очевидният начин за справяне с проблема, ще забележете, че има няколко проблема. Пуснете кода в qmlviewer, за да видите какво не е наред. Първо картинките са деформирани. Второ, производителността е ужасна, или поне далече от плавното предвижване, въпреки че ListView го поддържа много добре. Та, какво става тук? В общи линии ListView-to създава своите Image делегати, когато те трябва да е покажат, т.е когато картинката влезе във видимата част на ListView-то. Което е добре, защото не зареждаме цялата папка със снимки предварително, туй като може да имаме стотици картинки. Можем да подобрим скоростта на зареждането като използваме атрибута Image.sourceSize. Вътрешно той ще използва QImageReader и ще зареди картинката с необходимите размери, което ще намали използването на паметта и времето за зареждане. Добавете следният ред към атрибутите на Image и опитайте пак:

sourceSize.width: width

Друго нещо, което трябва да знаете тук е, че ако зададете само единият размер на картинката, за другият ще бъде използван реалният размер. Ако зададете и двата размера, това неминуемо ще наруши съотношенето височина/ширина. Което ни води до следващият проблем - развалено съотношение височина/ширина. Имате два избора за да оправите това:

fillMode: Image.PreserveAspectCrop // или: Image.PreserveAspectFit

Добавете този параметър към Image делегата и вижте какво се случва. Image.PreserveAspectCrop прави картинката с размери ширина и височина, без да нарушава съотнощението , но някои части от картинката може да са отрязани. Image.PreserveAspectFit от друга страна смалява картинката така, че да се събере в дадените ширина и височина, но може да има празни полета.

Използване на много ядра

Qt Quick ви позволява да използвате повече от една нишка, но това зависи от вас и за какво устройство правите приложението. Като за начало трябва да знаете, че картинките винаги се зареждат синхронно. Това означава, че Image задържа изпълнението на QML, кода докато не успее да зареди изобравението. Може да звучи лошо, но няма ли да е по-добре простo да показва празен правоъгълник докато картинката се зареди? Можете да пробвате този вариант като добавите следният ред към Image делегата:

asynchronous: true

Както може би сте забелязали, скролирането е доста по гладко от преди, но с цената на премигвания, тъй като може да отнеме до 100мс, докато картинката се зареди. За наш късмет, това може да се оправи! За да постигнем напълно гладко и плавно скролиране, ще направим така, че асинхронното зареждане на картинките да става извън видимата част, като използваме кеш буфера на ListView. ListView ни предоставя атрибута cacheBuffer, който дефинира колко делегата да да бъдат заредени преди и след видимата зона. cacheBuffer се измерва в брой пиксели и дефинира размера на частта от ListView-то, в която делегатите трябва да се кешират. Ако делегати излязат от тази област, те се унищожават. Ако навлязат в зоната, те се създават. По подразбиране cacheBuffer е нула и за това ние виждаме как се създават делегатите. За това нека да сложим cacheBuffer на някаква достатъчна стойност:

ListView {
 
 cacheBuffer: width * 4
 
}

В нашият пример, това ще зарежда предварително по 4 картинки преди и след видимата зона. Когато потребителя започне да се движи по ListView-то, там ще има вече до 4 заредени в паметта изображения, които да гарантират плавно придвижване и други ще се зареждат в невидимата част.

Фина настройка

Ако продължава да има някакви премигвания, можете да стартирате qmlviewer с опцията -opengl.