从QFileDialog库中移动窗口中的窗口小部件

时间:2018-03-19 19:38:29

标签: c++ qt qfiledialog

是否可以在QFileDialog的窗口中移动小部件?打开或保存文件时的示例。我想在文件名的行编辑和文件类型的组合框之间创建一个空格,所以我需要将组合框向下移动一行。是否可以像这样进行修改?

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:1)

要执行此操作,需要修改组成QFileDialog的窗口小部件的布局。完整的例子如下。您希望将自己的内容(窗口小部件,布局等)添加到释放的空间中 - 从modDialog返回必要的详细信息。 SO::SpaceButtons选项将按钮从内部QDialogButtonBox中取出,并将它们放在插入的行周围。否则,空间仅在前两列内延伸,按钮框保持不变。

Screenshot of the modified file dialog

// filedialog-mod-49371087
#include <QtWidgets>
#include <initializer_list>

struct GridPos {
   int row = -1, col = -1, rowSpan = {}, colSpan = {};
   GridPos(QGridLayout * layout, QWidget * widget) {
      int index = layout->indexOf(widget);
      if (index >= 0)
         layout->getItemPosition(index, &row, &col, &rowSpan, &colSpan);
   }
   GridPos(int r, int c, int rs, int cs) : row(r), col(c), rowSpan(rs), colSpan(cs) {}
   bool operator==(const GridPos & o) const {
      return o.row == row && o.col == col && o.rowSpan == rowSpan && o.colSpan == colSpan;
   }
};

namespace SO {
enum ModDialogOption { SpaceButtons = 1 };
Q_DECLARE_FLAGS(ModDialogOptions, ModDialogOption)
}
Q_DECLARE_OPERATORS_FOR_FLAGS(SO::ModDialogOptions)

struct ModDialogResult {
   QGridLayout *layout;
   int row;
   int colSpan;
};

ModDialogResult modDialog(QFileDialog * dialog, SO::ModDialogOptions options = {}) {
   auto *layout = qobject_cast<QGridLayout*>(dialog->layout());
   auto *fileNameLabel = dialog->findChild<QLabel*>("fileNameLabel");
   auto *fileNameEdit = dialog->findChild<QLineEdit*>("fileNameEdit");
   auto *buttonBox = dialog->findChild<QDialogButtonBox*>("buttonBox");
   auto *fileTypeLabel = dialog->findChild<QLabel*>("fileTypeLabel");
   auto *fileTypeCombo = dialog->findChild<QComboBox*>("fileTypeCombo");
   auto const buttons = buttonBox->findChildren<QPushButton*>();
   // ensure that the dialog has expected layout
   Q_ASSERT((GridPos{layout, fileNameLabel} == GridPos{2, 0, 1, 1}));
   Q_ASSERT((GridPos{layout, fileNameEdit} == GridPos{2, 1, 1, 1}));
   Q_ASSERT((GridPos{layout, buttonBox} == GridPos{2, 2, 2, 1}));
   Q_ASSERT((GridPos{layout, fileTypeLabel} == GridPos{3, 0, 1, 1}));
   Q_ASSERT((GridPos{layout, fileTypeCombo} == GridPos{3, 1, 1, 1}));
   Q_ASSERT(buttons.size() == 2);

   // remove widgets and layouts
   for (auto *w : std::initializer_list<QWidget*>{buttonBox, fileTypeLabel, fileTypeCombo})
      layout->removeWidget(w);

   // add widgets in new locations
   if (options & SO::SpaceButtons) {
      for (auto *b : buttons) b->setParent(dialog);
      buttonBox->hide();
      layout->addWidget(buttons.at(0), 2, 2, 1, 1);
      layout->addWidget(buttons.at(1), 4, 2, 1, 1);
   } else {
      layout->addWidget(buttonBox, 2, 2, 3, 1);
   }
   layout->addWidget(fileTypeLabel, 4, 0, 1, 1);
   layout->addWidget(fileTypeCombo, 4, 1, 1, 1);

   return {layout, 3, 3};
}

int main(int argc, char **argv) {
   QApplication app{argc, argv};
   QFileDialog dialog;
   dialog.setOption(QFileDialog::DontUseNativeDialog);
   auto mod = modDialog(&dialog, SO::SpaceButtons);
   mod.layout->addItem(new QSpacerItem(0, 50), mod.row, 0);
   dialog.show();
   return app.exec();
}