
tcellでTUIアプリを作成するで作成しましたTUIアプリで矢印キーでカーソルを移動できるようにします。
前回作成したコードに太字で示したコードを追加します。
~/workspace/tcell_sample/main.go
package main
import (
"github.com/gdamore/tcell/v2"
)
func main() {
screen, err := tcell.NewScreen()
if err != nil {
panic(err)
}
if err := screen.Init(); err != nil {
panic(err)
}
defer screen.Fini()
pos_x, pos_y := 5, 10
for {
ev := screen.PollEvent() // イベントを取得する
switch ev := ev.(type) {
case *tcell.EventKey:
switch ev.Key() {
case tcell.KeyEscape: // ESCキーが押されたら終了する
return
case tcell.KeyUp:
pos_y--
if pos_y <= 0 {
pos_y = 0
}
case tcell.KeyDown:
pos_y++
case tcell.KeyLeft:
pos_x--
if pos_x <= 0 {
pos_x = 0
}
case tcell.KeyRight:
pos_x++
}
}
screen.ShowCursor(pos_x, pos_y)
screen.Show()
}
}
pos_x, pos_y := 5, 10
でカーソルを最初に配置する場所を決め、for のイベントループ内の
screen.ShowCursor(pos_x, pos_y)
で指定した場所にカーソルを配置します。
後は for のイベントループ内で矢印キーを押した時の挙動を追加しています。
画面上と左は座標がわかるので、矢印を押しすぎた時の対応(pos_x等の変数を 0 にする)は簡単ですが、右と下の座標は現時点ではわかりません。
そこで、スクリーンのサイズを取得する為に下記のように書き換えます。
package main
import (
"github.com/gdamore/tcell/v2"
)
func main() {
screen, err := tcell.NewScreen()
if err != nil {
panic(err)
}
if err := screen.Init(); err != nil {
panic(err)
}
defer screen.Fini()
pos_x, pos_y := 5, 10
screen_x, screen_y := screen.Size()
for {
ev := screen.PollEvent() // イベントを取得する
switch ev := ev.(type) {
case *tcell.EventKey:
switch ev.Key() {
case tcell.KeyEscape: // ESCキーが押されたら終了する
return
case tcell.KeyUp:
pos_y--
if pos_y <= 0 {
pos_y = 0
}
case tcell.KeyDown:
pos_y++
if pos_y >= screen_y-1 {
pos_y = screen_y - 1
}
case tcell.KeyLeft:
pos_x--
if pos_x <= 0 {
pos_x = 0
}
case tcell.KeyRight:
pos_x++
if pos_x >= screen_x-1 {
pos_x = screen_x - 1
}
}
}
screen.ShowCursor(pos_x, pos_y)
screen.Show()
}
}
screen_x, screen_y := screen.Size()
で現在のスクリーンのサイズ(右端のx座標と下のy座標)を取得して、各々のキーの操作で使用します。
ただ、このコードでは、TUIアプリ起動時にウィンドウのサイズを変更した場合、右端のx座標と下のy座標が変更されてしまいますので、
package main
import (
"github.com/gdamore/tcell/v2"
)
func main() {
screen, err := tcell.NewScreen()
if err != nil {
panic(err)
}
if err := screen.Init(); err != nil {
panic(err)
}
defer screen.Fini()
pos_x, pos_y := 5, 10
screen_x, screen_y := screen.Size()
for {
ev := screen.PollEvent() // イベントを取得する
switch ev := ev.(type) {
case *tcell.EventKey:
switch ev.Key() {
case tcell.KeyEscape: // ESCキーが押されたら終了する
return
case tcell.KeyUp:
pos_y--
if pos_y <= 0 {
pos_y = 0
}
case tcell.KeyDown:
pos_y++
if pos_y >= screen_y-1 {
pos_y = screen_y - 1
}
case tcell.KeyLeft:
pos_x--
if pos_x <= 0 {
pos_x = 0
}
case tcell.KeyRight:
pos_x++
if pos_x >= screen_x-1 {
pos_x = screen_x - 1
}
}
case *tcell.EventResize:
screen.Sync()
screen_x, screen_y = screen.Size()
}
screen.ShowCursor(pos_x, pos_y)
screen.Show()
}
}
case *tcell.EventResize: screen.Sync() screen_x, screen_y = screen.Size()
ウィンドウのリサイズのイベントを追加して、再度、右端のx座標と下のy座標を取得します。