Glade を使って、gtk3 でテキストを表示します。(Gtk::TextViewGtk::ScrolledWindow

参考)

0.TextView(テキスト表示ウィジェット)を作る
Gladeでも作れますが、Gtk::TextView を Rubyのプログラムから作る方法も載せておきます。
 
  buffer;テキストの内容は Gtk::TextBufferクラスを使います
     nilの場合、自動的に Gtk::TextBuffer が作られます

 戻り値: Gtk::TextBuffer
 TextViewの持つテキストの内容(TextBuffer)を取得します

※TextBuffer は他のウィジェット(部品)でも呼び出したり共有できます

 text;テキスト文字列(エンコーディングは UTF-8)
 TextBuffer にテキスト文字列を設定します 

※以上をまとめると、テキスト表示部品を作ってテキスト文字列を設定するのは;
 text_area = Gtk::TextView.new
 text_area.buffer.text = 'Hello World!'
のようにできます
(もちろん以下のように、Gladeで TextBuffer を作って操作することも出来ます)


1.TextView の配置
Glade を起動し、GtkWindowを作り、GtkFixedコンテナを置き、その上に GtkTextView をドラッグします。
(Glade の左列>「Control and Display」>「Text View」にあります)

さらに、GtkTextBuffer を追加します。
(Glade の左列>「Miscellaneous」>「Text Buffer」をクリックするだけで追加されます)


それぞれの設定は;
○GtkWindow
 ・ID: window_1 
 ・デフォルトの幅: 400
 ・デフォルトの高さ: 300
 ・Signal: destroy, Handler: gtk_main_quit

○GtkFixed
 デフォルトのまま

○GtkTextView
 ・ID: textview1
 ・バッファー: textbuffer1
 ・Packing;X位置: 10,Y位置: 10
 ・要求する幅: 150
 ・要求する高さ: 200

○GtkTextBuffer
 ・ID: textbuffer1
 ・ラベル: Hello World!
  右の鉛筆アイコンをクリックして「Edit Text」ポップアップウィンドウで設定しても可。
  その際は、「Text」に文字列入力します(ここでは Hello World!)。さらに「Translatable」のチェックを外しました。


glade_text_1_glade


(license; public domain)
・glade_text_1.ui
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkTextBuffer" id="textbuffer1">
    <property name="text">Hello World!</property>
  </object>
  <object class="GtkWindow" id="window_1">
    <property name="can_focus">False</property>
    <property name="default_width">400</property>
    <property name="default_height">300</property>
    <signal name="destroy" handler="gtk_main_quit" swapped="no"/>
    <child>
      <object class="GtkFixed">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkTextView" id="textview1">
            <property name="width_request">150</property>
            <property name="height_request">200</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="buffer">textbuffer1</property>
          </object>
          <packing>
            <property name="x">10</property>
            <property name="y">10</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

・glade_text_1.rb
require 'gtk3'

builder = Gtk::Builder.new
builder.add_from_file("glade_text_1.ui")

win = builder.get_object("window_1")

def gtk_main_quit
  Gtk.main_quit
end

builder.connect_signals {|handler| method(handler)}
win.show_all
Gtk.main

glade_text_1




2.TextView の見た目を変える
Ruby のプログラム側で、CSS で設定します(Gtk::CssProvider)
 
○Gtk::CssProvider.new
 CSSオブジェクトを作成します

○Gtk::CssProvider#load(data: string)
 data: CSSの文字列 の形で読み込みます
 ・string;CSSの設定
 
○Gtk::CssProvider#load_from_path(filename)
 CSSファイルを読み込みます
 ・filename;CSSファイル

○Gtk::Window#style_context.add_provider(css_provider, Gtk::StyleProvider::PRIORITY_USER)
 ウィンドウにCSSの設定を加えます
 ・css_provider;Gtk::CssProviderクラス

○CSSの設定
a)textview の指定
下記のような CSS形式で指定します。
text {
  background-color: yellow;
  color: red;
}

text と書くと Gtk::TextView 全体の設定になります。
また、色の指定の仕方もいろいろあります。


さらに、CSSで ID指定やクラス指定もできます。
その場合は XMLファイルも書き換えます。
Glade を起動して、
・スタイルID で指定する場合
「Common」>「Widget Attributes」>「ウィジェット名」
 自分で決めた ID を記入します
(「General」の「ID」ではないことに注意!)

・クラスで指定する場合
「Common」>「Widget Attributes」>「Style Classes」
の<Type Here> をクリックして、自分で決めたクラス名を記入します
(enterキーを押さないと確定しません)

その後、CSSファイルを設定します。
・スタイルID で指定する場合(textview_widget とします)
 #を付けて指定します
#textview_widget {
  color: cyan;
}

・スタイルクラスで指定する場合(textview_style とします)
 .を付けて指定します
.textview_style {
  color: #00FFFF;
}



b)設定項目
・背景色
 background-color:

・文字の色
 color:

・文字のサイズ
 font: 40 px;

