QFileDialog:强制文件名

Posted

技术标签:

【中文标题】QFileDialog:强制文件名【英文标题】:QFileDialog: force file name 【发布时间】:2020-07-02 09:59:32 【问题描述】:

我想创建一个QFileDialog 设置为QFileDialog::AnyFile,其中文件名是固定的(但位置可以更改)。

到目前为止,我找到了问题QFileDialog - Saving a file with specified file name,但没有得到回答。 有直接选择目录的伪答案,这是我迄今为止在我的项目中所做的。然而,通过测试程序的人发现这令人困惑,因此不是一个可接受的答案。

到目前为止,我尝试的是派生QFileDialog,然后强制执行此操作,但我不知道该尝试什么了。当点击不同的文件时,我设法通过对适当的信号做出反应来重置文件名:

FixedFileDialog::FixedFileDialog(QWidget* parent) : QFileDialog(parent)

    connect(this, SIGNAL(currentUrlChanged(const QString&)), this, SLOT(current_changed(const QString&)));


void FixedFileDialog::current_changed(const QString&)

    selectFile(_filename);

(以_filename为开头设置的成员。)

到目前为止,这有效,但它不会阻止用户在行编辑中输入不同的名称。而且我还没有发现在这种情况下发出的任何信号。

另一个尝试是尝试访问 QLineEdit 小部件本身以禁用它,但我不知道如何。我试过了

QLineEdit* line_edit = dialog.d_func()->lineEdit();

dialog 属于派生类。)

这不起作用,因为d_func()QFileDialog 中是私有的。

有人知道该怎么做吗?

【问题讨论】:

QFileDialog::Directory - 就是您要找的。不需要修改文件名时可以选择目录。 @DmitrySazonov 我特意写了我不能用这个。 【参考方案1】:

我必须承认,我想到的这是一个肮脏的黑客。另一方面,OP对我来说似乎有些绝望。所以,我把它贴出来(带着一些疑问)。

由于OP的声明而提出的我的想法:

QLineEdit* line_edit = dialog.d_func()->lineEdit();

(对话框属于派生类。)

这不起作用,因为d_func()QFileDialog 中是私有的。

虽然d_func() 是私有的,但Qt 小部件提供了一种后门,因为它们的所有权管理可以被利用:

每个QObject 都提供一个其子级列表。因此,这个子树的简单遍历应该在 quest 中传递 QLineEdit(这是我在 Qt 5.13 中当前实现的 QFileDialog 中唯一的一个)。

这是我在示例中尝试过的:

/ Qt header:
#include <QtWidgets>

QLineEdit* findFirstQLineEdit(QWidget *pQWidget)

  //qDebug() << "Inspect" << pQWidget;
  const QObjectList pQObjs = pQWidget->children();
  for (QObject *pQObj : pQObjs) 
    if (QLineEdit *pQLineEdit = dynamic_cast<QLineEdit*>(pQObj)) 
      qDebug() << "Found:" << pQLineEdit;
      return pQLineEdit;
     else if (QWidget *pQWidget = dynamic_cast<QWidget*>(pQObj)) 
      if (QLineEdit *pQLineEdit = findFirstQLineEdit(pQWidget)) 
        return pQLineEdit;
      
    
  
  return nullptr;


// main application
int main(int argc, char **argv)

  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // setup GUI
  QFileDialog qFileDlg(nullptr,
    QString::fromUtf8("Choose Dir. to Save File"),
    QDir::currentPath());
  qFileDlg.show();
  // manipulate the file name input
  qFileDlg.selectFile("CMakeLists.txt");
  QLineEdit *const pQEdit = findFirstQLineEdit(&qFileDlg);
  pQEdit->setReadOnly(true);
  // runtime loop
  return app.exec();

输出:

文件名行编辑器是只读的。不允许编辑或删除,但仍可以从外部复制和更改内容。 (对于这种情况,OP 似乎已经找到了另一种解决方案。)

注意:

我的第一个想法是在派生自QFileDialog 的类的构造函数中调用findFirstQLineEdit()。这没有用!调试输出证明QFileDialog 在构造后没有任何子代。我得出的结论是,QFileDialog 的子代是稍后创建的——但肯定必须在 show() 之后创建。

要将这个 hack 嵌入到派生类中,在 QFileDialog::showEvent() 的覆盖中进行操作可能就足够了。 (我没有测试。)

【讨论】:

啊,非常感谢,工作正常。至于你的笔记,我假设它可以在施工后立即使用。在我的代码中,我创建了派生类的一个对象,设置了一些属性(如setFileMode),然后使用您的代码禁用小部件,然后调用exec()

以上是关于QFileDialog:强制文件名的主要内容,如果未能解决你的问题,请参考以下文章

QFileDialog : 获取文件名

QFileDialog - 用指定的文件名保存文件

需要用 QFileDialog 保存一个新文件

接受单个文件或单个目录的 QFileDialog

如何在 QFileDialog 中过滤带有空格字符的文件名?

Qt入门系列开发教程对话框QFileDialog文件对话框