使用Gtk::Viewport (gtkmm3)直接滚动



我有一个自定义容器,通过在Gtk::Viewport中嵌入Gtk::Grid来提供滚动功能。滚动部分工作完美,除了一个小故障。每当on_size_allocate事件发生时,它都会导致Gtk::Adjustmentproperty_value重置为0,从而导致滚动位置跳到顶部。因为这可能发生在任何子窗口发出队列大小调整,甚至当顶层窗口失去焦点时,滚动位置永远不会停留在应有的位置。通过重写容器的on_size_allocate处理程序,我确认当我调用基类的on_size_allocate时,Gtk::Adjustmentproperty_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::Adjustments的机制是什么?
  • 我怎样才能防止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 }

相关内容

  • 没有找到相关文章

最新更新