QGridLayout проблема со вставкой виджетов - PullRequest
2 голосов
/ 17 августа 2011

(с использованием Qt 4.6.3, x64, linux)

Я тестирую, как правильно вставлять виджеты в существующий QGridLayout, заполненный различными виджетами. Разобранный надуманный случай таков:

QApplication app(argc,argv);
QWidget      w;
QGridLayout* gl     = new QGridLayout(&w);
QLabel*      label  = new QLabel("Image Size:");
QLineEdit*   wedit  = new QLineEdit("100");
QLabel*      xlabel = new QLabel("x");

wedit->setAlignment(Qt::AlignRight);
gl->addWidget(label);
gl->addWidget(xlabel, 0, 1, 1, 1);
gl->addWidget(wedit,  0, gl->columnCount());

, который создает следующий виджет:

Valid XHTML.

Предполагая, что у него есть существующий QGridLayout, как указано выше, но без метки "x", и я хотел бы вставить это в макет, переключение двух последних строк addWidget может показаться действительным, т.е.

\\ same as above
gl->addWidget(label);
gl->addWidget(wedit,  0, gl->columnCount());
gl->addWidget(xlabel, 0, 1, 1, 1);

Это, однако, создает следующее:

Valid XHTML

gl->columnCount() после этого по-прежнему равно 2, так как метка x и QLineEdit заполняют одну и ту же ячейку. Основываясь на этих знаниях, следующий код дает желаемый исходный результат:

gl->addWidget(label);
gl->addWidget(wedit,  0, 2); // note: specified column 2, columnCount() is now 3
gl->addWidget(xlabel, 0, 1, 1, 1);

Хотя это не особенно полезно, так как рассматриваемый оригинальный макет не создан с учетом более поздних макетов.

Поскольку addWidget позволяет указывать положение ячейки, а также диапазон строк / столбцов, кажется странным, что Qt не будет автоматически заменять существующие виджеты в макете. У кого-нибудь есть предложение относительно того, как я мог бы преодолеть это? Я предполагаю, что было бы возможно воссоздать QGridLayout и скопировать в него дочерние элементы оригинала, стараясь вставить дополнительный виджет в нужное место. Это, однако, некрасиво и подвержено проблемам с версией Qt (поскольку я хочу изменить встроенный виджет).

Редактировать

Я понимаю, что я делаю предположение о мышлении QHBoxLayout, когда вставка виджета понимается однозначно, тогда как в QGridLayout это не так (?).

Я могу уточнить, что в конечном итоге я хотел бы изменить QFileDialog::getSaveFileName, вставив виджет (аналогично показанному выше виджету) прямо над двумя нижними строками (т. Е. Над «Файл и имя:»).

Спасибо

Ответы [ 2 ]

1 голос
/ 17 августа 2011

Переключение двух последних строк addWidget недопустимо. Для следующего кода:

gl->addWidget(label);
gl->addWidget(wedit,  0, gl->columnCount());
gl->addWidget(xlabel, 0, 1, 1, 1);

Аргументы для вызовов addWidget() оцениваются до добавления виджета. Следовательно, gl->columnCount() оценивает один вместо двух для второго вызова, так как столбец все еще должен быть создан. Вы эффективно добавляете два виджета в первый столбец.

0 голосов
/ 18 августа 2011

Возможным решением является повторное добавление виджетов, которые должны быть перемещены.Т.е.

QLayoutItem* x01 = gl->itemAtPosition(0,1);
gl->addWidget(x01->widget(), 0, 2);
gl->addWidget(xlabel, 0, 1, 1, 1);

Так вот, это не очень красиво и не просто в обслуживании, поскольку новая версия Qt может изменить исходный виджет, а слепая ручная выборка и перемещение детей не так уж умны.Следующий реальный пример (тот, который я действительно хотел решить) состоял в том, чтобы изменить диалоговое окно Qt «Сохранить как», которое отображается с использованием QFileDialog :: getSaveFileName.

class ImageFileDialog : public QFileDialog {
public:
  ImageFileDialog(QWidget* parent);
  ~ImageFileDialog();
  QString getFileName() const;
  QSize getImageSize() const;
  QDialog::DialogCode exec(); // Overriden

protected:
  void showEvent(QShowEvent* event); // Overriden

private:
  QString    fileName_;
  QSize      imageSize_;
  QLineEdit* widthLineEdit_;
  QLineEdit* heightLineEdit_;
};

