使用 Gtk::Viewport 直接滚动 (gtkmm3)
Direct scrolling using Gtk::Viewport (gtkmm3)
我有一个自定义容器,它通过在 Gtk::Viewport
中嵌入 Gtk::Grid
来提供滚动功能。除了一个小故障外,滚动部分工作正常。每当发生 on_size_allocate 事件时,它会导致 Gtk::Adjustment
的 property_value
重置为 0,导致滚动位置跳到顶部。由于这可能发生在任何子级发出队列大小调整时,甚至当顶层 window 失去焦点时,滚动位置永远不会停留在应有的位置。通过覆盖容器的 on_size_allocate
处理程序,我确认 Gtk::Adjustment
的 property_value
在我调用基础 class 的 on_size_allocate
时重置。下面是我的 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 行的流输出仍然 returns 0!查看 gtk_viewport_size_allocate
(gtk 代码)我看不到任何与 Gtk::Adjustment
.
重置相关的明显信息
- 什么会导致
Gtk::Adjustment::property_value
即使在设置为非零值后仍停留在 0?
Gtk::Viewport
重置为 Gtk::Adjustment
的机制是什么?
- 如何防止
Gtk::Adjustment::property_value
像这里发生的那样被重置?
注意:由于以下原因,我没有使用 Gtk::ScrolledWindow。滚动区域内的 'rows' 可以有不同的高度。不管怎样,可见区域都需要完整显示第一行和最后一行而不进行剪裁。如果不可能,则省略最后一行,并将额外的 space 转换为在顶部和底部之间均匀分布的填充。
找出我的错误。我应该调用 set_allocation
而不是调用父 类 on_size_allocate
。也不需要更新 Gtk::Adjustment
的上限,Gtk::ViewPort
在内部进行。以下代码工作正常。
001 void CScrollGrid::on_size_allocate(Gtk::Allocation &oAlloc)
002 {
003 set_allocation(oAlloc);
004
005 Fit();
006 }
我有一个自定义容器,它通过在 Gtk::Viewport
中嵌入 Gtk::Grid
来提供滚动功能。除了一个小故障外,滚动部分工作正常。每当发生 on_size_allocate 事件时,它会导致 Gtk::Adjustment
的 property_value
重置为 0,导致滚动位置跳到顶部。由于这可能发生在任何子级发出队列大小调整时,甚至当顶层 window 失去焦点时,滚动位置永远不会停留在应有的位置。通过覆盖容器的 on_size_allocate
处理程序,我确认 Gtk::Adjustment
的 property_value
在我调用基础 class 的 on_size_allocate
时重置。下面是我的 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 行的流输出仍然 returns 0!查看 gtk_viewport_size_allocate
(gtk 代码)我看不到任何与 Gtk::Adjustment
.
- 什么会导致
Gtk::Adjustment::property_value
即使在设置为非零值后仍停留在 0? Gtk::Viewport
重置为Gtk::Adjustment
的机制是什么?- 如何防止
Gtk::Adjustment::property_value
像这里发生的那样被重置?
注意:由于以下原因,我没有使用 Gtk::ScrolledWindow。滚动区域内的 'rows' 可以有不同的高度。不管怎样,可见区域都需要完整显示第一行和最后一行而不进行剪裁。如果不可能,则省略最后一行,并将额外的 space 转换为在顶部和底部之间均匀分布的填充。
找出我的错误。我应该调用 set_allocation
而不是调用父 类 on_size_allocate
。也不需要更新 Gtk::Adjustment
的上限,Gtk::ViewPort
在内部进行。以下代码工作正常。
001 void CScrollGrid::on_size_allocate(Gtk::Allocation &oAlloc)
002 {
003 set_allocation(oAlloc);
004
005 Fit();
006 }