我有一个自定义容器,通过在Gtk::Viewport
中嵌入Gtk::Grid
来提供滚动功能。滚动部分工作完美,除了一个小故障。每当on_size_allocate事件发生时,它都会导致Gtk::Adjustment
的property_value
重置为0,从而导致滚动位置跳到顶部。因为这可能发生在任何子窗口发出队列大小调整,甚至当顶层窗口失去焦点时,滚动位置永远不会停留在应有的位置。通过重写容器的on_size_allocate
处理程序,我确认当我调用基类的on_size_allocate
时,Gtk::Adjustment
的property_value
会重置。下面是我的on_size_allocate
处理程序。
001 void CScrollGrid::on_size_allocate(Gtk::Allocation &oAlloc)
002 {
003 {
004 double dValue = m_refAdjustment->get_value();
005
006 std::cout << "size allocate (before), value: " << dValue << "n";
007
008 Gtk::Widget::on_size_allocate(oAlloc);
009
010 std::cout
011 << "size allocate (after), value: "
012 << m_refAdjustment->get_value()
013 << "n";
014
015 // Update scroll
016 {
017 int nMinimum;
018 int nDummy;
019
020 if (Gtk::ORIENTATION_VERTICAL
021 == m_eOrientation)
022 {
023 m_oGrid.get_preferred_height(nMinimum,
024 nDummy);
025 } else
026 {
027 m_oGrid.get_preferred_width(nMinimum,
028 nDummy);
029 }
030
031 m_refAdjustment->set_upper(nMinimum);
032 }
033
034 m_refAdjustment->property_value().set_value(dValue);
035
036 std::cout
037 << "size allocate (before fit), value: "
038 << m_refAdjustment->get_value()
039 << "n";
040
041 Fit();
042 }
043 }
流输出如下:
size allocate (before), value: 146
size allocate (after), value: 0
size allocate (before fit), value: 0
在第006行,流输出打印正确的'value'。到第010行,"value"被重置为0。正如您所看到的,我已经尝试在第034行应用备份的值,但令人惊讶的是,第036行的流输出仍然返回0!查看gtk_viewport_size_allocate
(gtk代码),我看不到任何与重置Gtk::Adjustment
相关的明显内容。
- 什么可能导致
Gtk::Adjustment::property_value
保持在0,即使被设置为非零值后? Gtk::Viewport
重置Gtk::Adjustment
s的机制是什么?- 我怎样才能防止
Gtk::Adjustment::property_value
被重置,就像这里发生的事情一样?
注意:由于以下原因,我没有使用Gtk::ScrolledWindow。滚动区域内的"行"可以有不同的高度。无论如何,可见区域需要在不剪切的情况下完整显示第一行和最后一行。如果不可能,则省略最后一行,并将多余的空间转换为均匀分布在顶部和底部之间的填充。
我明白我的错误了。而不是调用父类on_size_allocate
,我应该只调用set_allocation
。也不需要更新Gtk::Adjustment
的上限,Gtk::ViewPort
内部已经完成了。下面的代码可以正常工作。
001 void CScrollGrid::on_size_allocate(Gtk::Allocation &oAlloc)
002 {
003 set_allocation(oAlloc);
004
005 Fit();
006 }