功能說明
界面上增加3個標籤,分別用於顯示黑白子棋子個數,還有一個用於顯示倒計時的時間。
還增加2個圖片控件,用於提示該誰落子(當前該黑子下,還是白子下)。
glade界面設計
示例代碼
package main
import (
"fmt"
"os"
"unsafe"
"github.com/mattn/go-gtk/gdk"
"github.com/mattn/go-gtk/gdkpixbuf"
"github.com/mattn/go-gtk/glib"
"github.com/mattn/go-gtk/gtk"
)
//控件結構體
type ChessWidet struct {
window *gtk.Window //窗口
buttonMin *gtk.Button //最小化按鈕
buttonClose *gtk.Button //關閉按鈕
labelBlack *gtk.Label //顯示黑子個數
labelWhite *gtk.Label //顯示白子個數
labelTime *gtk.Label //倒計時間顯示
imageBlack *gtk.Image //黑子image,用於提示該誰落子
imageWhite *gtk.Image //白子image,用於提示該誰落子
}
//屬性結構體
type ChessInfo struct {
w, h int //窗口的寬度高度
x, y int //鼠標點擊座標(相對於窗口)
}
type Chessboard struct {
//匿名字段
ChessWidet
ChessInfo
}
//函數,給按鈕設置圖片
func ButtonSetImageFromFile(button *gtk.Button, filename string) {
//獲取按鈕的寬度和高度
var w, h int
button.GetSizeRequest(&w, &h)
//獲取pixbuf,指定其大小
pixbuf, _ := gdkpixbuf.NewPixbufFromFileAtScale(filename, w-10, h-10, false)
//通過pixbuf新建image
image := gtk.NewImageFromPixbuf(pixbuf)
//按鈕設置圖片
button.SetImage(image)
//釋放資源
pixbuf.Unref()
}
//函數,給image設置圖片
func ImageSetPixbufFromFile(image *gtk.Image, filename string) {
//獲取image的寬度和高度
var w, h int
image.GetSizeRequest(&w, &h)
//獲取pixbuf,指定其大小
pixbuf, _ := gdkpixbuf.NewPixbufFromFileAtScale(filename, w-5, h-5, false)
//image設置pixbuf
image.SetFromPixbuf(pixbuf)
//釋放資源
pixbuf.Unref()
}
//Chessboard的方法,獲取控件,設置控件屬性,返回主窗口控件指針
func (obj *Chessboard) CreateWindow() *gtk.Window {
builder := gtk.NewBuilder() //新建builder
builder.AddFromFile("ui.glade") //讀取glade文件
//獲取glade對應的控件
obj.window = gtk.WindowFromObject(builder.GetObject("window1")) //獲取窗口控件
obj.buttonMin = gtk.ButtonFromObject(builder.GetObject("buttonMin")) //按鈕
obj.buttonClose = gtk.ButtonFromObject(builder.GetObject("buttonClose"))
obj.labelBlack = gtk.LabelFromObject(builder.GetObject("labelBlack")) //標籤
obj.labelWhite = gtk.LabelFromObject(builder.GetObject("labelWhite"))
obj.labelTime = gtk.LabelFromObject(builder.GetObject("labelTime"))
obj.imageBlack = gtk.ImageFromObject(builder.GetObject("imageBlack")) //image
obj.imageWhite = gtk.ImageFromObject(builder.GetObject("imageWhite")) //image
//設置屬性
//窗口屬性
obj.w = 800
obj.h = 480
obj.window.SetSizeRequest(obj.w, obj.h) //設置窗口大小
obj.window.SetPosition(gtk.WIN_POS_CENTER) //居中顯示
obj.window.SetAppPaintable(true) //允許窗口能繪圖(重要)
obj.window.SetDecorated(false) //去表框
//添加鼠標按下事件
obj.window.SetEvents(int(gdk.BUTTON_PRESS_MASK | gdk.BUTTON1_MOTION_MASK))
//按鈕屬性
ButtonSetImageFromFile(obj.buttonMin, "image/min.png") //給按鈕設置圖片,此爲自定義函數
ButtonSetImageFromFile(obj.buttonClose, "image/close.png")
obj.buttonMin.SetCanFocus(false) //去掉按鈕上的聚焦框
obj.buttonClose.SetCanFocus(false)
//標籤屬性
obj.labelBlack.ModifyFontSize(50) //修改字體大小
obj.labelWhite.ModifyFontSize(50) //修改字體大小
obj.labelTime.ModifyFontSize(30) //修改字體大小
//修改字體顏色爲白色
obj.labelBlack.ModifyFG(gtk.STATE_NORMAL, gdk.NewColor("white"))
obj.labelWhite.ModifyFG(gtk.STATE_NORMAL, gdk.NewColor("white"))
obj.labelTime.ModifyFG(gtk.STATE_NORMAL, gdk.NewColor("white"))
//image屬性
ImageSetPixbufFromFile(obj.imageBlack, "image/black.png")
ImageSetPixbufFromFile(obj.imageWhite, "image/white.png")
return obj.window
}
//繪圖事件處理函數,"expose-event"的回調函數
func PaintEvent(ctx *glib.CallbackContext) {
arg := ctx.Data() //獲取用戶傳遞的參數,是空接口類型
obj, ok := arg.(*Chessboard) //類型斷言
if false == ok { //如果ok爲false,說明類型斷言錯誤
fmt.Println("arg.(*Chessboard) err")
return
}
//指定窗口爲繪圖區域,在窗口上繪圖
painter := obj.window.GetWindow().GetDrawable()
gc := gdk.NewGC(painter)
//設置背景圖的pixbuf,其寬高和窗口一樣,最後一個參數固定爲false
bg, _ := gdkpixbuf.NewPixbufFromFileAtScale("./image/bg.jpg", obj.w, obj.h, false)
//畫圖,畫背景圖
painter.DrawPixbuf(gc, bg, 0, 0, 0, 0, -1, -1, gdk.RGB_DITHER_NONE, 0, 0)
//釋放資源
bg.Unref()
}
//鼠標按下事件處理,MousePressEvent爲其回調函數,把obj傳遞給回調函數
func MousePressEvent(ctx *glib.CallbackContext) {
arg := ctx.Data() //獲取用戶傳遞的參數,是空接口類型
obj, ok := arg.(*Chessboard) //類型斷言
if false == ok { //如果ok爲false,說明類型斷言錯誤
fmt.Println("arg.(*Chessboard) err")
return
}
//獲取鼠鍵按下屬性結構體變量,系統內部的變量,不是用戶傳參變量
tmp := ctx.Args(0)
event := *(**gdk.EventButton)(unsafe.Pointer(&tmp))
if event.Button == 1 { //左鍵
obj.x, obj.y = int(event.X), int(event.Y) //保存點擊的起點座標
}
}
//方法,事件、信號處理,回調函數如果簡單使用匿名函數,否則自定義函數
func (obj *Chessboard) HandleSignal() {
//鼠標按下事件處理,MousePressEvent爲其回調函數,把obj傳遞給回調函數
obj.window.Connect("button-press-event", MousePressEvent, obj)
//鼠標移動事件處理,實現窗口的移動
obj.window.Connect("motion-notify-event", func(ctx *glib.CallbackContext) {
//獲取鼠標屬性結構體變量,系統內部的變量,不是用戶傳參變量
arg := ctx.Args(0)
//還是EventButton
event := *(**gdk.EventButton)(unsafe.Pointer(&arg))
//移動窗口
obj.window.Move(int(event.XRoot)-obj.x, int(event.YRoot)-obj.y)
})
//改變窗口大小時,觸發"configure-event",然後手動刷新繪圖區域,否則圖片會重疊
obj.window.Connect("configure-event", func() {
obj.window.QueueDraw() //刷新繪圖區域
})
//繪圖(曝光)事件,其回調函數PaintEvent做繪圖操作,把obj傳遞給回調函數
obj.window.Connect("expose-event", PaintEvent, obj)
//最小化按鈕信號處理
obj.buttonMin.Connect("clicked", func() {
obj.window.Iconify() //窗口最小化
})
//關閉按鈕信號處理
obj.buttonClose.Connect("clicked", func() {
gtk.MainQuit() //程序結束
})
}
func main() {
gtk.Init(&os.Args)
var obj Chessboard //創建結構體變量
//創建控件,設計屬性
window := obj.CreateWindow()
//事件、信號處理
obj.HandleSignal()
//顯示控件
window.ShowAll()
gtk.Main()
}
程序運行效果: