1

我尝试使用 gtkmm 构建一个窗口,其中有两个文本视图。文本视图应排列为垂直分屏。像那样: 分屏

后来我希望能够一次又一次地垂直和水平分割屏幕并调整分割区域的大小,就像在 emacs 中一样。

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

这是我的代码:

主文件

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

例子window.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

例子window.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`

这会产生这样的结果: 文本视图太小

文本视图显然很小。如果我在两个文本视图上将 hexpand 和 vexpand 设置为 true,则 text_view1 会抑制 text_view2。

4

1 回答 1

1

正如@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;
}

在此处输入图像描述

于 2017-09-29T14:53:28.363 回答