・文字フォントの設定
 font-family: Serif;
 (フォントファミリーの設定;Serif,sans-serif など)

※ macOS では、以下のような警告が出ます;
Gtk-WARNING **: Theme parsing error: <data>:7:10: Not using units is deprecated. Assuming 'px'.
 24 px のように指定しているのですが、警告は消えません。また、他の単位 em,%,pt などだとエラーになります。


以上の設定をまとめた例です; 
text {
  background-color: yellow;
  color: red;
}
#textview_widget {
  font: 40 px;
  font-family: Serif;
  font-weight: bold;
}
 

3.TextViewの動作を設定する
Glade側の設定 
 
○テキストを編集不可にする;「編集可能」 
○カーソルを消す;「カーソルの表示」
○上書きする;「上書きモードかどうか」
Glade を起動し、GtkTextView の「General」>「Text View Attributes」の該当項目のチェックを入れたり外したりします。

○ワードラップの設定をする
GtkTextView の「General」>「Text Formatting」>「ラップモード」から選択します。


glade_text_2_glade_1
 

○フォーカスを設定する
(ウィンドウが前面になった時、TextView にフォーカス(カーソルが来ている状態) が来る)
GtkTextView の「Common」>「Widget Flags」>「フォーカスあり」にチェックを入れます。

○デフォルトを設定する
(他のウィジェットをクリックした後も、TextView にフォーカス(カーソルが来ている状態) が来る)
GtkTextView の「Common」>「Widget Flags」>「デフォルト可否」と「デフォルトあり」にチェックを入れます。

glade_text_2_glade_2


・glade_text_2.ui
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkWindow" id="window_1">
    <property name="can_focus">False</property>
    <property name="default_width">400</property>
    <property name="default_height">300</property>
    <signal name="destroy" handler="gtk_main_quit" swapped="no"/>
    <child>
      <object class="GtkFixed">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkTextView" id="textview1">
            <property name="name">textview_widget</property>
            <property name="width_request">150</property>
            <property name="height_request">200</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="editable">False</property>
            <property name="wrap_mode">char</property>
            <property name="cursor_visible">False</property>
          </object>
          <packing>
            <property name="x">10</property>
            <property name="y">10</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

・glade_text_2.rb
require 'gtk3'

builder = Gtk::Builder.new
builder.add_from_file("glade_text_2.ui")

win = builder.get_object("window_1")
text_area = builder.get_object("textview1")
text_area.buffer.text = 'こんにちは、今日は暑いね。'

css_provider = Gtk::CssProvider.new
css_provider.load(data:
"
text {
  background-color: yellow;
  color: red;
}
#textview_widget {
  font: 40 px;
  font-family: Serif;
  font-weight: bold;
}
")
text_area.style_context.add_provider(css_provider, Gtk::StyleProvider::PRIORITY_USER)

def gtk_main_quit
  Gtk.main_quit
end

