当前区域设置更改时动态更改图像

时间:2017-09-11 08:39:36

标签: qt qml locale translation qtquick2

简单视频播放器的界面,由VideoImage项组成,由Blend QtGraphicalEffects混合而成。 Image已将MouseArea和半透明图形按钮与英文“硬编码”文本相关联。 QQuickImageProvider从以下位置提供的默认图片:

import QtQml 2.2

import QtQuick 2.9
import QtMultimedia 5.9

import QtGraphicalEffects 1.0

Blend {
    id: blender

    mode: "normal"

    property alias playbackState: video.playbackState

    onVisibleChanged: {
        if (!visible) {
            video.playlist.clear()
        }
    }

    source: Video {
        id: video

        visible: false

        width: blender.width
        height: blender.height

        fillMode: VideoOutput.Stretch

        playlist: Playlist {
            onErrorChanged: {
                if (error() !== Playlist.NoError) {
                    console.log("Error: %1 (%2)".arg(error()).arg(errorString()))
                    video.stop()
                }
            }

            function nextInLoop() {
                currentIndex = (currentIndex + itemCount + 1) % itemCount
            }

            function previousInLoop() {
                currentIndex = (currentIndex + itemCount - 1) % itemCount
            }
        }

        Connections {
            target: videoPlayerSingleton
            onSetPlaylist: {
                if (video.playlist.clear()) {
                    if (video.playlist.addItems(playlist)) {
                        if (index < 0) {
                            video.playlist.playbackMode = Playlist.Random
                        } else {
                            video.playlist.currentIndex = index
                            video.playlist.playbackMode = Playlist.Sequential
                        }
                        video.play()
                    }
                }
            }
        }

        autoPlay: true
        loops: MediaPlayer.Infinite
    }

    foregroundSource: Image {
        visible: false

        width: blender.width
        height: blender.height

        sourceSize: Qt.size(width, height)
        source: {
            switch (playbackState) {
            case MediaPlayer.PlayingState : return "image://videoplayer/pause"
            case MediaPlayer.PausedState : return "image://videoplayer/play"
            case MediaPlayer.StoppedState : return "image://videoplayer/logo"
            }
        }
        smooth: true
    }

    MouseArea {
        anchors.fill: parent

        readonly property rect previousButton: Qt.rect((130 - 40) / 1920, (505 - 40) / 1080, 80 / 1920, 80 / 1080)
        readonly property rect nextButton: Qt.rect((1800 - 40) / 1920, (505 - 40) / 1080, 80 / 1920, 80 / 1080)
        readonly property rect playPauseButton: Qt.rect((950 - 40) / 1920, (980 - 40) / 1080, 80 / 1920, 80 / 1080)
        readonly property rect backToCatalogButton: Qt.rect((1510 - 40) / 1920, (980 - 40) / 1080, 80 / 1920, 80 / 1080)
        readonly property rect openCollectionButton: Qt.rect((1710 - 40) / 1920, (980 - 40) / 1080, 80 / 1920, 80 / 1080)

        onClicked: {
            var hit = Qt.point(mouse.x / width, mouse.y / height)
            if (videoPlayerSingleton.contains(previousButton, hit)) {
                video.playlist.previousInLoop()
            } else if (videoPlayerSingleton.contains(nextButton, hit)) {
                video.playlist.nextInLoop()
            } else if (videoPlayerSingleton.contains(playPauseButton, hit)) {
                if (playbackState === MediaPlayer.PlayingState) {
                    video.pause()
                } else {
                    video.play()
                }
            } else if (videoPlayerSingleton.contains(backToCatalogButton, hit)) {
                videoPlayerSingleton.backToCatalog(video.playlist.currentIndex)
            } else if (videoPlayerSingleton.contains(openCollectionButton, hit)) {
                videoPlayerSingleton.openCollection(video.playlist.currentIndex)
            }
        }
    }
}

+ru_RU/子文件夹中还有相应的图像进入资源。

来自全局上下文的C ++ QObject单圈可能具有信号void languageChanged(QLocale locale);,当QTranslator替换每个加载的资源时,所有QCoreApplication::removeTranslator/installTranslator被发出。

// i18n.hpp:

#pragma once

#include <QtCore>

Q_DECLARE_LOGGING_CATEGORY(i18nCategory)

#ifndef PROJECT_DEFAULT_LOCALE
#define PROJECT_DEFAULT_LOCALE "ru_RU"
#endif

class Internationalization
        : public QObject
{

    Q_OBJECT

    static QMutex mutex;
    static Internationalization * self;

    explicit Internationalization(QString projectName = QStringLiteral(PROJECT_NAME));

public :

    static
    Internationalization * instance()
    {
        Q_ASSERT(qApp);
        QMutexLocker lock{&mutex};
        if (!self) {
            self = ::new Internationalization;
        }
        return self;
    }

    void setDependencies(QStringList dependencies);

public Q_SLOTS :

    void load(QLocale locale = QStringLiteral(PROJECT_DEFAULT_LOCALE));

Q_SIGNALS :

    void aboutToLanguageChanged();
    void languageChanged(QLocale locale);

private :

    QStringList translations;
    QList< QPointer< QTranslator > > translators;

};

