Мне не очень нравится этот вопрос, так как он ничего особенного не спрашивает. Документация по Qt очень обширна, поэтому мне часто кажется странным, когда люди говорят, что прочитали документацию, руководства и примеры, но так и не нашли то, что искали. Тем не менее, я думаю, что понимаю суть того, о чем вы спрашиваете, и думаю, что ответ может быть полезен для некоторых, поэтому я попытаюсь ответить на него.
main.cpp
#include <QtGui/QGuiApplication>
#include <QtQml>
#include <QQuickItem>
#include "qtquick2applicationviewer.h"
class ApplicationItem : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(QString title MEMBER mTitle NOTIFY titleChanged)
public:
ApplicationItem(QQuickItem *parent = 0) : QQuickItem(parent) {
}
public slots:
void close() {
emit closed(this);
}
signals:
void titleChanged(QString title);
void closed(ApplicationItem *app);
private:
QString mTitle;
};
class SceneItem : public QQuickItem
{
Q_OBJECT
public:
SceneItem() {
}
public slots:
void startApp(const QString &qmlFile) {
QQmlComponent *component = new QQmlComponent(qmlEngine(this), QUrl(qmlFile));
if (component->isLoading()) {
QObject::connect(component, SIGNAL(statusChanged(QQmlComponent::Status)),
this, SLOT(componentStatusChanged()));
} else {
// The component was synchronously loaded, but it may have errors.
if (component->isError()) {
qWarning() << "Failed to start application:" << component->errorString();
} else {
addApp(component);
}
}
}
void componentStatusChanged(QQmlComponent::Status status) {
QQmlComponent *component = qobject_cast<QQmlComponent*>(sender());
if (status == QQmlComponent::Ready) {
addApp(component);
} else if (status == QQmlComponent::Error) {
qWarning() << "Failed to start application:" << component->errorString();
}
}
void appClosed(ApplicationItem *app) {
int appIndex = mApplications.indexOf(app);
if (appIndex != -1) {
mApplications.removeAt(appIndex);
app->deleteLater();
}
}
private:
void addApp(QQmlComponent *component) {
ApplicationItem *appItem = qobject_cast<ApplicationItem*>(component->create());
appItem->setParentItem(this);
connect(appItem, SIGNAL(closed(ApplicationItem*)), this, SLOT(appClosed(ApplicationItem*)));
mApplications.append(appItem);
delete component;
}
QList<ApplicationItem*> mApplications;
};
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QtQuick2ApplicationViewer viewer;
qmlRegisterType<ApplicationItem>("Test", 1, 0, "ApplicationItem");
qmlRegisterType<SceneItem>("Test", 1, 0, "SceneItem");
viewer.setMainQmlFile(QStringLiteral("qml/quick/main.qml"));
viewer.showExpanded();
return app.exec();
}
#include "main.moc"
Я представил оба класса как подклассы QQuickItem. SceneItem
состоит из множества экземпляров ApplicationItem
, которые добавляются к сцене путем вызова startApp()
. Этот слот принимает в качестве аргумента путь к файлу QML. Этот файл может быть загружен по сети или из локального файла, поэтому мы учитываем возможность как синхронной, так и асинхронной загрузки.
Файл QML должен описывать внешний вид приложения, и сцена ожидает, что его корневой тип будет ApplicationItem
. Например, вот MySweetApp.qml:
import QtQuick 2.0
import QtQuick.Controls 1.0
import Test 1.0
ApplicationItem {
id: someAppStyle
title: "My Sweet App"
width: 100
height: 100
MouseArea {
anchors.fill: parent
drag.target: parent
}
Rectangle {
radius: 4
color: "lightblue"
anchors.fill: parent
Text {
anchors.left: parent.left
anchors.right: closeButton.right
anchors.leftMargin: 4
anchors.top: parent.top
anchors.topMargin: 4
text: someAppStyle.title
}
Button {
id: closeButton
anchors.right: parent.right
anchors.rightMargin: 4
anchors.top: parent.top
anchors.topMargin: 2
onClicked: close()
text: "x"
width: 20
height: width
}
}
}
Приложения могут закрыться, вызвав слот close()
, объявленный в ApplicationItem
.
Вот main.qml:
import QtQuick 2.0
import QtQuick.Controls 1.0
import Test 1.0
SceneItem {
id: scene
width: 360
height: 360
Button {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
text: "Launch app"
onClicked: scene.startApp("qml/quick/MySweetApp.qml")
}
}
Здесь объявляется SceneItem
, а также простой интерфейс для запуска нескольких экземпляров My Sweet App (это очень полезное приложение).
Я считаю, что это наиболее подходящий способ сделать то, что вы просите. Это позволяет избежать проблем с настройкой списков ApplicationItems
в C++, которые доступны для QML (на самом деле это не так уж сложно, но это одна из областей, где документация может быть более очевидной), и дает пользователям вашей ОС свободу в том, как выглядят приложения. . Если вы хотите быть более строгим в том, что можно стилизовать, я бы посоветовал посмотреть, как Qt Quick Controls выполняет стилизацию.
person
Mitch
schedule
26.03.2014