QML Как рисовать разные для grabToImage()

Есть ли какой-нибудь возможный способ сделать grabToImage() буфер отличается от того, что отображается в графическом интерфейсе? я использую ChartView без легенды в графическом интерфейсе и хотите экспортировать его в PNG с легендой. Итак, я стараюсь:

chartView.legend.visible = true
chartView.update()
chartView.grabToImage(function(result) {
    console.log("grabbed")

    var path = filename.toString().replace(/^(file:\/{2})/,"");
    console.log(path + result.saveToFile(path));
    chartView.legend.visible = false
    update();
});

Но оба эти обновления происходят только после того, как элемент управления выходит из этой функции, поэтому я не получаю легенду в PNG. Также хотелось бы, чтобы появление легенды было незаметным для пользователя. Есть ли способы сделать это в QML?

1 ответ

Решение

Я не уверен, правильно ли я вас понял.

Мое предложение состоит в том, чтобы не схватить Item вы отображаете, но копию этого, который вы затем изменяете, как вам нравится.
Копирование здесь не означает, что у вас есть один и тот же объект дважды, но что вы визуализируете его дважды, используя ShaderEffectSource, Прежде чем схватить это ShaderEffectSource к изображению, вы можете добавить все, что вам нравится.

В моем примере я показываю простой Rectangle с хорошим градиентом. Что я сохраняю, то же самое Rectangle который расширяется Text 'Я легенда'. Пользователь не увидит этот текст в представлении в любое время.

Rectangle {
    id: commonView
    width: 200
    height: 200
    gradient: Gradient {
        GradientStop { position: 0; color: 'steelblue' }
        GradientStop { position: 1; color: 'orange' }
    }
    MouseArea {
        anchors.fill: parent

        // don't grab the rectangle itself.
        onClicked: legendView.grabToImage(function(result) {
            console.log(result.saveToFile("something.png"));
        });
    }
}

ShaderEffectSource {
    id: legendView
    visible: false // Does not need to be shown.
    sourceItem: commonView
    width: 200
    height: 200
    Text {
        anchors {
            right: parent.right
            bottom: parent.bottom
        }
        text: 'I am legend'
    }
}

Вы можете оптимизировать производительность, только имея ShaderEffectSource активен или даже создан при необходимости.

Вы можете использовать ShaderEffectSource.live -возможность отключить его обновление. Тогда используйте scheduleUpdate() запустить обновление.

Это может выглядеть так:

Rectangle {
    id: commonView
    width: 200
    height: 200
    gradient: Gradient {
        GradientStop { position: 0; color: 'steelblue' }
        GradientStop { id: gs1; position: 1; color: 'orange' }
    }
    MouseArea {
        anchors.fill: parent
        onClicked: {
            gs1.position -= 0.1
            legendView.save()
        }
    }
}

ShaderEffectSource {
    id: legendView
    y: 200
    visible: false // Do not render it (will only be rendered when called grapToImage()
    sourceItem: commonView
    width: 200
    height: 200
    live: false // Will only be updated, when explicitly called for
    function save() {
        console.log('Schedule Save')
        scheduleUpdate() // explicitly update. grabToImage() will force rendering afterwards.
        legendView.grabToImage(function(result) {
                        console.log(result.saveToFile("something" +gs1.position.toFixed(1) + ".png"));
                    })
    }

    // Put additional stuff on it.
    Text {
        anchors {
            right: parent.right
            bottom: parent.bottom
        }
        text: 'I am legend!'
    }
}
Другие вопросы по тегам