用GTK +/gtkmm Grid分割屏幕

问题描述:

我尝试用gtkmm创建一个窗口,其中有两个文本视图。文本视图应排列为垂直分屏。 就像是: Split screen用GTK +/gtkmm Grid分割屏幕

后来我想能够在Emacs一次又一次分割屏幕的垂直和水平并调整分离区域,等等。

我认为一个简单的分屏应该很容易,但我已经卡在那里了。 我曾考虑过使用Gtk :: Grid作为布局容器,每次用户想要分割屏幕时,我想添加一行或一列,并在新创建的区域添加一个新的文本视图。

这里是我的代码:

main.cc

#include <gtkmm/application.h> 

#include "examplewindow.h" 

int main(int argc, char *argv[]) 
{ 
    auto app = Gtk::Application::create(argc, argv, "org.gtkmm.example"); 

    ExampleWindow window; 

    //Shows the window and returns when it is closed. 
    return app->run(window); 
} 

examplewindow.h

#ifndef GTKMM_EXAMPLEWINDOW_H 
#define GTKMM_EXAMPLEWINDOW_H 

#include <gtkmm.h> 

class ExampleWindow : public Gtk::Window 
{ 
public: 
    ExampleWindow(); 
    virtual ~ExampleWindow(); 

protected: 
    Gtk::Grid main_grid; 
    Gtk::ScrolledWindow scrolled_window1; 
    Gtk::ScrolledWindow scrolled_window2; 
    Gtk::TextView text_view1; 
    Gtk::TextView text_view2; 

    Glib::RefPtr<Gtk::TextBuffer> text_buffer1, text_buffer2; 

    void fill_buffers(); 
}; 

#endif //GTKMM_EXAMPLEWINDOW_H 

examplewindow.cc

#include "examplewindow.h" 

ExampleWindow::ExampleWindow() { 
    set_title("Gtk splitted textviews"); 
    set_border_width(12); 

    add(main_grid); 

    scrolled_window1.add(text_view1); 
    scrolled_window1.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); 
    scrolled_window2.add(text_view2); 
    scrolled_window1.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); 

    main_grid.insert_column(0); 
    main_grid.attach(scrolled_window1, 0, 0, 1, 1); 
    //scrolled_window1.set_hexpand(true); 
    //scrolled_window1.set_vexpand(true); 

    main_grid.attach(scrolled_window2, 1, 0, 1, 1); 
    //scrolled_window1.set_hexpand(true); 
    //scrolled_window1.set_vexpand(true); 

    fill_buffers(); 
    text_view1.set_buffer(text_buffer1); 
    text_view2.set_buffer(text_buffer2); 

    show_all_children(); 
} 

ExampleWindow::~ExampleWindow() {} 

void ExampleWindow::fill_buffers() { 
    text_buffer1 = Gtk::TextBuffer::create(); 
    text_buffer1->set_text("This is the text from TextBuffer #1."); 

    text_buffer2 = Gtk::TextBuffer::create(); 
    text_buffer2->set_text(
      "This is some alternative text, from TextBuffer #2."); 

} 

构建具有:

g++ examplewindow.cc main.cc -o splittv `pkg-config gtkmm-3.0 --cflags --libs` 

这将产生的结果: Too small text views

文本的意见显然是小。如果我在两个文本视图上设置了hexpand和vexpand为true,text_view1会抑制text_view2。

+1

对于分割屏幕,我将开始寻找到['GtkPaned'](https://developer.gnome.org/gtk3 /stable/GtkPaned.html) – Gerhardh

+0

您的代码中存在拼写错误。为scrolled_window1设置十六进制和vexpand两次。也许你想要改变为scrolled_window2。 – JohnKoch

由于@Gerhardh在评论建议你可以使用GtkPaned

#include <gtkmm.h> 
#include <memory> 
#include <string> 

struct Body 
{ 
    inline static int i=0; 
    Gtk::Box Box; 
    Gtk::Button SplitHButton, SplitVButton, CloseButton; 
    Gtk::Label Label; 
    Body() 
    { 
     SplitHButton.set_label("h"); 
     SplitVButton.set_label("v"); 
     Label.set_text(std::to_string(i++)); 
     CloseButton.set_label("c"); 
     Box.add(SplitHButton); 
     Box.add(SplitVButton); 
     Box.add(Label); 
     Box.add(CloseButton); 
     Box.show_all(); 
    } 
}; 

struct Pane 
{ 
    Gtk::Paned PaneWidget; 
    std::shared_ptr<Pane> ChildPane1, ChildPane2; 
    Body Body1, Body2; 
    Pane(Gtk::Orientation orientation=Gtk::ORIENTATION_HORIZONTAL): 
     PaneWidget(orientation) 
    { 
     PaneWidget.add1(Body1.Box); 
     PaneWidget.add2(Body2.Box); 

     Body1.SplitHButton.signal_clicked().connect([this]{Split(ChildPane1, Gtk::ORIENTATION_HORIZONTAL, Body1, true);}); 
     Body1.SplitVButton.signal_clicked().connect([this]{Split(ChildPane1, Gtk::ORIENTATION_VERTICAL, Body1, true);}); 
     Body2.SplitHButton.signal_clicked().connect([this]{Split(ChildPane2, Gtk::ORIENTATION_HORIZONTAL, Body2, false);}); 
     Body2.SplitVButton.signal_clicked().connect([this]{Split(ChildPane2, Gtk::ORIENTATION_VERTICAL, Body2, false);}); 

     PaneWidget.show_all(); 
    } 

    void Split(std::shared_ptr<Pane>& pane, Gtk::Orientation orientation, Body& body, bool leftTop) 
    { 
     pane = std::make_shared<Pane>(orientation); 
     PaneWidget.remove(body.Box); 
     if(leftTop) 
      PaneWidget.add1(pane->PaneWidget); 
     else 
      PaneWidget.add2(pane->PaneWidget); 

     auto lambda = [&]{ 
       PaneWidget.remove(pane->PaneWidget); 
       if(leftTop) 
        PaneWidget.add1(body.Box); 
       else 
        PaneWidget.add2(body.Box); 
       PaneWidget.show_all(); 
       pane.reset(); 
     }; 

     pane->Body1.CloseButton.signal_clicked().connect(lambda); 
     pane->Body2.CloseButton.signal_clicked().connect(lambda); 
    } 
}; 

int main() 
{ 
    auto GtkApp = Gtk::Application::create(); 
    Gtk::Window w; 
    Pane p; 
    w.add(p.PaneWidget); 
    w.resize(800,600); 
    w.show_all(); 
    GtkApp->run(w); 
    return 0; 
} 

enter image description here