|
23.09.2010, 02:05
|
#1
|
|
Qt QML : декларативный интерфейс, императивная логика
Qt захватит мир !
при разработке интерфейсов мы очень часто сталкиваемся с огромным количеством рутины, обычно нужно работать со сложным конечным автоматом, кучей асинхронных анимаций и отзывчивостью к юзеру
императивный путь работы с интерфейсом тернист, а звёзд редко кто достигает, а если и достигает то следующий раз опять все тернии надо проходить (редко какой интерфейсный проект проще поддерживать чем переписать заново), а вот декларативный способ задания интерфейса всё меняет местами, мы задаем только то что хотим получить, всё остальное на себя берет декларативный движок
добавим к этому всему что Qt имеет систему сигналов-слотов и свой препроцессор (в общем-то свою билд-систему, и свой IDE ), и что же мы получим ? мы получим QML, декларативный язык задания интерфейса со сквозным двухсторонним биндингом с C++ кодом ! другими словами мы теперь пишем интерфейс на языке подобном html и он работает напрямую с нашей C++ логикой (слава чистому MVC, слава)
перейдем к примеру :
обычный класс на Qt :
class Stopwatch : public QObject
{
Q_OBJECT
public:
Stopwatch();
Q_INVOKABLE bool isRunning() const;
public slots:
void start();
void stop();
private:
bool m_running;
};
к обычным методам (не сигналам и не слотам) добавляется только Q_INVOKABLE перед декларацией метода, что в сотни-тыщи-миллионы-раз проще и лучше любого биндинга к скриптовым системам, собственно слоты start и stop уже можно использовать из QML
что мы пишем в qml :
import Qt 4.7
Rectangle {
width: 300
height: 300
MouseArea {
anchors.fill: parent
onClicked: {
if (stopwatch.isRunning())
stopwatch.stop()
else
stopwatch.start();
}
}
}
как видим тут объявляется область 300 на 300, в ней создается область работы с мышкой на весь размер родительской области, а по нажатию вызываются наши C++ методы ! (так же возможно наоборот - вызывать QML функции из C++ кода)
сам QML очень гибкий и базируется на JavaScript, что гарантирует некую лёгкость и гибкость изложения кода, любой валидный JavaScript код можно использовать как значение для параметров объектов, сам QML имеет встроенные средства для задания стейтов (кнопка имеет нажатый и не нажатый стейт к примеру), можно задавать любые параметры в стейтах, и имеет средства анимации между стейтами так же имеются встроенные средства для анимации параметров
к примеру :
Rectangle {
id: rect
width: 120; height: 200
Image {
id: img
source: "pics/qt.png"
x: 60 - img.width/2
y: 0
SequentialAnimation on y {
loops: Animation.Infinite
NumberAnimation { to: 200 - img.height; easing.type: Easing.OutBounce; duration: 2000 }
PauseAnimation { duration: 1000 }
NumberAnimation { to: 0; easing.type: Easing.OutQuad; duration: 1000 }
}
}
}
реализация QML называется Qt Declarative, доступна в релизе Qt 4.7, визуальный редактор для QML будет встроен в Qt Creator 2.1 (сейчас в релизе 2.0.1, 2.1 скоро будет )
Qt 4.7 доступен на огромнейшем количестве разнообразных платформ, написал один раз и оно работает на симбиане, meego, windows, linux, mac и тд и тд (собсно сам Qt под LGPL лицензией)
ps. сигналы - слоты это механизм передачи вызовов сигналов в вызов слота, ближайшая аналогия - визуальное программирование логики, там тоже стрелочки между блоками таскаем, откуда тащим - сигнал, куда - слот, вызывая один из нескольких сигналов (физически декларируем метод, реализует сам Qt), вызывается слот к которому сигналы привязаны (физически описывается как метод только в секции slots)
|
|
|
Эти 11 пользователя(ей) сказали Спасибо за это полезное сообщение:
|
.Squid (23.09.2010), baton4ik (23.09.2010), BlackDragon (27.09.2010), falcon (23.09.2010), HolyDel (23.09.2010), impersonalis (23.09.2010), pax (25.09.2010), Phantom (25.09.2010), Randomize (23.09.2010), Reks888 (23.09.2010), Жека (24.09.2010)
|
27.09.2010, 02:21
|
#2
|
|
Ответ: Qt QML : декларативный интерфейс, императивная логика
чтобы опробовать инструмент решил написать понг чисто на QML, в принципе результирующий код вышел немного громоздким из-за асинхронного javascript кода и qml анимаций
мышкой управляются обе платформы, скорость игры постепенно увеличивается, необходимо набрать наибольшее количество очков
// imports
import Qt 4.7
// root object
Rectangle
{
id:screen; width:1024; height:768; color:"#DDDDDD"
// game text, show status of the game
Text
{
id:gameText;
anchors.top:screen.top; anchors.horizontalCenter:screen.horizontalCenter
text:"QML pong by jimon"
}
// score text
Text
{
id:gameScoreText;
anchors.top:screen.top; x:5;
font.family: "Courier New"; font.pointSize: 16; color: "#000000"
function zeroPad(num, count)
{
while(num.length < count) num = "0" + num;
return num;
}
function setScore(score)
{
text = "SCORE : " + zeroPad(score.toString(), 7)
}
Component.onCompleted:setScore(0);
}
// ball
Rectangle
{
id:ball; width:64; height:64; color:"#000000"
x:(screen.width - ball.width) / 2; y:(screen.height - ball.height) / 2
property variant wayX: 0 // ball way X
property variant wayY: 0 // ball way Y
property double speed: 0
property double speedDefault: 0.25 // in pixels per millisec
// moving, use number animation on x and y, calculate duration by hands
// moving by javascript and etc is a really BAD idea
NumberAnimation on x {id:ballAnimX}
NumberAnimation on y {id:ballAnimY}
function moveTo(newV, oldV, anim)
{
anim.stop();
anim.duration = Math.abs(oldV - newV) / speed;
anim.from = oldV;
anim.to = newV;
anim.start();
}
function moveToX(newX)
{
moveTo(newX, ball.x, ballAnimX)
}
function moveToY(newY)
{
moveTo(newY, ball.y, ballAnimY)
}
function stopAnimations()
{
ballAnimX.stop();
ballAnimY.stop();
}
function setWayX(newWayX)
{
if(newWayX != wayX)
{
ball.moveToX(newWayX == 1 ? screen.width - ball.width : 0);
wayX = newWayX;
}
}
function setWayY(newWayY)
{
if(newWayY != wayY)
{
ball.moveToY(newWayY == 1 ? screen.height - ball.height : 0);
wayY = newWayY;
}
}
}
// left platform
Rectangle
{
id:left; width:32; height:128; color:"#5555FF"; anchors.left:screen.left
y:(screen.height - left.height) / 2
}
// right platform
Rectangle
{
id:right; width:32; height:128; color:"#5555FF"; anchors.right:screen.right
y:(screen.height - right.height) / 2
}
// game logic timer
Timer
{
interval:20; running:true; repeat:true
onTriggered:gameTick();
}
// work with mouse
MouseArea
{
id:mouse;
anchors.fill:screen; hoverEnabled:true
onPositionChanged:gameUpdateMouse();
onClicked:gameRestart();
}
property variant gameCanRestart:1;
property variant gameScore:0;
function gameTick()
{
if(!gameCanRestart) // if game running
{
gameScore = gameScore + 10;
gameScoreText.setScore(gameScore);
ball.speed = ball.speed * 1.001;
}
if(gamePlatformCheck(left)) // horizontal moving
ball.setWayX(1);
if(gamePlatformCheck(right))
ball.setWayX(-1);
else if(ball.x <= 0 || ball.x >= screen.width - ball.width)
screen.gameLose();
if(ball.y >= screen.height - ball.height) // vertical moving
ball.setWayY(-1);
else if(ball.y <= 0)
ball.setWayY(1);
}
function gamePlatformCheck(platform)
{
return (Math.abs(platform.x - ball.x + (platform.width - ball.width) / 2) < (platform.width + ball.width) / 2) &&
(Math.abs(platform.y - ball.y + (platform.height - ball.height) / 2) < (platform.height + ball.height) / 2);
}
function gameUpdateMouse()
{
left.y = mouse.mouseY - left.height / 2;
right.y = mouse.mouseY - right.height / 2;
}
function gameLose()
{
gameText.text = "Game Over !";
ball.stopAnimations();
ball.x = (screen.width - ball.width) / 2;
ball.y = (screen.height - ball.height) / 2;
gameCanRestart = 1;
}
function gameRestart()
{
if(gameCanRestart)
{
gameScore = 0;
gameScoreText.setScore(gameScore);
ball.speed = ball.speedDefault;
ball.wayX = 0;
ball.wayY = 0;
ball.setWayX(-1);
ball.setWayY(-1);
gameText.text = "Game Started !";
gameCanRestart = 0;
}
}
}
основная громоздкость в необходимости хранить направление движения, потому что функция moveTo выполняется асинхронно с анимациями и может банально не дать анимации стартовать
подход выполнения логики в javascriptе мне совсем не понравился, он слишком сырой сейчас, попробую еще реализовать логику на C++
|
|
|
27.09.2010, 20:46
|
#3
|
Бывалый
Регистрация: 03.12.2008
Адрес: наша раша
Сообщений: 762
Написано 129 полезных сообщений (для 245 пользователей)
|
Ответ: Qt QML : декларативный интерфейс, императивная логика
Один заголовок темы тянет на статью в солидном западном журнале
Дядя Дима не пугай детей...
ЗЫ Отвлеченный вопрос, сорри. А что такое explicit? Это термин из С++ или...?
__________________
Reality Simulation Games
Core 2 Duo 2,8GHz, RAM 1Gb, ATI R5670 1Gb. WinXP 32
|
(Offline)
|
|
27.09.2010, 21:56
|
#4
|
|
Ответ: Qt QML : декларативный интерфейс, императивная логика
Morganolla
запрет на автоприведение типов при вызове конструктора
к примеру :
class A
{
A(int V){ ... }
};
...
A foo = 5; // работает
A foo = A(5); // работает
class A
{
explicit A(int V){ ... }
};
...
A foo = 5; // не работает
A foo = A(5); // работает
|
|
|
Эти 4 пользователя(ей) сказали Спасибо за это полезное сообщение:
|
|
05.01.2013, 04:10
|
#5
|
|
Ответ: Qt QML : декларативный интерфейс, императивная логика
вышел qt quick 2, намного более шустрый фреймворк для qml
в итоге 1200 прямоугольников, которые случайно перемещаются по экранму и меняют цвет, выдает 60 фпс
import QtQuick 2.0
Rectangle
{
width: 1024
height: 768
focus: true
Repeater
{
id: rep;
model: 1200
Rectangle
{
id: rectt;
width: 16; height: 16;
color: "black";
SequentialAnimation
{
running: true; loops: -1;
ColorAnimation { target: rectt; property:"color"; from: "black"; to: "yellow"; duration: 1000;}
ColorAnimation { target: rectt; property:"color"; from: "yellow"; to: "black"; duration: 1000;}
}
}
}
Timer
{
interval: 16; running: true; repeat: true;
onTriggered:
{
for(var i = 0; i < rep.count; i++)
{
var o = rep.itemAt(i);
o.x = Math.random()*1024;
o.y = Math.random()*768;
}
}
}
Keys.onPressed: { if(event.key == Qt.Key_Escape) Qt.quit(); }
}
а сколько html5 на таком коде выдаст ?
еще одна хорошая новость, Desktop Components for QML почти готовы к релизу и будут включены в qt 5.1
посмотрите насколько просто и быстро создавать настольные приложения : http://www.youtube.com/watch?v=Y1pqL5bXe0A
|
|
|
Сообщение было полезно следующим пользователям:
|
|
05.01.2013, 05:46
|
#6
|
.
Регистрация: 05.08.2006
Сообщений: 10,429
Написано 3,454 полезных сообщений (для 6,863 пользователей)
|
Ответ: Qt QML : декларативный интерфейс, императивная логика
http://moka.co/rects/
Chrome: 150
FF: 116
1200 прямоугольников, цвет циклируется.
Шустро же
|
(Offline)
|
|
05.01.2013, 10:28
|
#7
|
ПроЭктировщик
Регистрация: 30.01.2012
Сообщений: 162
Написано 40 полезных сообщений (для 86 пользователей)
|
Ответ: Qt QML : декларативный интерфейс, императивная логика
Моя опера выдала ~20 фпс... Chrome (Яндекс.Б) ~20, Ыфафкш (Safari то есть под винду) ~65 фпс...
__________________
Blitz3D - СИЛА!
|
(Offline)
|
|
05.01.2013, 14:05
|
#8
|
|
Ответ: Qt QML : декларативный интерфейс, императивная логика
Сообщение от MoKa
|
попробуй не canvas, а на dom дереве, а то не интересно : в qml тесте создаются честные 1200 объектов, я кстати чуть модифицировал тест вчера и с 60 фпс рендерило уже 1700 объектов
ps. модифицированый тест http://pastebin.com/ATdvC6PK, фпс мерялся фрапсом
|
|
|
05.01.2013, 15:50
|
#9
|
[object Object]
Регистрация: 01.08.2008
Адрес: В России
Сообщений: 4,358
Написано 2,472 полезных сообщений (для 6,854 пользователей)
|
Ответ: Qt QML : декларативный интерфейс, императивная логика
Сообщение от jimon
попробуй не canvas, а на dom дереве, а то не интересно : в qml тесте создаются честные 1200 объектов, я кстати чуть модифицировал тест вчера и с 60 фпс рендерило уже 1700 объектов
|
Попробуй игры в экселе писать.
HTML нужен только для представления данных, а СSS для их стилизации.
Для динамики используется canvas/webgl.
__________________
Retry, Abort, Ignore? █
Intel Core i7-9700 4.70 Ghz; 64Gb; Nvidia RTX 3070
AMD Ryzen 7 3800X 4.3Ghz; 64Gb; Nvidia 1070Ti
AMD Ryzen 7 1700X 3.4Ghz; 8Gb; AMD RX 570
AMD Athlon II 2.6Ghz; 8Gb; Nvidia GTX 750 Ti
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
05.01.2013, 16:05
|
#10
|
|
Ответ: Qt QML : декларативный интерфейс, императивная логика
Сообщение от Randomize
Попробуй игры в экселе писать.
HTML нужен только для представления данных, а СSS для их стилизации.
Для динамики используется canvas/webgl.
|
what ? что же еще все сайты на canvas не делают ? ведь у некоторых анимаций больше чем данных
я ведь не выложил тест где 100500 прямоугольников рисуются шейдером за 1 дип, а то он бы выдал вам 100500 тыс фпс и было бы что canvas в 100500x раз медленее, я выложил честный тест с честными отдельными объектами, они эквивалентны dom, можно такой же тест с xaml провести
|
|
|
05.01.2013, 16:38
|
#11
|
[object Object]
Регистрация: 01.08.2008
Адрес: В России
Сообщений: 4,358
Написано 2,472 полезных сообщений (для 6,854 пользователей)
|
Ответ: Qt QML : декларативный интерфейс, императивная логика
Сообщение от jimon
what ? что же еще все сайты на canvas не делают ? ведь у некоторых анимаций больше чем данных
|
Потому что есть Internet Explorer, Windows XP, Intel GMA, Opera а так же ряд ущербных и беспросветных мобильных калькуляторов
__________________
Retry, Abort, Ignore? █
Intel Core i7-9700 4.70 Ghz; 64Gb; Nvidia RTX 3070
AMD Ryzen 7 3800X 4.3Ghz; 64Gb; Nvidia 1070Ti
AMD Ryzen 7 1700X 3.4Ghz; 8Gb; AMD RX 570
AMD Athlon II 2.6Ghz; 8Gb; Nvidia GTX 750 Ti
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 08:16.
|