この章では、Go-GTK のメニューバーとツールバーとステータスバーを説明します。
GTK のこれらバーは、他の GUI アプリケーション・フレームワークとは違い、次のような特徴があります。
package main
import (
"github.com/mattn/go-gtk/gtk"
"os"
)
func main() {
gtk . Init(&os.Args)
window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
window . SetTitle("Menu Bar")
window . Connect("destroy", gtk.MainQuit)
menubar := gtk.NewMenuBar()
filemenu:= gtk.NewMenuItemWithMnemonic("_File")
menubar . Append(filemenu)
filesub := gtk.NewMenu()
filemenu. SetSubmenu(filesub)
newmenu := gtk.NewMenuItemWithMnemonic("N_ew")
openmenu:= gtk.NewMenuItemWithMnemonic("O_pen")
savemenu:= gtk.NewMenuItemWithMnemonic("S_ave")
filesepa:= gtk.NewSeparatorMenuItem()
exitmenu:= gtk.NewMenuItemWithMnemonic("E_xit")
exitmenu. Connect("activate", func() {
gtk.MainQuit()
})
filesub . Append(newmenu)
filesub . Append(openmenu)
filesub . Append(savemenu)
filesub . Append(filesepa)
filesub . Append(exitmenu)
editmenu:= gtk.NewMenuItemWithMnemonic("E_dit")
menubar . Append(editmenu)
editsub := gtk.NewMenu()
editmenu. SetSubmenu(editsub)
undomenu:= gtk.NewMenuItemWithMnemonic("U_ndo")
redomenu:= gtk.NewMenuItemWithMnemonic("R_edo")
editsepa:= gtk.NewSeparatorMenuItem()
copymenu:= gtk.NewMenuItemWithMnemonic("C_opy")
cutmenu := gtk.NewMenuItemWithMnemonic("C_ut")
pastmenu:= gtk.NewMenuItemWithMnemonic("P_aste")
editsub . Append(undomenu)
editsub . Append(redomenu)
editsub . Append(editsepa)
editsub . Append(copymenu)
editsub . Append(cutmenu)
editsub . Append(pastmenu)
textview:= gtk.NewTextView()
frame := gtk.NewFrame("")
frame . Add(textview)
swindow := gtk.NewScrolledWindow(nil, nil)
swindow . SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
swindow . SetBorderWidth(10)
swindow . AddWithViewPort(frame)
vbox := gtk.NewVBox(false, 1)
vbox . PackStart(menubar, false, false, 0)
vbox . PackStart(swindow, true, true, 0)
window . Add(vbox)
window . ShowAll()
window . SetSizeRequest(400, 250)
gtk . Main()
}
ターミナルで、menubar.go を保存したディレクトリに移動して、次のコードを実行してください。
go run menubar.go
menubar := gtk.NewMenuBar()
メニューバーを作っています。
filemenu:= gtk.NewMenuItemWithMnemonic("_File")
メニューアイテム(menu item)を作っています。アンダースコア( _ )の後の文字が、ニーモニック(mnemonic)キーになります。ニーモニックとは、オプション(option)キーと同時にそのキーを押すと、そのメニューを選んだことになるキーです。メニューには、File のように、ニーモニックキーにアンダーラインが付いて表示されます。
filemenu:= gtk.NewMenuItemWithLabel("File")
上記のように記述すると、ニーモニックを使用しないメニューアイテムが作れます。
menubar . Append(filemenu)
メニューバーに、filemenu メニューアイテムを追加しています。
filesub := gtk.NewMenu()
ファイルメニューに、さらにメニューアイテムを追加するには、まずメニューを作ります。
filemenu. SetSubmenu(filesub)
そのメニューを、ファイルメニューのサブメニューとして設定します。
newmenu := gtk.NewMenuItemWithMnemonic("N_ew")
そして、ファイルメニューに追加するメニューアイテムを作ります。
filesub . Append(newmenu)
そのメニューアイテムを、サブメニューに追加します。
vbox . PackStart(menubar, false, false, 0)
そして、メニューバーを Box コンテナーに入れます。
window . Add(vbox)
最後に、その Box コンテナーをウィンドウに追加します。
package main
import (
"github.com/mattn/go-gtk/gtk"
"os"
"strconv"
)
func main() {
gtk . Init(&os.Args)
window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
window . SetTitle("Tool Bar")
window . SetBorderWidth(5)
window . SetPosition(gtk.WIN_POS_CENTER)
window . Connect("destroy", gtk.MainQuit)
count := 5
tool := gtk.NewToolbar()
tool . SetStyle(gtk.TOOLBAR_ICONS)
undo := gtk.NewToolButtonFromStock(gtk.STOCK_UNDO)
redo := gtk.NewToolButtonFromStock(gtk.STOCK_REDO)
sep := gtk.NewSeparatorToolItem()
quit := gtk.NewToolButtonFromStock(gtk.STOCK_QUIT)
redo . SetSensitive(false)
tool . Insert(undo, 0)
tool . Insert(redo, 1)
tool . Insert(sep, 2)
tool . Insert(quit, 3)
label := gtk.NewLabel("")
label . SetAngle(20)
label . SetMarkup("<span size='19000'>5</span>")
vbox := gtk.NewVBox(false, 5)
vbox . PackStart(tool, false, false, 0)
vbox . Add(label)
window . Add(vbox)
undo . Connect("clicked", func() {
count--
switch count {
case 0:
undo.SetSensitive(false)
case 4:
redo.SetSensitive(true)
}
str := "<span size='19000'>" + strconv.Itoa(count) + "</span>"
label.SetMarkup(str)
})
redo . Connect("clicked", func() {
count++
switch count {
case 1:
undo.SetSensitive(true)
case 5:
redo.SetSensitive(false)
}
str := "<span size='19000'>" + strconv.Itoa(count) + "</span>"
label.SetMarkup(str)
})
quit . Connect("clicked", gtk.MainQuit)
window . ShowAll()
window . SetSizeRequest(400, 250)
gtk . Main()
}
ターミナルで、toolbar.go を保存したディレクトリに移動して、次のコードを実行してください。
go run toolbar.go
package main
import (
"github.com/mattn/go-gtk/gtk"
"os"
)
func main() {
gtk . Init(&os.Args)
window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
window . SetTitle("Status Bar")
window . SetBorderWidth(5)
window . SetPosition(gtk.WIN_POS_CENTER)
window . Connect("destroy", gtk.MainQuit)
ok := gtk.NewButtonWithLabel("OK")
cancel := gtk.NewButtonWithLabel("Cencel")
hbox := gtk.NewHBox(true, 5)
hbox . Add(ok)
hbox . Add(cancel)
textview:= gtk.NewTextView()
frame := gtk.NewFrame("")
frame . Add(textview)
swindow := gtk.NewScrolledWindow(nil, nil)
swindow . SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
swindow . AddWithViewPort(frame)
status := gtk.NewStatusbar()
id := status.GetContextId("go")
status . Push(id, "Ready.")
ok . Connect("clicked", func() {
status.Push(id, "OK was clicked.")
})
cancel . Connect("clicked", func() {
status.Push(id, "Cancel was clicked.")
})
vbox := gtk.NewVBox(false, 5)
vbox . PackStart(hbox, false, false, 0)
vbox . Add(swindow)
vbox . PackEnd(status,false,false,0)
window . Add(vbox)
window . ShowAll()
window . SetSizeRequest(400, 250)
gtk . Main()
}
ターミナルで、statusbar.go を保存したディレクトリに移動して、次のコードを実行してください。
go run statusbar.go
package main
import (
"github.com/mattn/go-gtk/gtk"
)
func main() {
gtk.Init(nil)
window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
window . SetDefaultSize(400, 250)
window . SetTitle("Other Menu")
window . SetPosition(gtk.WIN_POS_CENTER)
window . Connect("destroy", gtk.MainQuit)
vbox := gtk.NewVBox(false, 1)
window . Add(vbox)
label := gtk.NewLabel("")
label . SetMarkup("<span foreground='red' size='19000'>Red</span>")
vbox . PackEnd(label, true, true,0)
//--------------------------------------------------------
// Menu
//--------------------------------------------------------
menubar := gtk.NewMenuBar()
vbox . PackStart(menubar, false, false, 0)
radio := gtk.NewMenuItemWithMnemonic("_Radio")
menubar . Append(radio)
radiosub:= gtk.NewMenu()
radio . SetSubmenu(radiosub)
red := gtk.NewRadioMenuItemWithLabel(nil, "Red")
green := gtk.NewRadioMenuItemWithLabel(red.GetGroup(), "Green")
blue := gtk.NewRadioMenuItemWithLabel(red.GetGroup(), "Blue")
radiosub. Append(red)
radiosub. Append(green)
radiosub. Append(blue)
red . Connect("activate", func() {
if red.GetActive() {
label.SetMarkup("<span foreground='red' size='19000'>Red</span>")
}
})
green . Connect("activate", func() {
if green.GetActive() {
label.SetMarkup("<span foreground='green' size='19000'>Green</span>")
}
})
blue . Connect("activate", func() {
if blue.GetActive() {
label.SetMarkup("<span foreground='blue' size='19000'>Blue</span>")
}
})
check := gtk.NewMenuItemWithMnemonic("_Check")
menubar . Append(check)
checksub:= gtk.NewMenu()
check . SetSubmenu(checksub)
show := gtk.NewCheckMenuItemWithMnemonic("_Show Label")
checksub. Append(show)
show . Connect("activate", func() {
if show.GetActive() {
label.Show()
} else {
label.Hide()
}
})
show . SetActive(true)
window . ShowAll()
gtk . Main()
}
ターミナルで、othermenu.go を保存したディレクトリに移動して、次のコードを実行してください。
go run othermenu.go
Control + Q(macOSでは Command + Q)で終了(Quit)メニューを選んだことになるようなキーの組み合わせをショートカットキーと呼びます。
GTK のショートカットキーの設定方法は、他の GUI アプリケーション・フレームワークと比べるとかなり変わっています。
まず、XMLで、メニューの外枠を規定します。そしてそこからコードをゴニョゴニョしてショートカットキーを設定していきます。
package main
import (
"github.com/mattn/go-gtk/gtk"
)
func main() {
UI_INFO := `
<ui>
<menubar name='MenuBar'>
<menu action='FileMenu'>
<menuitem action='FileNew' />
<menuitem action='FileOpen' />
<menuitem action='FileSave' />
<separator />
<menuitem action='FileQuit' />
</menu>
<menu action='EditMenu'>
<menuitem action='EditUndo' />
<menuitem action='EditRedo' />
<separator />
<menuitem action='EditCopy' />
<menuitem action='EditPaste' />
<menuitem action='EditCut' />
<menuitem action='EditSomething' />
</menu>
</menubar>
<toolbar name='ToolBar'>
<toolitem action='FileNewTool' />
<toolitem action='FileOpenTool' />
<toolitem action='FileSaveTool' />
<separator />
<toolitem action='FileQuit' />
</toolbar>
</ui>
`
gtk.Init(nil)
window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
window . SetDefaultSize(400, 250)
window . SetTitle("Action Menu")
window . SetPosition(gtk.WIN_POS_CENTER)
window . Connect("destroy", gtk.MainQuit)
vbox := gtk.NewVBox(false, 1)
window . Add(vbox)
label := gtk.NewLabel("未選択")
vbox . PackEnd(label, true, true,0)
/* */
/* Action */
/* */
action := gtk.NewActionGroup("my_action")
ui := gtk.NewUIManager()
ui . AddUIFromString(UI_INFO)
ui . InsertActionGroup(action, 0)
accel := ui.GetAccelGroup()
window . AddAccelGroup(accel)
/* */
/* File Menu */
/* */
action . AddAction(gtk.NewAction("FileMenu", "File", "", ""))
filenew := gtk.NewAction("FileNew", "", "", gtk.STOCK_NEW)
filenew . Connect("activate", func() { label.SetLabel("New")})
action . AddActionWithAccel(filenew, "")
//action. AddAction(filenew) アクセルがつかない
fileopen:= gtk.NewAction("FileOpen", "", "", gtk.STOCK_OPEN)
fileopen. Connect("activate", func() { label.SetLabel("Open")})
action . AddActionWithAccel(fileopen, "")
filesave:= gtk.NewAction("FileSave", "", "", gtk.STOCK_SAVE)
filesave. Connect("activate", func() { label.SetLabel("Save")})
action . AddActionWithAccel(filesave, "")
filequit:= gtk.NewAction("FileQuit", "", "", gtk.STOCK_QUIT)
filequit. Connect("activate", gtk.MainQuit)
action . AddActionWithAccel(filequit, "")
/* */
/* Edit Menu */
/* */
action . AddAction(gtk.NewAction("EditMenu", "Edit", "", ""))
editundo:= gtk.NewAction("EditUndo", "", "", gtk.STOCK_UNDO)
editundo. Connect("activate", func() {label.SetLabel("Undo")})
action . AddActionWithAccel(editundo, "")
editredo:= gtk.NewAction("EditRedo", "", "", gtk.STOCK_REDO)
editredo. Connect("activate", func() {label.SetLabel("Redo")})
action . AddActionWithAccel(editredo, "")
editcopy:= gtk.NewAction("EditCopy", "", "", gtk.STOCK_COPY)
editcopy. Connect("activate", func() { label.SetLabel("Copy")})
action . AddActionWithAccel(editcopy, "")
editpast:= gtk.NewAction("EditPaste", "", "", gtk.STOCK_PASTE)
editpast. Connect("activate", func() { label.SetLabel("Paste")})
action . AddActionWithAccel(editpast, "")
editcut := gtk.NewAction("EditCut", "", "", gtk.STOCK_CUT)
editcut . Connect("activate", func() { label.SetLabel("Cut")})
action . AddActionWithAccel(editcut, "")
editsome:= gtk.NewAction("EditSomething", "Something", "", "")
editsome. Connect("activate", func() {
label.SetLabel("Something was selected.")
})
action . AddActionWithAccel(editsome, "<control><alt>S")
/* */
/* Tool Bar */
/* */
new := gtk.NewAction("FileNewTool", "", "", gtk.STOCK_NEW)
new . Connect("activate", func() { label.SetLabel("Tool New")})
action . AddActionWithAccel(new, "")
open := gtk.NewAction("FileOpenTool", "", "", gtk.STOCK_OPEN)
open . Connect("activate", func() { label.SetLabel("Tool Open")})
action . AddActionWithAccel(open, "")
save := gtk.NewAction("FileSaveTool", "", "", gtk.STOCK_SAVE)
save . Connect("activate", func() { label.SetLabel("Tool Save")})
action . AddActionWithAccel(save, "")
/* */
/* Assembly */
/* */
menubar := ui.GetWidget("/MenuBar")
toolbar := ui.GetWidget("/ToolBar")
vbox . PackStart(menubar, false, false, 0)
vbox . PackStart(toolbar, false, false, 0)
//vbox . Add(label)
window . ShowAll()
gtk . Main()
}
ターミナルで、action.go を保存したディレクトリに移動して、次のコードを実行してください。
go run action.go