自动滚动gtkscrolledwindow

问题描述 投票:3回答:3

我有一个带有大量水平下拉菜单和GTKscrolledWindow内的文本框的表单界面。表单必须水平对齐,因为窗口中有无限数量的表单(请考虑表单的表格)。

是(可能/如何),当操作员切换到位于屏幕右侧的下一个窗体控件时,它会自动向右滚动GTKScrolledWindow。

相关问题将是如何检测聚焦元素(按钮等)在其父滚动窗口中是否可见。

谢谢。

gtk pygtk gtkscrolledwindow
3个回答
1
投票

根据Michy的回答,这就是我所做的。

要使滚动窗口自动滚动,请在构造函数中运行:FocusScroll(scrolledwindow)。

class FocusScroll(object):
"""
Get a gtk.ScrolledWindow which contains a gtk.Viewport.
Attach event handlers which will scroll it to show the focused widget.
"""
def __init__(self, scrolledwindow):
    self.scrolledwindow = scrolledwindow
    self.viewport = scrolledwindow.get_child()
    assert isinstance(self.viewport, gtk.Viewport)
    self.main_widget = self.viewport.get_child()
    self.vadj = scrolledwindow.get_vadjustment()
    self.window = self.get_window(scrolledwindow)

    self.viewport.connect('set-focus-child', self.on_viewport_set_focus_child)

def get_window(self, widget):
    if isinstance(widget, gtk.Window):
        return widget
    else:
        return self.get_window(widget.get_parent())

def is_child(self, widget, container):
    """
    Go recursively over all children of container, to check if widget is
    a child of it.
    """
    for child in container.get_children():
        if child is widget:
            return True
        elif isinstance(child, gtk.Container):
            if self.is_child(widget, child):
                return True
    else:
        return False

def on_viewport_set_focus_child(self, _viewport, _child):
    idle_add(self.scroll_slide_viewport)

def scroll_slide_viewport(self):
    """Scroll the viewport if needed to see the current focused widget"""
    widget = self.window.get_focus()
    if not self.is_child(widget, self.main_widget):
        return

    _wleft, wtop = widget.translate_coordinates(self.main_widget, 0, 0)
    wbottom = wtop + widget.get_allocation().height

    top = self.vadj.value
    bottom = top + self.vadj.page_size

    if wtop < top:
        self.vadj.value = wtop
    elif wbottom > bottom:
        self.vadj.value = wbottom - self.vadj.page_size

4
投票

[希望您不要介意我在描述中使用GTK + C API,解决方案可以轻松转换为PyGTK,并且原理保持不变。

[从第二个问题开始-如果您知道要测试的窗口小部件,则可以通过调用gtk_widget_translate_coordinates(child, parent, 0, 0, &x, &y)来获取子级相对于父级的位置来检测其可见性。通过gtk_widget_get_allocation(),您可以获得父级和子级的大小,并且只需测试整个子矩形是否在滚动窗口中即可。

gboolean is_visible_in (GtkWidget *child, GtkWidget *scrolled)
{
    gint x, y;
    GtkAllocation child_alloc, scroll_alloc;
    gtk_widget_translate_coordinates (child, scrolled, 0, 0, &x, &y);
    gtk_widget_get_allocation(child, &child_alloc);
    gtk_widget_get_allocation(scrolled, &scroll_alloc);

    return (x >= 0 && y >= 0) 
        && x + child_alloc.width <= scroll_alloc.width
        && y + child_alloc.height <= scroll_alloc.height;
}

您可以通过gtk_window_get_focus ()在窗口中获得当前焦点对准的小部件,也可以在焦点更改时检测到它。

在自动滚动问题中,您可以处理连接到可聚焦的窗口小部件的"focus"信号,或连接到包含窗口小部件的容器的"set-focus-child"事件。在信号处理程序中,您应该检查聚焦的小部件是否可见。如果不是,请确定其位置并正确滚动。

为此,您必须检测小部件在整个滚动区域内的位置。如果您使用的容器不支持滚动(例如GtkHBox)iside GtkScrolledWindow(视口调整),则可以通过gtk_widget_translate_coordinates()再次获取焦点控件相对于容器的坐标-现在使用容器而不是滚动窗口。调整值,如果使用GtkViewport,则调整值对应于滚动区域中以像素为单位的位置,因此将调整值设置为x相对坐标将进行滚动。因此处理程序的重要部分可能是

    GtkWidget *scrolled = /* The scrolled window */
    GtkWidget *container = /* The container in the scrolled window */
    GtkWidget *focused = /* The focused widget */

    GtkAdjustment *hadj = gtk_scrolled_window_get_hadjustment( 
        GTK_SCROLLED_WINDOW(scrolled));
    gint x, y;
    gtk_widget_translate_coordinates (focused, container, 0, 0, &x, &y);
    gtk_adjustment_set_value(hadj, min(x, maximal adjustment value allowed);

允许的最大调整值是adjustment.upper-Adjustment.page_size。聚焦的窗口小部件作为两个信号的信号处理程序参数传递,在"set-focus-child"信号的情况下,您还将容器作为参数。


2
投票

[第一,第一。您如何检测焦点?您连接到GtkWidget :: focus信号。在该回调中,您可以将窗口滚动到所需的任何位置,如何执行此操作,您需要获取GtkScrolledWindowGtkAdjustment,并根据需要移动它以显示所需的内容。

© www.soinside.com 2019 - 2024. All rights reserved.