QT版本:2014年5月15日 系统:MSY2/UCRT64(最新)
我的 QMainWindow 左侧有一个 QDockWidget。
当用户与其交互时,该小部件会自动调整大小。
一开始效果很好,但如果用户关闭程序并重新启动它,突然扩展坞可以增长到它需要的新大小,但永远不会正确缩小。
当我们从 QSettings 恢复时,我已经找到了问题所在:
restoreState(qsettings.value("windowState", saveState()).toByteArray());
正如文档所说,这也会恢复 QDockWidgets 的状态。不幸的是,由于某种原因,它破坏了这个特定小部件的大小调整。
如何在restoreState()之前保存该特定停靠小部件的状态,然后撤消restoreState()所做的任何操作?
我尝试过以下方法:
Qt::WindowStates dockState = ui->dockWidget_left->windowState();
restoreState(qsettings.value("windowState", saveState()).toByteArray());
ui->dockWidget_left->setWindowState(dockState);
但遗憾的是这似乎没有任何区别。
我还尝试查看restoreState()调用之前和之后的各种值,例如minimumWidth()、maximumWidth()、sizeHint()、baseSize()、width()和sizePolicy() - 但似乎没有受到影响通过电话。
为了更完整的上下文,整个结构如下所示:
一个 QVBoxLayout,其中包含一个 QWidget,其中包含一个 QTreeWidget,其中有一个 QHeaderView。
通过调整 QTreeWidget() 的最小宽度来增大和缩小。 QWidget 的大小类型为 Preferred,而 QDockWidget 使用 maximum 来尝试将其缩小到所需的最小值。
因为
ResizeMode::ResizeToContents()
在标题视图的第一列上无法正常工作,我创建了一个函数来手动计算其所需的大小并应用它。每次展开或折叠树上的元素时都会调用它。
即:
(树的构造函数内部)
{
QHeaderView* h = m_tree->header();
h->setSectionResizeMode(0, QHeaderView::ResizeMode::ResizeToContents);
h->setSectionResizeMode(1, QHeaderView::ResizeMode::ResizeToContents);
h->setSectionResizeMode(2, QHeaderView::ResizeMode::ResizeToContents);
connect(m_tree, &QTreeWidget::itemExpanded, this, onTreeExpansionsChanged);
connect(m_tree, &QTreeWidget::itemCollapsed, this, onTreeExpansionsChanged);
}
(以及调整大小的函数)
void MyTree::onTreeExpansionsChanged(QTreeWidgetItem* item)
{
double dpiX = static_cast<double>(QPaintDevice::logicalDpiX());
double scale = dpiX / 240.0;
// Size offsets to account for the fact that
// QHeaderView::ResizeMode::ResizeToContents() does not function
// properly on the first column - though it works fine on the others
// These sizes represent the minimum size in pixels needed to prevent
// that node from having its text cut-off when it's fully expanded.
int emptyMinSize = (132 + 50) * scale;
int node0Size = (166 + 75) * scale;
int node1Size = (203 + 125) * scale;
int node2Size = (399 + 125) * scale;
int node3Size = (172 + 125) * scale;
int node4Size = (515 + 150) * scale;
int node5Size = (381 + 175) * scale;
int node6Size = (167 + 125) * scale;
int node7Size = (166 + 75) * scale;
int node8Size = (166 + 450) * scale;
QHeaderView* h = m_tree->header();
h->resizeSections(QHeaderView::ResizeMode::ResizeToContents);
int sectionSize0 = h->sectionSize(0);
int sectionSize1 = h->sectionSize(1);
int sectionSize2 = h->sectionSize(2);
h->setSectionResizeMode(0, QHeaderView::ResizeMode::Fixed);
int newSizeCol0 = sectionSize0;
newSizeCol0 = std::max(emptyMinSize, newSizeCol0);
if (node0->isExpanded())
{
newSizeCol0 = std::max(node0Size , newSize0);
}
if (node1->isExpanded())
{
newSizeCol0 = std::max(node1Size, newSizeCol0);
}
if (node2->isExpanded())
{
newSizeCol0 = std::max(node2Size, newSizeCol0);
}
if (node3->isExpanded())
{
newSizeCol0 = std::max(node3Size, newSizeCol0);
}
if (node4->isExpanded())
{
newSizeCol0 = std::max(node4Size, newSizeCol0);
}
if (node5->isExpanded())
{
newSizeCol0 = std::max(node5Size, newSizeCol0);
}
if (node6->isExpanded())
{
newSizeCol0 = std::max(node6Size, newSizeCol0);
}
if (node7->isExpanded())
{
newSizeCol0 = std::max(node7Size, newSizeCol0);
}
if (node8->isExpanded())
{
newSizeCol0 = std::max(node8Size, newSizeCol0);
}
int newTotalSize = newSize0 + sectionSize1 + sectionSize2;
m_tree->setMinimumWidth(newTotalSize * 1.05);
// All of the following do not help, commented out for now
//m_tree->setMaximumWidth(newTotalSize * 1.10);
//h->resizeSection(0, newSize0);
//h->setMinimumWidth(newTotalSize * 1.05);
//h->setMaximumWidth(newTotalSize * 1.10);
//h->adjustSize();
// m_mw->ui->dockWidget_contents->setMinimumWidth(newTotalSize * 1.1);
// m_mw->ui->dockWidget_contents->setMaximumWidth(newTotalSize * 1.5);
// m_mw->ui->dockWidget_contents->adjustSize();
}
关于如何撤消恢复状态()对特定停靠小部件所做的任何事情,有什么想法吗?
调整停靠小部件本身(而不是其内容)的最大宽度最终起作用 - 没有其他因素解决它。我已将乘数更改为 DPI 缩放偏移,这看起来更好一些。
这是必要的,这有点烦人 - 因为 ResizeToContents 拒绝在树的第一列上正常工作,并且似乎没有办法有选择地撤消特定停靠小部件上的 restoreState() 的工作。但这不是一个大问题。