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

Posted

技术标签:

【中文标题】使用 Gtk::Viewport (gtkmm3) 直接滚动【英文标题】:Direct scrolling using Gtk::Viewport (gtkmm3) 【发布时间】:2021-01-20 04:40:09 【问题描述】:

我有一个自定义容器,它通过在 Gtk::Viewport 中嵌入 Gtk::Grid 来提供滚动功能。滚动部分工作完美,除了一个小故障。每当发生 on_size_allocate 事件时,它都会导致Gtk::Adjustmentproperty_value 重置为0,从而导致滚动位置跳到顶部。由于这可能发生在任何孩子发出队列调整大小时,或者甚至当***窗口失去焦点时,滚动位置永远不会停留在应有的位置。通过覆盖容器的on_size_allocate 处理程序,我确认当我调用基类的on_size_allocateGtk::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 行,流输出打印出正确的“值”。到第 010 行,“值”被重置为 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。滚动区域内的“行”可能具有不同的高度。无论如何,可见区域都需要完整显示第一行和最后一行而不进行裁剪。如果无法做到这一点,则省略最后一行,并将多余的空间转换为在顶部和底部之间均匀分布的填充。

【问题讨论】:

【参考方案1】:

找出我的错误。我不应该调用父类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 

【讨论】:

以上是关于使用 Gtk::Viewport (gtkmm3) 直接滚动的主要内容,如果未能解决你的问题,请参考以下文章

在 gtkmm3 中使用 Gtk::Assistant

Gtkmm3 TreeView ListStore.Clear 或 TreeSelection.unselectAll 导致错误

GTKmm3 (GTK+ 3 C++) 编译但运行时抛出 GLib-GIO-CRITICAL 错误

gtkmm 3 窗口 64 位

gtkmm 3.10.1 中带有 CSS 的 Gtk::Box 样式问题

进度条 gtkmm Glade