gtkmm: ScrolledWindow und Viewport vs. Layout



  • Hallo,

    ich möchte eine längere Reihe von Checkboxen mit Scrollbalken versehen.

    Das ScrolledWindow braucht einen Viewport, und der braucht Adjustments.
    Das Tutorial der gtkmm-Seite schlägt vor, mit get_vadjustment() das Adjustment
    vom inneren Widget zu bekommen, aber kaum ein Widget hat diese Methode.

    Die Klassendokumentation von Layout schien da vielversprechend. Der Code unten
    funktioniert soweit, nur dass im Scrollbalken kein beweglicher Teil ist. Er
    wird also angezeigt, ist aber nicht aktiv.

    Wie kann man das hinbekommen?

    Vielen Dank für Hinweise!

    for ( int i = 0; i < numCheckboxes; i++ )
    {
        Gtk::CheckButton* pButton = manage(  new Gtk::CheckButton()  );
        vector_checkboxes[i] = pButton;
        pButton->show();
    
        Gtk::Label* pLabel = new Gtk::Label(labeltext);
        pLabel->show();
    
        Gtk::VBox* pVBox = manage( new Gtk::VBox() );
        pVBox->pack_start(*pButton, false, false, 0);
        pVBox->pack_start(*pLabel, false, false, 0);
        pVBox->show();
    
        m_HBox_checkboxes.pack_start(*pVBox, false, false, 8);
    }
    m_HBox_checkboxes.show();
    
    m_Layout.put(m_HBox_checkboxes, 0,0);
    m_Layout.show();
    
    m_ScrolledWindow_checkboxes.add(m_Layout);
    m_ScrolledWindow_checkboxes.show();
    
    m_VBox.pack_start(m_ScrolledWindow_checkboxes, false, false, 0);
    


  • Das sieht dann so aus:

    // ... for-Schleife
    
    m_HBox_checkboxes.show();
    
    m_Layout.put(m_HBox_checkboxes, 0,0);
    Gtk::Requisition req;
    m_HBox_checkboxes.size_request(req);
    m_Layout.set_size(req.width,req.height);
    m_Layout.show();
    
    m_ScrolledWindow_checkboxes.add(m_Layout);
    m_ScrolledWindow_checkboxes.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC);
    m_ScrolledWindow_checkboxes.show();
    
    pack_start(m_ScrolledWindow_checkboxes, true, true, 0);
    


  • Hi,

    evtl. habe ich dein Problem noch nicht verstanden, aber warum nicht einfach so:

    #include <gtkmm.h>
    
    class Foo : public Gtk::Window {
      Gtk::HBox hbox;  //Root-Container
      Gtk::VBox vbox;  //Container für die CheckButtons
      Gtk::ScrolledWindow scrolledWindow;
    
      Gtk::CheckButton a,b,c,d,e;
    
    public:
      Foo() : a("One"), b("Two"), c("Three"), d("Four"), e("Five") {
        set_title("Foo");
        set_default_size(200, 100);
    
        vbox.add(a);
        vbox.add(b);
        vbox.add(c);
        vbox.add(d);
        vbox.add(e);
    
        scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
        scrolledWindow.add(vbox);
    
        hbox.add(scrolledWindow);     
        add(hbox);
    
        show_all_children();
      }
    };
    
    int main(int argc, char **argv) {
      Gtk::Main m(argc, argv);
    
      Foo f;
      m.run(f);
      return 0;
    }
    

    Cheers

    GPC



  • Hallo,

    tatsächlich, es geht auch ohne Layout, Danke für den Hinweis.

    Bekommt man den Schatten noch weg? Das ganze Fenster ist sonst voller Linien...

    #include <gtkmm.h>
    
    class Foo : public Gtk::Window {
      Gtk::VBox vbox;  //Root-Container
      Gtk::HBox hbox;  //Container für die CheckButtons
      Gtk::ScrolledWindow scrolledWindow;
      Gtk::Label label;
    
      Gtk::CheckButton a,b,c,d,e;
    
    public:
      Foo() : a("One"), b("Two"), c("Three"), d("Four"), e("Five"), label("Label") {
        set_title("Foo");
        set_default_size(200, 100);
    
        hbox.add(a);
        hbox.add(b);
        hbox.add(c);
        hbox.add(d);
        hbox.add(e);
    
        scrolledWindow.set_shadow_type(Gtk::SHADOW_NONE);
        scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
        scrolledWindow.add(hbox);
    
        vbox.add(label);
        vbox.add(scrolledWindow);    
        add(vbox);
    
        show_all_children();
      }
    };
    
    int main(int argc, char **argv) {
      Gtk::Main m(argc, argv);
    
      Foo f;
      m.run(f);
      return 0;
    }
    

    Noch eine Frage dazu: Wenn der horizontale Scrollbalken (dynamisch) notwendig wird, nimmt er vertikal Platz weg und damit ist dann auch ein vertikaler Scrollbalken nötig.

    Lieber wäre es mir, wenn das Fenster dann vertikal ein bisschen größer wird.
    Geht das auch? Mit der policy scheint im Zweifel einfach ein Teil nicht angezeigt zu werden?

    scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_NEVER);
    


  • namtel schrieb:

    Bekommt man den Schatten noch weg? Das ganze Fenster ist sonst voller Linien...

    Ich hab' keine Schatten... muss irgendwas mit deinen Einstellungen des Windowmanagers zu tun haben. Oder sonst mach mal 'n Screenshot.

    Noch eine Frage dazu: Wenn der horizontale Scrollbalken (dynamisch) notwendig wird, nimmt er vertikal Platz weg und damit ist dann auch ein vertikaler Scrollbalken nötig.

    Nicht immer, aber gut.

    Lieber wäre es mir, wenn das Fenster dann vertikal ein bisschen größer wird. Geht das auch?

    Ich wüsste nicht wie. Jedenfalls nicht automatisch. Du kannst das natürlich coden, indem du auf das resize-Event reagierst und es dann vergrößerst, aber das wäre mir die Geschichte nicht wert.



  • GPC schrieb:

    namtel schrieb:

    Bekommt man den Schatten noch weg? Das ganze Fenster ist sonst voller Linien...

    Ich hab' keine Schatten... muss irgendwas mit deinen Einstellungen des Windowmanagers zu tun haben. Oder sonst mach mal 'n Screenshot.

    Ich glaub er meint den grauen Rand:
    http://watteimdocht.de/jan-nik/Bildschirmfoto-Foo.png



  • Danke für die Antworten, ich bin jetzt erst wieder dabei.

    Danke auch für den Screenshot, der trifft es. In dem Fenster wie es am Ende aussehen soll sind schon einige horizontale lange Linien und ich versuche, die durch leeren Raum zu ersetzen und so das Ganze übersichtlicher und angenehmer fürs Auge zu gestalten.

    Ist aber nicht wirklich wichtig. Beide Fragen sind insgesamt auch eher Gestaltungs-Fragen als technische Fragen.



  • namtel schrieb:

    Danke für die Antworten, ich bin jetzt erst wieder dabei.

    Danke auch für den Screenshot, der trifft es. In dem Fenster wie es am Ende aussehen soll sind schon einige horizontale lange Linien und ich versuche, die durch leeren Raum zu ersetzen und so das Ganze übersichtlicher und angenehmer fürs Auge zu gestalten.

    Ist aber nicht wirklich wichtig. Beide Fragen sind insgesamt auch eher Gestaltungs-Fragen als technische Fragen.

    Mich würde die Lösung allerdings sehr interessieren 🙂



  • namtel schrieb:

    Danke für die Antworten, ich bin jetzt erst wieder dabei.

    Danke auch für den Screenshot, der trifft es. In dem Fenster wie es am Ende aussehen soll sind schon einige horizontale lange Linien und ich versuche, die durch leeren Raum zu ersetzen und so das Ganze übersichtlicher und angenehmer fürs Auge zu gestalten.

    Ist aber nicht wirklich wichtig. Beide Fragen sind insgesamt auch eher Gestaltungs-Fragen als technische Fragen.

    Ähm, mach mal' einen Screenshot... so dass ich's mir vorstellen kann 🙂



  • GPC schrieb:

    namtel schrieb:

    Danke für die Antworten, ich bin jetzt erst wieder dabei.

    Danke auch für den Screenshot, der trifft es. In dem Fenster wie es am Ende aussehen soll sind schon einige horizontale lange Linien und ich versuche, die durch leeren Raum zu ersetzen und so das Ganze übersichtlicher und angenehmer fürs Auge zu gestalten.

    Ist aber nicht wirklich wichtig. Beide Fragen sind insgesamt auch eher Gestaltungs-Fragen als technische Fragen.

    Ähm, mach mal' einen Screenshot... so dass ich's mir vorstellen kann 🙂

    Hm.. ist doch eigentlich ganz einfach: In meinem Screenshot, der graue Rand vom Scrolledwindow, der soll weg. Wahrscheinlich weil das ScrolledWindow in etwas drinn ist, was schon einen Rand hat, z.B. GtkNotebook.



  • Ach, jetzt. Also wollt ihr praktisch ein scrolledWindow.hide_border(); haben? Hm, kann morgen mal danach schauen... bin grad unter Win unterwegs und da ist kein gtkmm drauf.



  • Hm, also ich hab' nichts gefunden. Nur Gtk::Notebook bietet die Methode set_show_border(boolean) an, die festlegt, ob um die einzelnen Pages Rahmen ergzeugt werden, die 3D-style wirken.

    Aber speziell das Gtk::ScrolledWindow hat keinerleich solche Methoden. Also entweder musst du deine GUI etwas umstellen oder dich damit abfinden.



  • 😕 Nur, dass wenn ich das Ganze in Glade zusammenstöpsele, dann ist da kein Rahmen um das ScrolledWindow zu sehen. Wie machen die das?

    (Für die Codegenerierung nutze ich Glade nicht, weil es glade-- auch nach der Installation (Win XP) nicht findet und von der Commandozeile ging es auch nicht und ich wollte eh erst mal mit gtkmm warm werden. Aber vielleicht gibt es einen einfachen Trick, den man unter Windows beachten muss für Glade?)



  • Ich hab eine Möglichkeit gefunden, die allerdings nicht sauber ist:

    #include <gtkmm.h>
    #include <cassert>
    
    class Foo : public Gtk::Window {
      Gtk::VBox vbox;  //Root-Container
      Gtk::HBox hbox;  //Container für die CheckButtons
      Gtk::ScrolledWindow scrolledWindow;
      Gtk::Label label;
      Gtk::Adjustment adjustment;
      Gtk::Viewport viewport;
    
      Gtk::CheckButton a,b,c,d,e;
    
    public:
      Foo() : a("One"), b("Two"), c("Three"), d("Four"), e("Five"), label("Label"), adjustment(0,0,0), viewport(adjustment, adjustment) {
        set_title("Foo");
        set_default_size(200, 100);
    
        hbox.add(a);
        hbox.add(b);
        hbox.add(c);
        hbox.add(d);
        hbox.add(e);
    
        scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
        scrolledWindow.add(viewport);
        scrolledWindow.set_shadow_type(Gtk::SHADOW_NONE);
        viewport.set_shadow_type(Gtk::SHADOW_NONE);
        viewport.add(hbox);
        assert(scrolledWindow.get_shadow_type() == Gtk::SHADOW_NONE);
    
        vbox.add(label);
        vbox.add(scrolledWindow);    
        add(vbox);
    
        show_all_children();
      }
    };
    
    int main(int argc, char **argv) {
      Gtk::Main m(argc, argv);
    
      Foo f;
      m.run(f);
      return 0;
    }
    

    So funktioniert es.
    Ich könnte mir vorstellen, dass es sich um einen Bug im Gtk::ScrolledWindow handelt.


Anmelden zum Antworten