2011-08-01 6 views
3

GTKscrolledWindow 안에있는 다수의 수평 드롭 다운 및 텍스트 상자가있는 양식 인터페이스가 있습니다. 양식을 무제한으로 만들 수 있기 때문에 양식을 가로로 정렬해야합니다 (양식의 표를 생각하십시오).자동 스크롤 및 gtkscrolledwindow

운영자가 화면의 오른쪽에있는 다음 양식 컨트롤로 이동할 때 GTKScrolledWindow를 오른쪽으로 자동 스크롤 할 수 있습니까?

관련 질문에 포커스가있는 요소 (단추 등)가 부모 스크롤 창에 표시되는지 어떻게 알 수 있습니까?

감사합니다.

+0

요즘에는 '포커스 위젯을 보이게하는 스크롤'이 자동으로 수행됩니다. 그것은 확실히 저를 위해 gtkmm에서 여러가지 위젯을 가지고있는 기본적인 ScrolledWindows를 사용하고 키보드를 사용하여 그것들 사이에 집중하는 것 같습니다. 나는 이것이 과거에는 일어나지 않았다고 생각한다. 그러나 수동으로 위젯이 표시되는지 여부를 묻는 것은 - 비록이 경우에는 필요하지 않지만 - 플랫폼/WM-/gfxAPI -... 등의 많은 플랫폼에 의존하는 것으로 보이기 때문에 엄청나게 고통 스럽습니다. 특정 물건. –

답변

1

다음은 Michy의 대답을 기반으로 한 것입니다.

스크롤 창을 자동 스크롤하려면, 생성자 인 FocusScroll (스크롤 창)을 실행하십시오.

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 
1

먼저 첫 번째. 포커스를 어떻게 감지합니까? GtkWidget :: focus 신호에 연결합니다. 그리고 그 콜백에서 원하는대로 원하는대로 창을 스크롤 할 수 있습니다. GtkAdjustmentGtkScrolledWindow을 가져와 원하는대로 보여줄 수 있도록 이동해야합니다.

3

설명에서 GTK + C API를 사용하고 있어도 괜찮을 것입니다. sollution은 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()에 의해 창에서 curently 초점을 맞춘 위젯을 얻을 수 있습니다 또는 초점이 변경 될 때 당신은 그것을 감지 할 수 있습니다.

는 자동 스크롤 문제에서는 포커싱 할 수있는 위젯 또는 위젯을 포함하는 용기에 접속 된 경우에 접속 "set-focus-child""focus" 신호를 처리 할 수있다. 시그널 핸들러에서 포커스가있는 위젯이 보이는지 확인해야합니다. 그렇지 않으면 위치를 결정하고 제대로 스크롤하십시오.

이렇게하려면 전체 스크롤 영역 내에서 위젯의 위치를 ​​감지해야합니다. 스크롤을 지원하지 않는 일부 컨테이너 (예 : GtkHBox)가 GtkScrolledWindow (뷰포트에 따라 조정 됨)을 사용하는 경우 gtk_widget_translate_coordinates()으로 컨테이너를 기준으로 초점 위젯의 좌표를 다시 가져올 수 있습니다. 이제는 스크롤 된 창 대신 컨테이너를 사용합니다. 조정 값이 GtkViewport 인 경우 조정 값은 스크롤 영역의 픽셀 위치에 해당하므로 조정 값을 x 상대 좌표로 설정하면 스크롤됩니다. adjustment.page_size - 그래서 핸들러의 중요한 부분은 허용되는 최대 조정 값이 adjustment.upper입니다

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); 

수 있습니다. 위젯은 두 신호 모두에 대한 신호 처리기 인수로 전달됩니다. "set-focus-child" 신호의 경우 컨테이너를 인수로 가져옵니다.