(2017.10.19 追加記事;
→・Ruby/GTK3を今時のGlade, XML, Builder, CSSで書く6 - テキスト入力


gtk2,gtk3 で文字を入力するテキストボックス(Gtk::Entry)を表示します。

→・テキストエントリ -  Ruby/GTK2 チュートリアル
→・Gtk::Entry クラスRuby/GTK API Reference
→・Numeric/Text Data EntryRuby/GTK2 Tutorial


1.テキストエントリ(Gtk::Entry)を作る
○Gtk::Entry を作る
Gtk::Entry.new

○テキストエントリに文字をセットする
Gtk::Entry#text=(text)
Gtk::Entry#set_text(text)
  text;文字列(エンコーディングは UTF-8)

○テキストエントリの内容(文字) を取得する
Gtk::Entry#text
 テキストエントリ内の文字列が取得できます


(license; public domain)
・gtk_entry_1.rb
require 'gtk3'
#require 'gtk2'              # gtk2ライブラリでも実行可能

window = Gtk::Window.new
window.set_size_request(400, 300)

entry_area = Gtk::Entry.new
entry_area.text = 'こんにちは!'

fixed = Gtk::Fixed.new
fixed.put(entry_area, 5, 220)
window.add(fixed)

window.show_all
window.signal_connect("destroy") { Gtk.main_quit }
Gtk.main

gtk_entry_1


※ gtk3 で日本語の文字を入力して Enterキーを押すと、以下のようなエラーメッセージが出ますが、今のところ問題ないようです。
Pango-CRITICAL **: pango_layout_get_cursor_pos: assertion 'index >= 0 && index <= layout->length' failed
from /Users/xxxx/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/gobject-introspection-3.1.3/lib/gobject-introspection/loader.rb:110:in `block in define_singleton_method'
from gtk_entry_1.rb:16:in `<main>'
→・What does "Pango-CRITICAL **: pango_layout_get_cursor_pos: assertion 'index >= 0 && index <= layout->length' failed" mean? - gtk-app-devel-list



2.テキストエントリの設定
○テキストエントリのサイズを設定する
 幅(width)、高さ(height)をピクセル単位で設定します
 -1;サイズ指定なし

○文字サイズ,フォント等を設定する
・Gtk::Widget#override_font(font_desc)  ;gtk3
       str;"[FAMILY-LIST] [STYLE-OPTIONS] [SIZE]"
         [FAMILY-LIST]:serif(明朝体)、sans(ゴシック体)など
         [STYLE-OPTIONS]:bold(太字)など
         [SIZE]:文字サイズ(ポイント数)
         各要素は省略可、それぞれは空白で区切る(文字列で指定)
 

○背景の色を設定する
Gtk::Widget#modify_base(state, color);gtk2  ※ modify_bg ではないことに注意!
  state(状態);Gtk::STATE_NORMAL(または :normal);通常状態(これ以外は無効?)
  color(色) ;・Gdk::Color.new(red, green, blue)
           red, green, blue はそれぞれ 0 - 65535 の値
         ・Gdk::Color.parse(spec)
            spec は'green'など代表的色名、
          または '#FF0000' のようにRGBそれぞれ 00 - FF の値

  state(状態);Gtk::StateFlags::NORMAL(または :normal);通常状態(これ以外は無効?)
  color(色) ;Gdk::RGBA::new(red, green, bule, alpha)
         red, green, blue, alpha はそれぞれ 0 - 1.0 の値


○文字の色を設定する
Gtk::Widget#modify_text(state, color);gtk2  ※ modify_fg ではないことに注意!
 state(状態);Gtk::STATE_NORMAL(または :normal) ;通常状態(これ以外は無効?)
 color(色) ;・Gdk::Color.new(red, green, blue)
          red, green, blue はそれぞれ 0 - 65535 の値
        ・Gdk::Color.parse(spec)
           spec は'green'など代表的色名、
         または '#FF0000' のようにRGBそれぞれ 00 - FF の値

 state(状態);Gtk::StateFlags::NORMAL(または :normal);通常状態(これ以外は無効?)
        red, green, blue, alpha はそれぞれ 0 - 1.0 の値

○編集可能にするかどうか
Gtk::Entry#editable=(editable)
  editable:true;編集可能(デフォルト)
       false;編集不可

○入力した文字を表示するかどうか(パスワード入力時などに文字を隠す)
Gtk::Entry#visibility=(visible)
  visible:true;文字を表示(デフォルト)
      false;文字を隠す

○入力可能な最大文字数を設定する
Gtk::Entry#set_max_length(length)
Gtk::Entry#max_length=(length)
  length:最大文字数;0 は制限無し


・gtk_entry_2_gtk2.rb
require 'gtk2'

window = Gtk::Window.new
window.set_size_request(400, 300)

font = Pango::FontDescription.new("Serif bold 14")
yellow = Gdk::Color.new(65535, 65535, 0)   # RGB; 0-65535
red    = Gdk::Color.parse('#FF0000')   # RGB; 00-FF (parseを使った作り方)

entry_area = Gtk::Entry.new
entry_area.set_size_request(250, -1)

entry_area.modify_font(font)
entry_area.modify_base(Gtk::STATE_NORMAL, yellow)
entry_area.modify_text(Gtk::STATE_NORMAL, red)
entry_area.set_max_length(10)

fixed = Gtk::Fixed.new
fixed.put(entry_area, 5, 220)
window.add(fixed)

window.show_all
window.signal_connect("destroy") { Gtk.main_quit }
Gtk.main

・gtk_entry_2_gtk3.rb
require 'gtk3'

window = Gtk::Window.new
window.set_size_request(400, 300)

font = Pango::FontDescription.new("Serif bold 14")
yellow  = Gdk::RGBA::new(1.0, 1.0,   0, 1.0)    # RGBA; 0-1.0
red     = Gdk::RGBA::new(1.0,   0,   0, 1.0)

entry_area = Gtk::Entry.new
entry_area.set_size_request(250, -1)

entry_area.override_font(font)
entry_area.override_background_color(:normal, yellow)
entry_area.override_color(:normal, red)
entry_area.set_max_length(10)

fixed = Gtk::Fixed.new
fixed.put(entry_area, 5, 220)
window.add(fixed)

window.show_all
window.signal_connect("destroy") { Gtk.main_quit }
Gtk.main

gtk_entry_2_gtk3

(「文字の例です。今日は」とキーボードから入力した例)


3.ユーザー入力の設定
○ユーザーの入力を捉える
GLib::Instantiatable#signal_connect(detailed_signal){|instance, *args| ... }
 ・detailed_signal:
  "changed" ;文字が変更される毎に(文字が入力、削除される毎に)
  "activate";(エントリーボックス内で)Enterキーが押された時  

 ・{|instance| 処理}
  instance;シグナルを発行したウィジット(ここではエントリーボックス)
  処理;処理を直接書くか、Proc を入れます


○フォーカスを設定する
Gtk::Widget#grab_focus
  ウィンドウが前面になった時、テキストボックスが文字入力状態にフォーカス
  (カーソルが来ている状態)
  ※ Fixed#put や Box#pack_start などで Entry を登録した後でないと有効になりません


・gtk_entry_3.rb
require 'gtk3'
#require 'gtk2'              # gtk2ライブラリでも実行可能

window = Gtk::Window.new
window.set_size_request(400, 300)

entry_area = Gtk::Entry.new
entry_area.signal_connect("changed") do |entry|
 puts "#{entry.text}"
end

fixed = Gtk::Fixed.new
fixed.put(entry_area, 5, 220)
window.add(fixed)

window.show_all
window.signal_connect("destroy") { Gtk.main_quit }
Gtk.main

gtk_entry_3_rb


gtk_entry_3_term
文字が入力されると一文字毎に(日本語は入力確定する毎に)、ターミナルに入力内容が出力される


・gtk_entry_4.rb
require 'gtk3'
#require 'gtk2'              # gtk2ライブラリでも実行可能

window = Gtk::Window.new
window.set_size_request(400, 300)

entry_area = Gtk::Entry.new
entry_area.signal_connect("activate") do |entry|
 puts "#{entry.text}"
end

text_area = Gtk::TextView.new
text_area.set_size_request(150, 200)
text_area.buffer.text = 'Hello World!'

fixed = Gtk::Fixed.new

fixed.put(entry_area, 5, 220)
entry_area.grab_focus  # フォーカスをエントリーボックスに;fixed.put 後でないと無効
fixed.put(text_area, 10, 10)

window.add(fixed)
window.show_all
window.signal_connect("destroy") { Gtk.main_quit }
Gtk.main

gtk_entry_4

ウィンドウが前面になった時、TextView と Entry の 2つのウィジェット(部品)の内、Entry にカーソルが来ている(フォーカスされている)



4.応用
Entry に文字を入力して、Enterキーかボタンを押すと、入力した文字が TextView に表示されていくプログラムです。

・gtk_entry_5.rb

require 'gtk3'
#require 'gtk2'              # gtk2ライブラリでも実行可能

window = Gtk::Window.new
window.set_size_request(400, 300)

def put_text(entry, textview)
  textview.buffer.text += "#{entry.text}\n"  # Entryの内容をTextVeiwのテキストに追加
  entry.text = ''     # Entryの文字を消す
  entry.grab_focus    # ボタンをクリックしてもフォーカスをEntryに戻す
end

text_area = Gtk::TextView.new
text_area.set_size_request(250, 200)

entry_area = Gtk::Entry.new
entry_area.set_size_request(250, -1)
entry_area.signal_connect("activate") do
  put_text(entry_area, text_area)
end

button = Gtk::Button.new
button.set_label('Button')
button.signal_connect("clicked") do
  put_text(entry_area, text_area)
end


fixed = Gtk::Fixed.new
fixed.put(text_area,  10,  10)
fixed.put(entry_area, 10, 220)
fixed.put(button,    280, 220)
entry_area.grab_focus     # フォーカスをEntryに

window.add(fixed)
window.show_all
window.signal_connect("destroy") { Gtk.main_quit }
Gtk.main

gtk_entry_5