#define i18n Internationalization::instance()

// i18n.cpp:

#include "i18n.hpp"

Q_LOGGING_CATEGORY(i18nCategory, "internationalization")

QMutex Internationalization::mutex;
Internationalization * Internationalization::self = Q_NULLPTR;

Internationalization::Internationalization(QString projectName)
    : QObject{qApp}
{
    translations.prepend(projectName);
    translations.prepend(PROJECT_NAME);
}

void Internationalization::setDependencies(QStringList dependencies)
{
    translations << dependencies;
}

void Internationalization::load(QLocale locale)
{
    // get_target_property(QT_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION)
    // qmake -query QT_INSTALL_TRANSLATIONS
    Q_ASSERT(!(translators.size() > translations.size()));
    while (translators.size() < translations.size()) {
        translators << ::new QTranslator{qApp};
    }
    Q_EMIT aboutToLanguageChanged();
    QLocale::setDefault(locale);
    QMutableListIterator translator{translators};
    for (const auto translation : translations) {
        Q_ASSERT(translator.hasNext());
        const auto t = translator.next();
        if (!QCoreApplication::removeTranslator(t)) {
            if (!t->isEmpty()) {
                qCDebug(i18nCategory).noquote()
                        << tr("Unable to remove translation from project %1")
                           .arg(translation);
            }
        }
        if (t->load(locale, translation, ".", ":/i18n")) {
            if (!QCoreApplication::installTranslator(t)) {
                qCDebug(i18nCategory).noquote()
                        << tr("Unable to install translation for %1 locale from project %2")
                           .arg(locale.name(), translation);
            }
        } else {
            qCDebug(i18nCategory).noquote()
                    << tr("Unable to load translation for %1 locale from project %2")
                       .arg(locale.name(), translation);
        }
    }
    Q_EMIT languageChanged(locale);
}

我想改变随着语言环境变化而发出的信号的图像位置。是否可以在运行时更改所选文件(即无需重新创建包含Item的父VideoPlayer}?

已连接的问题:首先受文件选择器影响的是:QImageReader Quick QQuickImageProvidersource:内部使用的文件路径{{1} }}?后者来自第一个。或者两者兼而有之?

1 个答案:

答案 0 :(得分:0)

方法是将您的语言环境分配给QML属性,然后将绑定表达式中的视频playbackState枚举属性用于source项的Image属性。

单击该按钮时,将更改QML语言环境属性,并自动重新评估sourceImage上的绑定表达式,从而使QQuickImageProvider提供新图像。

main.qml

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
import QtMultimedia 5.9

ApplicationWindow {
    id: applicationWindow
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Video {
        id: video
    }

    Column {
        id: contents

        property bool toggle: false

        function toggleLocale() {
            if (toggle) {
                // set QML locale
                applicationWindow.locale = Qt.locale("en_GB")
            } else {
                // set QML locale
                applicationWindow.locale = Qt.locale("ru_RU")
            }

            toggle = !toggle
        }

        Text { text: "locale %1".arg(applicationWindow.locale.name) }
        Text { text: "playbackState %1".arg(video.playbackState) }

        Button { text: "toggle locale"; onClicked: contents.toggleLocale() }

        Image {
            source: "image://colors/%1/%2".arg(applicationWindow.locale.name).arg(video.playbackState)
        }
    }
}

imageprovider.h

#ifndef IMAGEPROVIDER_H
#define IMAGEPROVIDER_H

#include <QDebug>
#include <QImage>
#include <QMediaPlayer>
#include <QQuickImageProvider>

class ImageProvider : public QQuickImageProvider
{
public:
    ImageProvider()
        : QQuickImageProvider(QQuickImageProvider::Image)
    {
    }

    QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize)
    {
        Q_UNUSED(requestedSize)

        QString localePath = id.split("/").at(0);
        QString fileName;

        int playbackState = id.split("/").at(1).toInt();
        switch (playbackState) {
        case QMediaPlayer::StoppedState:
            fileName = "logo.png";
            break;
        case QMediaPlayer::PlayingState:
            fileName = "play.png";
            break;
        case QMediaPlayer::PausedState:
            fileName = "pause.png";
            break;
        default:
            fileName = "logo.png";
            break;
        }

        // the following images are located under resources:
        // en_GB/logo.png
        // en_GB/play.png
        // en_GB/pause.png
        // ru_RU/logo.png
        // ru_RU/play.png
        // ru_RU/pause.png
        // which is why imagePath starts with : colon
        // but they could also be on the filesystem
        QString imagePath = QString(":%1/%2").arg(localePath).arg(fileName);
        qDebug() << "return Image file:" << imagePath;

        QImage image(imagePath);
        *size = image.size();

        // QImage supports copy, so can return like this
        // copy is returned, original on the stack is destroyed
        return image;
    }
};

#endif // IMAGEPROVIDER_H

的main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "imageprovider.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    engine.addImageProvider(QLatin1String("colors"), new ImageProvider());

    engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}