c++ QFileDialog:如何通过触摸屏输入选择多个文件?

vyswwuz2  于 2023-05-08  发布在  其他
关注(0)|答案(1)|浏览(368)

在我们使用Qt 4并支持触摸输入的应用程序中,我们使用带有QFileDialog::DontUseNativeDialogQFileDialog::ExistingFiles选项的QFileDialog。第一个是必需的,因为我们设置了自己的样式表,而这在本机对话框中不起作用。第二个是用于选择多个文件,这是我们想要做的。
问题是,一个不能选择多个文件与触摸输入在QFileDialog,因为我们没有Shift或CTRL可用。在Windows中,这个问题是通过在项目中添加复选框来解决的,但QFileDialog没有复选框。
我试图操纵QFileDialog使其显示项目的复选框,但失败了。
我尝试交换底层QTreeViewQListView使用的QFileSystemModel,但这会破坏模型和对话框之间的信号槽连接。我无法找到一种方法来恢复他们,因为他们是深埋在私人肠子的对话。
目前我能想到的唯一解决办法就是写一个全新的对话框,但我想避免这种努力。

  • 那么,有没有一种方法可以将复选框添加到QFileDialog模型视图中呢?
  • 你有其他的想法如何选择多个文件可以成为可能?
  • 问题在Qt 5中解决了吗?无论如何,我们都要更新。
nwlls2ji

nwlls2ji1#

由于我未能将复选框添加到项目视图中,我实现了一个“黑客”解决方案。它在对话框中添加了一个额外的可检查按钮,充当“ctrl”键。选中该按钮后,可以选择多个文件。这个解决方案有点难看,因为它依赖于了解对话框的内部结构,但它确实完成了这项工作。
这里是header的代码。

// file touchfiledialog.h

/*
Event filter that is used to add a shift modifier to left mouse button events.
This is used as a helper class for the TouchFileDialog
*/
class EventFilterCtrlModifier : public QObject
{
    Q_OBJECT;

    bool addCtrlModifier;

public:
    EventFilterCtrlModifier( QObject* parent);

    void setAddCtrlModifier(bool b);

protected:
    virtual bool eventFilter( QObject* watched, QEvent* e);
};

/*
TouchDialog adds the possibility to select multiple files with touch input to the QFileDialog.
This is done by adding an extra button which can be used as control key replacement.
*/
class QTOOLS_API TouchFileDialog : public QFileDialog
{
    Q_OBJECT

    EventFilterCtrlModifier* listViewEventFilter;
    EventFilterCtrlModifier* treeViewEventFilter;

    bool initialized;

public:
    TouchFileDialog( QWidget* parent);

protected:
    virtual void showEvent( QShowEvent* e);

private slots:
    void activateCtrlModifier(bool b);

private:
    void initObjectsForMultipleFileSelection();
};

随着实施…

// file touchfiledialog.cpp

#include "touchfiledialog.h"

EventFilterCtrlModifier::EventFilterCtrlModifier(QObject* parent)
    : QObject(parent)
    , addCtrlModifier(false)
{

}

void EventFilterCtrlModifier::setAddCtrlModifier(bool b)
{
    addCtrlModifier = b;
}

bool EventFilterCtrlModifier::eventFilter(QObject* watched, QEvent* e)
{
    QEvent::Type type = e->type();
    if( type == QEvent::MouseButtonPress || type == QEvent::MouseButtonRelease)
    {
        if( addCtrlModifier)
        {
            QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(e);
            // Create and post a new event with ctrl modifier if the event does not already have one.
            if( !mouseEvent->modifiers().testFlag(Qt::ControlModifier)) 
            {
                QMouseEvent* newEventWithModifier = new QMouseEvent( 
                    type, 
                    mouseEvent->pos(),
                    mouseEvent->globalPos(), 
                    mouseEvent->button(),
                    mouseEvent->buttons(),
                    mouseEvent->modifiers() | Qt::ControlModifier
                    );

                QCoreApplication::postEvent(watched, newEventWithModifier);

                return true;    // absorb the original event
            }
        }
    }

    return false;
}

//#######################################################################################
TouchFileDialog::TouchFileDialog(QWidget* parent)
    : QFileDialog(parent)
    , listViewEventFilter(NULL)
    , treeViewEventFilter(NULL)
    , initialized(false)
{

}

void TouchFileDialog::showEvent(QShowEvent* e)
{
    // install objects that are needed for multiple file selection if needed
    if( !initialized)
    {
        if( fileMode() == QFileDialog::ExistingFiles)
        {
            initObjectsForMultipleFileSelection();
        }

        initialized = true;
    }

    QFileDialog::showEvent(e);
}

void TouchFileDialog::initObjectsForMultipleFileSelection()
{
    // install event filter to item views that are used to add ctrl modifiers to mouse events
    listViewEventFilter = new EventFilterCtrlModifier(this);
    QListView* listView = findChild<QListView*>();
    listView->viewport()->installEventFilter(listViewEventFilter);

    treeViewEventFilter = new EventFilterCtrlModifier(this);
    QTreeView* treeView = findChild<QTreeView*>();
    treeView->viewport()->installEventFilter(treeViewEventFilter);

    QGridLayout* dialogLayout = static_cast<QGridLayout*>(layout()); // Ugly because it makes assumptions about the internals of the QFileDialog

    QPushButton* pushButtonSelectMultiple = new QPushButton(this);
    pushButtonSelectMultiple->setText(tr("Select multiple"));
    pushButtonSelectMultiple->setCheckable(true);
    connect( pushButtonSelectMultiple, SIGNAL(toggled(bool)), this, SLOT(activateCtrlModifier(bool)));

    dialogLayout->addWidget(pushButtonSelectMultiple, 2, 0);
}

void ZFFileDialog::activateCtrlModifier(bool b)
{
    listViewEventFilter->setAddCtrlModifier(b);
    treeViewEventFilter->setAddCtrlModifier(b);
}

TouchFileDialog将事件过滤器安装到项目视图中,当选中对话框中的相应按钮时,该事件过滤器将向视图的鼠标事件添加ControlModifier。
请随意发布其他解决方案,因为这有点即兴。

相关问题