И в источнике (показывая толькоконструктор, обработка фокуса и exec):

ImageFileDialog::ImageFileDialog(QWidget* parent)
  : fileName_(""),
    imageSize_(0,0),
    widthLineEdit_(0),
    heightLineEdit_(0)
{
  setAcceptMode(QFileDialog::AcceptSave);
  setFileMode(QFileDialog::AnyFile);
  setConfirmOverwrite(true);

  QGridLayout* mainLayout = dynamic_cast<QGridLayout*>(layout());
  assert(mainLayout->columnCount() == 3);
  assert(mainLayout->rowCount()    == 4);

  QWidget*     container      = new QWidget();
  QGridLayout* glayout        = new QGridLayout();
  QLabel*      imageSizeLabel = new QLabel("Image Size:");
  widthLineEdit_              = new QLineEdit("400");
  heightLineEdit_             = new QLineEdit("300");
  widthLineEdit_->setAlignment(Qt::AlignRight);
  heightLineEdit_->setAlignment(Qt::AlignRight);

  container->setLayout(glayout);
  glayout->setAlignment(Qt::AlignLeft);
  glayout->addWidget(widthLineEdit_);
  glayout->addWidget(new QLabel("x"), 0, 1);
  glayout->addWidget(heightLineEdit_, 0, 2);
  glayout->addWidget(new QLabel("[pixels]"), 0, 3);
  glayout->addItem(new QSpacerItem(250, 0), 0, 4);
  glayout->setContentsMargins(0,0,0,0); // Removes unwanted spacing

  // Shifting relevant child widgets one row down.
  int rowCount = mainLayout->rowCount();
  QLayoutItem* x00 = mainLayout->itemAtPosition(mainLayout->rowCount()-2,0);
  QLayoutItem* x10 = mainLayout->itemAtPosition(mainLayout->rowCount()-1,0);
  QLayoutItem* x01 = mainLayout->itemAtPosition(mainLayout->rowCount()-2,1);
  QLayoutItem* x11 = mainLayout->itemAtPosition(mainLayout->rowCount()-1,1);
  QLayoutItem* x02 = mainLayout->itemAtPosition(mainLayout->rowCount()-1,2);
  assert(x00);   assert(x01);   assert(x10);   assert(x11);   assert(x02);

  mainLayout->addWidget(x00->widget(), rowCount-1, 0, 1, 1);
  mainLayout->addWidget(x10->widget(), rowCount,   0, 1, 1);
  mainLayout->addWidget(x01->widget(), rowCount-1, 1, 1, 1);
  mainLayout->addWidget(x11->widget(), rowCount,   1, 1, 1);
  mainLayout->addWidget(x02->widget(), rowCount-1, 2, 2, 1);

  // Adding the widgets in the now empty row.
  rowCount        = mainLayout->rowCount();
  mainLayout->addWidget(imageSizeLabel, rowCount-3, 0, 1, 1 );
  mainLayout->addWidget(container,      rowCount-3, 1, 1, 1);

  // Setting the proper tab-order
  QLayoutItem* tmp  = mainLayout->itemAtPosition(mainLayout->rowCount()-2,1);
  QLayoutItem* tmp2 = mainLayout->itemAtPosition(mainLayout->rowCount()-1,1);
  assert(tmp); assert(tmp2);
  QWidget::setTabOrder(heightLineEdit_      , tmp->widget());
  QWidget::setTabOrder(tmp->widget(), tmp2->widget());
}

// Makes sure the right widget is in focus
void ImageFileDialog::showEvent(QShowEvent* event)
{
  widthLineEdit_->setFocus(Qt::OtherFocusReason);
}

// Called to create the widget
QDialog::DialogCode ImageFileDialog::exec()
{
  if (QFileDialog::exec() == QDialog::Rejected)
    return QDialog::Rejected;
  // The code that processes the widget form and stores results for later calls to
  // getImageSize()
  return QDialog:Accepted;
}

Который, используя, например,

ImageFileDialog* dialog = new ImageFileDialog(&w);
dialog->exec();

Создает следующий виджет:

Valid XHTML


Комментарии и способы сделать это лучше, или почему это просто неправильно, приветствуются :))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...