我尝试使用gtkmm构建一个窗口,其中我有两个文本视图。文本视图应排列为垂直分屏。
像那样:
稍后我希望能够一次又一次地分割屏幕垂直和水平,并调整分割区域的大小,就像在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`
文本视图显然很小。如果我在两个文本视图上都将hexpand和vexpand设置为true,则text_view1会压缩text_view2。
答案 0 :(得分:0)
在评论中建议使用@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;
}