简单视频播放器的接口由Video和Image项目组成,由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 singletone可能具有信号void languageChanged(QLocale locale);,该信号是在QCoreApplication::removeTranslator/installTranslator中为每个加载的资源替换所有QTranslator时发出的。
// 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的w/o )?
连接的问题:首先,文件选择器会影响什么:QImageReader的文件被内部用于QQuickImageProvider或source: of Quick Image?后者是从第一个派生出来的,或者两者兼而有之?
发布于 2017-09-26 07:11:01
方法是将区域设置分配给QML属性,然后在绑定表达式中使用该属性和视频playbackState enum属性到Image项的source属性。
当单击按钮时,QML属性将被更改,Image项的Image上的绑定表达式将自动重新计算,从而导致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_Hmain.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();
}https://stackoverflow.com/questions/46151449
复制相似问题