【问题标题】:Limit amount of files user can select in QFileDialog限制用户可以在 QFileDialog 中选择的文件数量
【发布时间】:2020-06-17 15:58:25
【问题描述】:

代码如下:

dialog = new QFileDialog(this);
dialog->setFileMode(QFileDialog::ExistingFiles);
connect(dialog, SIGNAL(currentChanged(const QString&)),
    this, SLOT(dialogSelectionChanged(const QString&)));

void MainWindow::dialogSelectionChanged(const QString& file)
{
    QStringList selected = dialog->selectedFiles();
}

问题是

  • fileSelected(const QString&)filesSelected(const QStringList&) 仅在我按下“打开”按钮后发出。
  • currentChanged(const QString&) 只传递新选择的文件
  • selectedFiles() 在这种情况下返回我在上一步选择的文件。可能对话框在发出 currentChanged(const QString&) 后会更新文件。

这就是为什么我不知道如何跟踪当前选定的文件。 另一个问题是,如果用户超出允许选择的限制,我目前不知道如何取消对最后选择的文件的选择。

我见过几个例子,人们使用 QProxyModel 或自定义实现 QFileDialog 来实现自定义功能,但我不确定什么最适合我的需求。

【问题讨论】:

  • 您是否尝试过覆盖selectFile(const QString& filename)?可能是您正在寻找的那个。
  • 从文档看来,这不是一个虚函数
  • 不是,我查了资料。另外,这个方法在实现中没有用到,只是用户API的一部分,没有更多

标签: c++ qt qfiledialog


【解决方案1】:

没有这种方法,但是一旦您的客户完成选择,您就可以通过调用方法 selectedFiles 来验证操作

QStringList 的大小是否大于您的约束,您可以中止操作并显示一些错误消息。

喜欢

void MainWindow::dialogSelectionChanged(const QString& file)
{
    QStringList selected = dialog->selectedFiles();
    if(selected.size()>LIMIT)
    {
        showErrorMsg("some helpful mesage");
    }

}

【讨论】:

  • 如果找不到更好的解决方案,我将使用它。谢谢!
  • 没有别的,除非你自己写Dialog¯\_(ツ)_/¯
【解决方案2】:

如果您愿意接受无耻的黑客攻击,可以这样做:-)

假设以下代码...

QFileDialog fd;

使用fd.findChildren<QListView *>() 检查fd 发现它有两个子代,要么是QListView,要么继承自QListView...

  1. QListView 命名为 listView
  2. QSidebar 命名为侧边栏

(其中 Qsidebar 是 Qt 私有的)。

假设名为listViewQListView 是您感兴趣的小部件,您可以将回调连接到其选择模型...

QFileDialog fd;
for (const auto &i: fd.findChildren<QListView *>("listView")) {
  auto *sm = i->selectionModel();
  QObject::connect(sm, &QItemSelectionModel::selectionChanged,
                   [sm](const QItemSelection &selected, const QItemSelection &deselected)
                     {

                       /*
                        * Here we pass a hard-coded max selected items
                        * value of 5 to the real callback/slot.
                        */
                       handle_selection_updated(5, sm, selected, deselected);
                     });
}

这里handle_selection_updated有如下定义...

void handle_selection_updated (int selection_max, QItemSelectionModel *sm,
                               const QItemSelection &selected,
                               const QItemSelection &deselected)
{

  /*
   * We need to remember the last valid selection.  The following
   * is declared static in this simple case but would generally be
   * a class member in `real' code.
   */
  static QItemSelection last_selected;

  /*
   * Because we update the selection model `sm' from within this
   * slot this function will recurse which will cause problems if
   * we don't detect it and take appropriate action.
   */
  static bool recursing = false;
  if (recursing)
    return;

  /*
   * If the number of rows selected is greater than the value
   * specified by `selection_max' then revert to the last valid
   * selection as specified by `last_selected'.
   */
  if (sm->selectedRows().size() > selection_max) {

    /*
     * The following call to QItemSelectionModel::clearSelection
     * will result in a recursive call to this function.  Set
     * `recursing' to true to catch this and avoid associated
     * problems.
     */
    recursing = true;

    /*
     * Now clear the selection and reset it to the items from
     * `last_selected'.
     */
    sm->clearSelection();
    for (const auto &i: last_selected.indexes()) {
      sm->select(i, QItemSelectionModel::Select);
    }
    recursing = false;
  }

  /*
   * Update `last_selected'.
   */
  last_selected = sm->selection();
}

我只是简单地测试了上面的代码,但它的行为似乎符合要求。

【讨论】:

    猜你喜欢
    • 2011-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多