Qt Изменение размера QMainWindow с помощью Splitter
У меня есть QMainWindow с:
- Два виджета в горизонтальном сплиттере. "m_liner" находится на правой стороне
- Оба виджета имеют минимальный размер, скажем, 300 пикселей.
- Флажок, чтобы скрыть / показать правый виджет m_liner.
Я хочу, чтобы общий QMainWindow расширялся при отображении виджета, а уменьшался при скрытии. Код ниже делает это за исключением:
- Если отображаются оба виджета, минимальный размер окна составляет 600 пикселей.
- Сожмите окно до этого наименьшего размера.
- Снимите флажок, чтобы скрыть виджет справа.
- Программа скрывает виджет справа.
- Программа вызывает this->resize(300, height);
- Окно заканчивается шириной 600 пикселей (минимальный размер с видимыми обоими виджетами) вместо 300 (минимальный размер только с левым виджетом).
- Позже я могу изменить размер окна до 300 пикселей с помощью мыши или другой кнопки. Но это не изменит размер до 300 в событии флажка, даже если я вызову изменение размера несколько раз.
У кого-нибудь есть идеи как это решить?
Далее следует критический фрагмент кода, у меня есть полный проект, если он вам нужен:
void MainWindow::on_checkBox_stateChanged(int val)
{
std::cout << "-------------------- Checkbox clicked " << val << std::endl;
bool visible = val;
QWidget * m_liner = ui->textEdit_2;
QSplitter * m_splitter = ui->splitter;
int linerWidth = m_liner->width();
if (linerWidth <= 0) linerWidth = m_lastLinerWidth;
if (linerWidth <= 0) linerWidth = m_liner->sizeHint().width();
// Account for the splitter handle
linerWidth += m_splitter->handleWidth() - 4;
std::cout << "Frame width starts at " << this->width() << std::endl;
std::cout << "Right Panel width is " << m_liner->width() << std::endl;
// this->setUpdatesEnabled(false);
if (visible && !m_liner->isVisible())
{
// Expand the window to include the Right Panel
int w = this->width() + linerWidth;
m_liner->setVisible(true);
QList<int> sizes = m_splitter->sizes();
if (sizes[1] == 0)
{
sizes[1] = linerWidth;
m_splitter->setSizes(sizes);
}
this->resize(w, this->height());
}
else if (!visible && m_liner->isVisible())
{
// Shrink the window to exclude the Right Panel
int w = this->width() - linerWidth;
std::cout << "Shrinking to " << w << std::endl;
m_lastLinerWidth = m_liner->width();
m_liner->setVisible(false);
m_splitter->setStretchFactor(1, 0);
this->resize(w, this->height());
m_splitter->resize(w, this->height());
this->update();
this->resize(w, this->height());
}
else
{
// Toggle the visibility of the liner
m_liner->setVisible(visible);
}
this->setUpdatesEnabled(true);
std::cout << "Frame width of " << this->width() << std::endl;
}
1 ответ
Мне кажется, что есть некоторые внутренние события Qt, которые нужно распространить, прежде чем он узнает, что вы можете изменить размер главного окна. Если это так, то я могу придумать два возможных решения:
Используйте один таймер в очереди для вызова кода, который изменяет размер вашего окна до 300 пикселей:
m_liner->hide();
QTimer::singleShot( 0, this, SLOT(resizeTo300px()) );
или, после того, как вы скрыли свой виджет, вы можете попробовать вызвать processEvents() (эта функция имеет потенциально опасные побочные эффекты, поэтому используйте ее с осторожностью):
m_liner->hide();
QApplication::processEvents();
resize( w, height() );
Другим потенциальным решением было бы установить политику горизонтального размера вашего виджета, чтобы игнорировать его при скрытии:
m_liner->hide();
m_liner->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Preferred );
resize( w, height() );
При повторном отображении виджета вам нужно будет снова изменить политику размеров.