builder.connect_signals {|handler| method(handler)}
win.show_all
Gtk.main 
(この例では、Glade で GtkTextBuffer を作らず、Ruby側で Gtk::TextView#buffer.text = で文字を設定しました)

glade_text_2

(テキスト編集不可,カーソルを消す,ワードラップ文字単位)


5.テキストの文字(TextBuffer)を部分的に変更する
→・複数行テキスト表示ウィジェットの概要 - Gtk/TextView、Gtk/TextBuffer、およびその関連クラスについて - Ruby/GTK2, Ruby-GNOME2 - プログラミング工房
→・Text Tags - The Text View WidgetRuby/GTK2 Tutorial

5-1.タグを作る
Gtk::TextBuffer#create_tag(tag_name, properties)
 tag_name;タグの名前を自分で付ける、または nil(無名)に設定
 properties;Gtk::TextTag の :property => 値

Gtk::TextTag の property
・フォント
 :family => 'Serif'('Sans','sans-serif' など)
 :font => 'Sans Italic 18' 

・文字サイズ
 'size_points' => 18(ポイント単位で)

・太字
 :weight => Pango::Weight::BOLD

・斜体(イタリック)
 :style => :italic

・文字の色
 :foreground => 'red'('blue' など)
 'foreground_gdk' => Gdk::Color.new(65535, 0, 0) など

・文字の背景色
 :background => 'yellow'('green' など)
 'background_gdk' => Gdk::Color.parse('#FFFF00') など


5-2.テキスト(TextBuffer)の文字の位置を設定する
Gtk::TextBuffer#get_iter_at( :offset => char_offset )
  char_offset;先頭からの文字数(先頭は0)
 テキストの先頭から何文字目という位置を設定します

Gtk::TextBuffer#get_mark(name)
  Gtk::TextMark の位置を設定します
 (あらかじめ、Gtk::TextBuffer#create_mark でマークを作っておきます)


5-3.タグを使う
Gtk::TextBuffer#apply_tag(tag, start, end)
 tag;タグ名
 start;開始位置
 end;終了位置


以上を組み合わせて使います

・glade_text_3.ui
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkWindow" id="window_1">
    <property name="can_focus">False</property>
    <property name="default_width">400</property>
    <property name="default_height">300</property>
    <signal name="destroy" handler="gtk_main_quit" swapped="no"/>
    <child>
      <object class="GtkFixed">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkTextView" id="textview1">
            <property name="width_request">150</property>
            <property name="height_request">200</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
          </object>
          <packing>
            <property name="x">10</property>
            <property name="y">10</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

・glade_text_3.rb
require 'gtk3'

builder = Gtk::Builder.new
builder.add_from_file("glade_text_3.ui")

win = builder.get_object("window_1")
text_area = builder.get_object("textview1")
text_area.buffer.text = 'こんにちは、今日は暑いね。'

tag = text_area.buffer.create_tag(nil, :foreground => 'red', 'size_points' => 16)
start_char = text_area.buffer.get_iter_at(:offset => 6)
end_char   = text_area.buffer.get_iter_at(:offset => 9)   # 日本語だと文字位置がずれる
text_area.buffer.apply_tag(tag, start_char, end_char)

def gtk_main_quit
  Gtk.main_quit
end

builder.connect_signals {|handler| method(handler)}
win.show_all
Gtk.main


glade_text_3_glade

glade_text_3
(日本語だと文字位置がずれる)


6.スクロールバーをつける
6-1.GtkScrolledWindow の配置
Glade を起動し、GtkWindowを作り、GtkFixedコンテナを置き、先に GtkScrolledWindow をその上にドラッグします。(Glade の左列>「Containers」>「Scrolled Window」にあります)
その後、 GtkTextView を GtkScrolledWindow の上にドラッグします。


6-1.GtkScrolledWindow の設定
GtkScrolledWindow の「General」>「Scrolled Window Attributes」から選択します。
横方向のスクロールバーは「Horizontal」、縦方向のスクロールバーは「Vertical」から選択します。
「Scrollbar Policy」を「Always」(常時表示)、「Automatic」(自動表示)、「Never」(表示しない)、「External」(?) の中から選択します。

glade_text4_glade


7.テキストの最後までスクロールする
○Gtk::TextView#scroll_to_iter(Gtk::TextView.buffer#end_iter, 0.0, true, 0.0, 0.0)

Gtk::TextView#scroll_to_iter(iter, within_margin, use_align, xalign, yalign)
  iter;Gtk::TextIter の位置までスクロール  最後の位置の Gtk::TextIte


※ これだと、スクロールの位置がずれる場合があります
 その場合は、以下のように最終行をマークしてそこまでスクロールさせます

○ end_mark = Gtk::TextView#buffer.create_mark(nil, Gtk::TextView.buffer.end_iter, true)
 Gtk::TextView#scroll_to_mark(end_mark, 0.0, false, 0.0, 0.0)

・Gtk::TextBuffer#create_mark(mark_name, iter, left_gravity)
 マーク(Gtk::TextMark)を作る
Gtk::TextBuffer#end_iter
  最後の位置の Gtk::TextIter
Gtk::TextView#scroll_to_mark(mark, within_margin, use_align, xalign, yalign)


・glade_text_4.ui
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkWindow" id="window_1">
    <property name="can_focus">False</property>
    <property name="default_width">400</property>
    <property name="default_height">300</property>
    <signal name="destroy" handler="gtk_main_quit" swapped="no"/>
    <child>
      <object class="GtkFixed">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkScrolledWindow">
            <property name="width_request">150</property>
            <property name="height_request">100</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="hscrollbar_policy">never</property>
            <property name="vscrollbar_policy">always</property>
            <property name="shadow_type">in</property>
            <child>
              <object class="GtkTextView" id="textview1">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="wrap_mode">char</property>
              </object>
            </child>
          </object>
          <packing>
            <property name="x">10</property>
            <property name="y">10</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

・glade_text_4.rb
require 'gtk3'

builder = Gtk::Builder.new
builder.add_from_file("glade_text_4.ui")

win = builder.get_object("window_1")
text_area = builder.get_object("textview1")
text_area.buffer.text =
'Ruby/GTK2,Ruby/GTK3 はクロスプラットフォームの GUIツールキットである GTK+ を Rubyから使うライブラリです。
GTK+ バージョン2.x に対応するのが、Ruby/GTK2 で gem名は gtk2、
GTK+ バージョン3.x に対応するのが、Ruby/GTK3 で gem名は gtk3です。'

# テキストの最後にスクロールする
# text_area.scroll_to_iter(text_area.buffer.end_iter, 0.0, true, 0.0, 0.0) # これだとうまくいかない
end_mark = text_area.buffer.create_mark(nil, text_area.buffer.end_iter, true)
text_area.scroll_to_mark(end_mark, 0.0, false, 0.0, 0.0)

def gtk_main_quit
  Gtk.main_quit
end

builder.connect_signals {|handler| method(handler)}
win.show_all
Gtk.main





glade_text_4