简体   繁体   English

QFileDialog:强制文件名

[英]QFileDialog: force file name

I want to create a QFileDialog set to QFileDialog::AnyFile in which the file name is fixed (but the location can be changed).我想创建一个QFileDialog设置为QFileDialog::AnyFile ,其中文件名是固定的(但位置可以更改)。

So far I found the question QFileDialog - Saving a file with specified file name , which was not answered.到目前为止,我发现了问题QFileDialog - Saving a file with specified file name ,没有得到回答。
There is the pseudo-answer of choosing the directory directly instead, which is what I did so far in my project.有直接选择目录的伪答案,这是我迄今为止在我的项目中所做的。 However, by people testing the program, this was found to be confusing, thus is not an acceptable answer.然而,通过人们测试该程序,发现这令人困惑,因此不是一个可接受的答案。

What I tried so far is to derive QFileDialog and then enforce this, but I don't know what to try anymore.到目前为止,我尝试的是派生QFileDialog然后强制执行此操作,但我不知道该尝试什么了。 I managed to reset the file name when a different file is clicked by reacting to the appropriate signal:当点击不同的文件时,我设法通过对适当的信号做出反应来重置文件名:

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);
}

(With _filename being a member set at the beginning.) (以_filename为开头的成员集。)

This works so far, but it does not prevent the user from entering a different name in the line edit.到目前为止,这有效,但它不会阻止用户在行编辑中输入不同的名称。 And I haven't found any signal which is emitted in this case.而且我还没有发现在这种情况下发出的任何信号。

Another attempt was trying to access the QLineEdit widget itself to disable it, but I don't know how.另一种尝试是尝试访问QLineEdit小部件本身以禁用它,但我不知道如何。 I tried我试过了

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

(With dialog being of the derived class.) dialog是派生的 class。)

This does not work, as d_func() is private in QFileDialog .这不起作用,因为d_func()QFileDialog中是私有的。

Does somebody have any other idea what to do?有人有其他想法该怎么做吗?

I must admit that this what I got in mind is a dirty hack.我必须承认,我想到的是一个肮脏的黑客。 On the other hand, the OP appeared somehow desperate to me.另一方面,OP对我来说似乎有些绝望。 So, I post it (with some doubts in mind).所以,我把它贴出来(带着一些疑问)。

My idea raised due to the statement of OP:由于OP的声明,我提出了我的想法:

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

(With dialog being of the derived class.) (对话框是派生的 class。)

This does not work, as d_func() is private in QFileDialog .这不起作用,因为d_func()QFileDialog中是私有的。

While d_func() is private, Qt widgets provide a kind of back-door due to their owner-ship management which can be exploited:虽然d_func()是私有的,但 Qt 小部件提供了一种后门,因为它们的所有权管理可以被利用:

Each QObject provides a list of its children.每个QObject都提供一个其子对象的列表。 So, a simple traversal of this children tree should pass the QLineEdit in quest (which is the only one in the current implementation of QFileDialog I have in Qt 5.13).因此,对这个子树的简单遍历应该在 quest 中传递QLineEdit (这是我在 Qt 5.13 中QFileDialog的当前实现中唯一的一个)。

This is what I tried in a sample:这是我在示例中尝试的:

/ 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();
}

Output: Output:

testQFileDialogQLineEditReadOnly 的快照

The file name line editor is read-only.文件名行编辑器是只读的。 Neither editing nor deleting is allowed but the contents may still be copied and changed from outside.不允许编辑或删除,但仍可以从外部复制和更改内容。 (For this case, OP seems to have found another solution, already.) (对于这种情况,OP 似乎已经找到了另一种解决方案。)

Note:笔记:

My first idea was to call findFirstQLineEdit() in the constructor of a class derived from QFileDialog .我的第一个想法是在派生自QFileDialog的 class 的构造函数中调用findFirstQLineEdit() This didn't work!这没有用! The debug output proofed that the QFileDialog hasn't any children after construction.调试 output 证明QFileDialog构造后没有任何子级。 I came to the conclusion that the children of the QFileDialog are created at a later time – but surely have to be already created after show() .我得出的结论是, QFileDialog的子项是稍后创建的——但肯定必须在show()之后创建。

To embed this hack into a derived class, it might be sufficient to do the manipulation in an override of QFileDialog::showEvent() .要将这个 hack 嵌入到派生的 class 中,在QFileDialog::showEvent()的覆盖中进行操作可能就足够了。 (I didn't test it.) (我没有测试它。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM