文字列の数(長さ)を取得する – FlyWithLua

2023年3月30日

文字の長さをボクセル(ピクセル)で取得する方法。文字数でなく実際のピクセルで測定した長さになるので大文字や小文字、Oとi等では長さが違うということも判別することができるので、正確な長さを測る場合はこれを使う。

長さをボクセル(ピクセル)で取得

これは文字を長さ(ピクセル)で取得するので文字数とは違う値がでてくる。
measure_string(“string”) フォントを指定しない、drow_string()のような場合
measure_string(“string”,”fontname”) フォントを指定する場合

このように使う:
measure_string(“ABCDEFG, “Helvetica_12”)

ボクセルとは、三次元グラフィックスなどで、立体物の表現に用いられる立方体の単位。二次元画像におけるピクセル(画素)に相当する。

このテストでは7行、8行でのテキストの長さをピクセル値で取得する方法になる。2つは同じ数のテキストだが長さが違うのが分かると思う。小文字の方が短くなっているのが分かる。
従って、正確な長さを図る場合は使用できない。

demo_wnd = float_wnd_create(400, 150, 1, true)
float_wnd_set_title(demo_wnd, "imgui Demo")
float_wnd_set_imgui_builder(demo_wnd, "build_demo")
float_wnd_set_onclose(demo_wnd, "closed_demo")

function build_demo(wnd, x, y) 
	local text = measure_string("ABCDEFG")
	local text2 = measure_string("abcdefg")
	imgui.TextUnformatted("text : " .. text) -- テキストを表示
	imgui.TextUnformatted("text2 : " .. text2)
end
function closed_demo(wnd)
end

文字の大きさを指定した場合

measure_string(“ABCDEFG”, “Helvetica_12”)

長さの測り方として文字数を取得と長さをピクセルとか他の何かで取得する方法があると思うが、数だと英語等な文字の幅が文字によって違うので長さが違ってくる。

imguiでは、ウィンドウのサイズをボクセルで指定します。 ボクセルはスケーラブルなピクセルです。
設定で UI スケールが 100% に設定されている場合、ボクセルはピクセルに相当します。 ただし、ユーザーが UI スケールを 100% 以上に設定すると、ボクセルは複数のピクセルにまたがるようにスケーリングされます。
※スケーラブルとは画面の解像度に応じて変化すること?

これは文字を長さ(ピクセル)で取得するので文字数とは違う値がでてくる。
measure_string(“string”) フォントを指定しない、drow_string()のような場合
measure_string(“string”,”fontname”) フォントを指定する場合

実際の例、以下はcursize=54となる
local cursize = measure_string(“ABCDEFG”)

measure_string( “string” )
a) string = 測定する文字列。
画面ピクセルの特定の文字列の長さを浮動小数点数として返します。 計算は、draw_string()で使用される標準の比例フォントに基づいています。

measure_string( “string“, “font name” ) 
a) string = 文字列 =測定する文字列。
b) font name = フォント名= GLUTで使用するフォントの名前。
画面のピクセルで指定された文字列の長さを整数として返します。 
計算は、2番目の引数で指定されたフォントに基づいています。 Helvetica_10、Helvetica_12、Helvetica_18、Times_Roman_10またはTimes_Roman_24です。

単純に文字数を数える

変数の前に「#」を付けるのがポイント。これで文字数を数えることができる。小文字でも大文字でもコンマが入っても数が同じになるし、長さもその数が一緒だと同じ長さになるようなのでこれが使える。

demo_wnd = float_wnd_create(200, 100, 1, true)
float_wnd_set_title(demo_wnd, "imgui Demo")
float_wnd_set_imgui_builder(demo_wnd, "build_demo")
float_wnd_set_onclose(demo_wnd, "closed_demo")

function build_demo(wnd, x, y) 
	text_1 = "Sample"
  	n_1 = #text_1
	imgui.TextUnformatted("text : " .. n_1) -- テキストを表示
	text_2 = "SAMPLE,SAMPLE"
  	n_2 = #text_2
	imgui.TextUnformatted("text : " .. n_2)

end
function closed_demo(wnd)
end

テキストの数をdraw_stringでX-Plane の画面に表示する場合。Sampleは6文字になる。
X-Planeで表示される英文は、大文字でも小文字も実際に寸法を測ると同じ長さに成る。

function Text_draw()
	text = "Sample"
	n = #text
	draw_string(x + 10, y - 50, n)
end
do_every_draw("Text_draw()")

ほかにもこんな方法がある
文字列、その後のl1〜l3までは文字の数取得していることになる。

function Text_draw()
	s = "Hello"
	l1 = string.len(s)
	l2 = s:len()
	l3 = #s
	polo = (string.format("%s length is %d %d %d.", s, l1, l2, l3))
	draw_string( 100, 100, polo, 0, 1, 0)
