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

QFileDialog: How to select multiple files with touch-screen input?

本文关键字:选择 文件 输入 触摸屏 何通过 QFileDialog      更新时间:2023-10-16

在我们使用Qt 4并支持触摸输入的应用程序中,我们使用带有选项QFileDialog::DontUseNativeDialogQFileDialog::ExistingFilesQFileDialog。第一个是必需的,因为我们设置了自己的样式表,而这不适用于本机对话框。第二个是用于选择多个文件,这是我们想要做的

问题是,在QFileDialog中无法通过触摸输入选择多个文件,因为我们没有可用的ShiftCTRL

我试图操作QFileDialog,使其显示项目的复选框,但我失败了。

我试图交换底层QTreeViewQListView使用的QFileSystemModel,但这破坏了模型和对话框之间的信号槽连接。我找不到修复它们的方法,因为它们深深地埋在对话的私人肠道里。

目前,我能想到的唯一解决方案是编写一个全新的对话框,但我希望避免这种努力。

  • 那么,有没有办法在QFileDialog模型视图中添加复选框呢
  • 你对如何选择多个文件有其他想法吗
  • 问题在Qt 5中解决了吗?我们无论如何都要更新

由于我未能将复选框添加到项目视图中,我实现了一个"破解"的解决方案。它在对话框中添加了一个额外的可检查按钮,充当"ctrl"键。选中该按钮时,可以选择多个文件。这个解决方案有点难看,因为它依赖于了解对话框的内部,但它能完成任务。

这是标题的代码。。。

// 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。

请随意发布其他解决方案,因为这在某种程度上是即兴创作的。