通过按钮单击触发带有参数的 QQuickImageProvider::requestImage()

Posted

技术标签:

【中文标题】通过按钮单击触发带有参数的 QQuickImageProvider::requestImage()【英文标题】:Trigger QQuickImageProvider::requestImage() with parameter via button click 【发布时间】:2018-10-22 13:52:58 【问题描述】:

我有一个使用QQuickImageProvider 显示图像的 QQuickControls 2 应用程序。有时我只是想显示一个未经编辑的图像,所以我只是像这样实现我的 QML:

Image 
    id: image
    fillMode: Image.PreserveAspectFit
    source: "image://provider/foo/bar/placeholder.jpg"

其他时候我会想显示图像的编辑版本。我如何告诉QQuickImageProvider::requestImage() 我想展示一个编辑过的版本?

QImage ImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)

    // Somehow determine we need to show an editted version of the image
    if (showEdited) 
        // maybe pass query parameters to the id?
        // for eg 'image://provider/foo/bar/i.jpg?edit=true'
        // Then I parse the id string for this query parameter?

        cv::Mat src = cv::imread(id.toStdString());

        // ... perform some image processing to the image

        QImage img = convertMatToQImage(src);

        if (size)
            *size = QSize(img.width(), img.height());

        return img;
    
    else 
        QImage img(id);

        if (size)
            *size = QSize(img.width(), img.height());

        return img;
    

显示编辑图像的触发器是通过单击按钮:

Button 
    id: processBtn
    text: qsTr("Process")
    onClicked: 
        // Somehow call QQuickImageProvider::requestImage() and specify we are editting it?
        // Maybe...
        // image.source = image.source + "?edit=true"   
    

【问题讨论】:

传递id,例如imageimage-edited 并在requestImage() 中解析它,或者,这是正确的,创建2 个图像提供程序并使用你需要的。 【参考方案1】:

我可以传递图像的 url,并使用 QUrl 类来获取 edit=true,如下所示:

QImage ImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)

    Q_UNUSED(requestedSize)
    QUrl url(id);
    bool showEdited = url.query() == "edit=true";
    if (showEdited) 
        cv::Mat src = cv::imread(url.toLocalFile().toStdString());
        
        ///begin process
        cv::GaussianBlur(src, src, cv::Size(3,3), 0, 0, cv::BORDER_DEFAULT );
        cv::Mat grad_x, grad_y;
        cv::Mat abs_grad_x, abs_grad_y, src_gray, grad;
        int scale = 1;
        int delta = 0;
        int ddepth = CV_16S;
        cv::cvtColor( src, src_gray, CV_BGR2GRAY );
        /// Gradient X
        cv::Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, cv::BORDER_DEFAULT );
        /// Gradient Y
        cv::Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, cv::BORDER_DEFAULT );
        convertScaleAbs( grad_x, abs_grad_x );
        convertScaleAbs( grad_y, abs_grad_y );
        addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );
        ///end process
        QImage img = convertMatToQImage(grad);
        if (size)
            *size = QSize(img.width(), img.height());
        return img;
    
    else 
        QImage img(url.toLocalFile());
        if (size)
            *size = QSize(img.width(), img.height());
        return img;
    


ma​​in.qml

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.11
import QtQuick.Dialogs 1.0

Window 
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    property string path: ""
    onPathChanged: image.source = path == "" ? "": "image://provider/"+ path
    ColumnLayout 
        anchors.fill: parent
        Image 
            id: image
            Layout.preferredWidth: parent.width
            Layout.preferredHeight: parent.height * 0.8
            fillMode: Image.PreserveAspectFit
        
        Pane 
            id: pane
            Layout.fillWidth: true
            RowLayout 
                width: parent.width
                Button 
                    id: selectBtn
                    text: qsTr("Select")
                    Layout.alignment: Qt.AlignHCenter
                    onClicked: fileDialog.open();
                
                Button 
                    id: processBtn
                    text: qsTr("Process")
                    Layout.alignment: Qt.AlignHCenter
                    onClicked: if(path != "")  image.source = "image://provider/"+ path + "?edit=true"
                
            
        
    
    FileDialog 
        id: fileDialog
        title: "Please choose a file"
        folder: shortcuts.home
        nameFilters: [ "Image files (*.jpg *.png)", "All files (*)" ]
        onAccepted:  path = fileDialog.fileUrl
    

原文:

流程:

完整的例子可以在this link.找到

【讨论】:

【参考方案2】:

使用id 而不使用类似的扩展名:

Button 
    property bool edit: false
    onClicked: 
         image.source = "image:://provider/foo/path" + (edit ? placeholder-edit : placeholder ) 
    

但是您可以在没有图像提供程序的情况下使用自定义属性实现 QQuickPaintedItem

【讨论】:

以上是关于通过按钮单击触发带有参数的 QQuickImageProvider::requestImage()的主要内容,如果未能解决你的问题,请参考以下文章

导航栏按钮单击事件在单击其下方区域时触发。

单击 HTML 按钮时如何触发带有文本区域内容的文件下载

IOS Toolbarbutton项目不触发带有滚动条的动作

SharePoint 2013 Web 部件按钮单击事件未触发

输入触发器按钮单击

带有按钮 addTarget 事件的标签不会触发