end
do_every_draw("Text_draw()")

日本語と英語の比較

日本語と英語では文字数が同じでも長さが違うので、大体の長さを同じに見えるようにしてみたらどのような数値を表示するのかやってみた。
上2行はこれには関係ない。float_wnd_set_imgui_builder()で英語を測定したもの。

日本語を使うにはfloat_wnd_set_ondraw()が必要なのでそれを使って実験した。上の画像では下の4行がそれにあたる。
その4行の、上2行が同じ長さに見えるように調整したテキストになる。その長さを測ったらその上の77という数値が出たので、かなり正確な数値が長さとして測定されているのが分かる。

wnd = float_wnd_create(200, 200, 1, true)
float_wnd_set_position(wnd, 50, 70)
float_wnd_set_title(wnd, "imgui Button")
float_wnd_set_imgui_builder(wnd, "button_demo")
float_wnd_set_ondraw(wnd, "on_draw_Button")
float_wnd_set_onclick(wnd, "on_click")

function button_demo(wnd, x, y)
	local text = measure_string("ABCDEFG")
	local text2 = measure_string("abcdefg")
	imgui.TextUnformatted("text : " .. text) -- テキストを表示
	imgui.TextUnformatted("text2 : " .. text2)
end

function on_draw_Button(wnd, x, y)
	XPLMSetGraphicsState(0, 0, 0, 1, 1, 0, 0)

	local text = measure_string("ABCDEFCABD")
	local text2 = measure_string("日本語日本語日")

	-- 日本語が使えるテキスト表示
	draw_string(x + 20, y + 120, "ABCDEFCABD", "white")
	draw_string(x + 20, y + 100, "日本語日本語日", "white")
	draw_string(x + 20, y + 80, "英語text : " .. text, "white")
	draw_string(x + 20, y + 60, "日本語text2 : " .. text2, "white")
end -- function on_draw

imgui.CalcTextSize(text)

これかなり使える。

テキストの長さと高さを取得する
これは14文字あり、結果「98」となり、1文字7の長さになる。小文字にしても同じ結果が出るので実際の長さは同じになるのが分かる。これはテキストの幅と高さを返してくるようだ。
local text = imgui.CalcTextSize(“ABCDEFGABCDEFG”)

demo_wnd = float_wnd_create(400, 150, 1, true)
float_wnd_set_title(demo_wnd, "imgui Demo")
float_wnd_set_imgui_builder(demo_wnd, "build_demo")
float_wnd_set_onclose(demo_wnd, "closed_demo")

function build_demo(wnd, x, y) 
	local text_width, text_height = imgui.CalcTextSize("ABCDEFG")
	imgui.TextUnformatted("text width : " .. text_width) -- テキストを表示
	imgui.TextUnformatted("text height : " .. text_height)
	-- CalcTextSize は、ボックス内のテキストの幅と高さを返します。
end
function closed_demo(wnd)
end

実際の例題「Pilot」の文字をボタンの中心に表示する。この方法だと半角英数字の場合、大文字でも小文字でも同じ幅でテキストが作成されているので長さが同じになる。

14行目と20行目で文字列の長さを取得している。

------------------------------------------------------------------------
-- ウインドウの作成
wnd = float_wnd_create(400, 200, 1, true)
float_wnd_set_title(wnd, "Buttons")             --wnd変数をセット
float_wnd_set_imgui_builder(wnd, "im_on_build") --関数を読み込みセットする
------------------------------------------------------------------------

local function button_draw()
  if imgui.Button("Button", 120, 65) then

  end

  local text = "Pilot"
  local text_size = imgui.CalcTextSize(text)  --テキストのサイズを取得
  --68はボタンの中心位置、テキストサイズを半分にして引くとボタンに対してテキストが中心になる。
  imgui.SetCursorPos(68 - (text_size / 2), imgui.GetCursorPosY())--パラメーターは、Xの位置と、Yの位置
  imgui.TextUnformatted(text)

  local text2 = "PILOT"
  local text_size2 = imgui.CalcTextSize(text2)  --テキストのサイズを取得
  --68はボタンの中心位置、テキストサイズを半分にして引くとボタンに対してテキストが中心になる。
  imgui.SetCursorPos(68 - (text_size2 / 2), imgui.GetCursorPosY())--パラメーターは、Xの位置と、Yの位置
  imgui.TextUnformatted(text2)
end
--ボタンを作成するための関数
function im_on_build(wnd, x, y)
  button_draw()
end
-- window close
function polo_onclose(polo_wnd)
  float_wnd_destroy(polo_wnd) --消し去る
end