2011-08-01 71 views
3

我有一個窗體界面,包含大量的水平下拉框和GTKscrolledWindow內的文本框。窗體必須水平對齊,因爲窗體中存在無限數量的窗體(請考慮窗體的tabel)。自動滾動gtkscrolledwindow

是否(可能/如何)當GTKScrolledWindow自動滾動到右側時,操作員鍵入屏幕右側的下一個窗體控件。

相關問題將如何檢測焦點元素(按鈕等)是否在它的父滾動窗口中可見。

謝謝。

+0

現在這個'滾動使焦點窗口部件可見'自動發生,對吧?在'gtkmm'中,對於我來說,似乎對於我來說,基本的ScrolledWindows包含各種小部件,並使用鍵盤來集中它們。我想這在過去沒有發生過。然而,手動查詢widget是否可見 - 雖然在這種情況下不需要 - 看起來非常痛苦,甚至可能不可行 - 因爲它似乎依賴於很多平臺/ WM-/gfxAPI -...等具體的東西。 –

回答

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 
1

首先,第一個。 你如何檢測焦點?你連接到GtkWidget :: focus信號。 並在該回調中,您可以滾動窗口,無論您喜歡什麼,如何做到這一點,您需要獲得GtkAdjustmentGtkScrolledWindow並隨意移動它以顯示您想要的內容。

3

我希望你不介意我在描述中使用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()獲得窗口curently集中Widget或當焦點發生變化,你可以檢測到它。

在自動滾屏問題,你可以處理連接到可聚焦在窗口小部件或連接到包含窗口小部件的容器中的"set-focus-child"事件"focus"信號。在信號處理程序中,您應該檢查,如果焦點小部件可見。如果沒有,請確定其位置並正確滾動。

爲此,您必須檢測小部件在整個滾動區域內的位置。如果您正在使用某個不支持滾動的容器(例如GtkHBox)位於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); 

允許的最大調整值是adjust.upper - adjustment.page_size。聚焦的小部件作爲兩個信號的信號處理器參數傳遞,在"set-focus-child"信號的情況下,您也將容器作爲參數。