Go로 간단한 시스템 트레이 앱 만들기

25309 단어 systraygo

실습: 다른 국가를 선택할 수 있는 가능성과 함께 현재 현지 시간을 보여주는 시스템 트레이 애플리케이션을 빌드해 보겠습니다.
우리는 Getlantern의 라이브러리systray를 사용할 것입니다.

package main

import (
    "fmt"
    "io/ioutil"

    "github.com/getlantern/systray"
)

func main() {
    systray.Run(onReady, onExit)
}

func onReady() {
    systray.SetIcon(getIcon("assets/clock.ico"))
    systray.SetTitle("I'm alive!")
    systray.SetTooltip("Look at me, I'm a tooltip!")
}

func onExit() {
    // Cleaning stuff here.
}

func getIcon(s string) []byte {
    b, err := ioutil.ReadFile(s)
    if err != nil {
        fmt.Print(err)
    }
    return b
}


이 코드를 바로 사용해 볼 수 있습니다.
할 일은 시스템 트레이에 아이콘과 함께 간단한 메시지를 표시하는 것뿐입니다. 그게 다야.
이것을 조금 나누어 봅시다. outmain()에서 우리가 할 수 있는 유일한 일은 함수Run를 사용하여 라이브러리 systray의 새 인스턴스를 호출하는 것입니다. 이 함수는 onReady에서 수행할 작업과 애플리케이션이 종료될 때 정의하는 몇 가지 매개 변수를 받습니다.SetIcon , SetTitleSetTooltip 는 매우 간단합니다. 고려해야 할 유일한 사항은 SetIcon가 []바이트로 표시하려는 아이콘을 매개변수로 사용한다는 것입니다. 함수getIcon를 사용하여 .ico 파일을 읽고 []바이트를 반환합니다.

힌트: 무료 아이콘을 찾을 수 있는 좋은 장소는 IconArchive입니다.

이제 우리는 내가 살아있다는 것을 원하지 않습니다! 제목으로 타이머의 로컬 값으로 매초를 업데이트할 것입니다. onReady() 함수를 업데이트하고 시간 값을 얻는 데 도움이 되는 몇 가지를 더 추가해 보겠습니다.

func onReady() {
    systray.SetIcon(getIcon("assets/clock.ico"))
    for {
        systray.SetTitle(getTime())
        systray.SetTooltip("Look at me, I'm a tooltip!")
        time.Sleep(1 * time.Second)
    }
}

func getTime() string {
    t := time.Now()
    hour, min, sec := t.Clock()
    return ItoaTwoDigits(hour) + ":" + ItoaTwoDigits(min) + ":" + ItoaTwoDigits(sec)
}

// ItoaTwoDigits time.Clock returns one digit on values, so we make sure to convert to two digits
func ItoaTwoDigits(i int) string {
    b := "0" + strconv.Itoa(i)
    return b[len(b)-2:]
}


실행하면 시계가 매초 업데이트되는 것을 볼 수 있습니다. 그러나 이것은 autoupdater를 구현하는 가장 좋은 방법은 아닙니다. time.Sleep()를 구현하면 현재 인스턴스를 일시 중지할 수 있지만 기본 프로세스를 차단하고 싶지는 않습니다. 이 경우 Go routine을 사용합니다.

go func() {
    for {
    systray.SetTitle(getTime())
    systray.SetTooltip("Look at me, I'm a tooltip!")
        time.Sleep(1 * time.Second)
    }
}()


이제 메뉴 항목을 추가할 차례입니다. systray.AddMenuItem("Title", "Tooltip") 로 쉽게 할 수 있습니다. 이 함수는 누르면 채널을 반환합니다. 그래서 이런 식으로 몇 가지 항목을 추가하려고 합니다.

localTime := systray.AddMenuItem("Local time", "Local time")
hcmcTime := systray.AddMenuItem("Ho Chi Minh time", "Asia/Ho_Chi_Minh")
sydTime := systray.AddMenuItem("Sydney time", "Australia/Sydney")
gdlTime := systray.AddMenuItem("Guadalajara time", "America/Mexico_City")
sfTime := systray.AddMenuItem("San Fransisco time", "America/Los_Angeles")
systray.AddSeparator()
mQuit := systray.AddMenuItem("Quit", "Quits this app")


또한 코드 상단에 사용 중인 시간대를 추적하는 방법을 추가해 보겠습니다.

var (
    timezone string
)


그리고 systray.SetTitle(getTime())systray.SetTitle(getClockTime(timezone))로 바꿉니다.
이제 메뉴 항목을 눌렀을 때 가져오는 방법입니다.

go func() {
    for {
        select {
    case <-localTime.ClickedCh:
            timezone = "Local"
        case <-hcmcTime.ClickedCh:
            timezone = "Asia/Ho_Chi_Minh"
        case <-sydTime.ClickedCh:
            timezone = "Australia/Sydney"
        case <-gdlTime.ClickedCh:
            timezone = "America/Mexico_City"
        case <-sfTime.ClickedCh:
            timezone = "America/Los_Angeles"
        case <-mQuit.ClickedCh:
            systray.Quit()
            return
        }
    }
}()


그리고 시간대 선택기와 좀 더 호환되도록 getTime 함수를 수정해 보겠습니다.

func getClockTime(tz string) string {
    t := time.Now()
    utc, _ := time.LoadLocation(tz)

    hour, min, sec := t.In(utc).Clock()
    return ItoaTwoDigits(hour) + ":" + ItoaTwoDigits(min) + ":" + ItoaTwoDigits(sec)
}


힌트: 시간대 식별자는 IANA 시간대 식별자로 알려져 있습니다. 그렇게 구글링. time.is에서 필요한 도시의 식별자를 쉽게 얻을 수 있습니다.

따라서 모든 코드는 다음과 같아야 합니다.

package main

import (
    "fmt"
    "io/ioutil"
    "strconv"
    "time"

    "github.com/getlantern/systray"
)

var (
    timezone string
)

func main() {
    systray.Run(onReady, onExit)
}

func onReady() {
    timezone = "Local"

    systray.SetIcon(getIcon("assets/clock.ico"))

    localTime := systray.AddMenuItem("Local time", "Local time")
    hcmcTime := systray.AddMenuItem("Ho Chi Minh time", "Asia/Ho_Chi_Minh")
    sydTime := systray.AddMenuItem("Sydney time", "Australia/Sydney")
    gdlTime := systray.AddMenuItem("Guadalajara time", "America/Mexico_City")
    sfTime := systray.AddMenuItem("San Fransisco time", "America/Los_Angeles")
    systray.AddSeparator()
    mQuit := systray.AddMenuItem("Quit", "Quits this app")

    go func() {
        for {
            systray.SetTitle(getClockTime(timezone))
            systray.SetTooltip(timezone + " timezone")
            time.Sleep(1 * time.Second)
        }
    }()

    go func() {
        for {
            select {
            case <-localTime.ClickedCh:
                timezone = "Local"
            case <-hcmcTime.ClickedCh:
                timezone = "Asia/Ho_Chi_Minh"
            case <-sydTime.ClickedCh:
                timezone = "Australia/Sydney"
            case <-gdlTime.ClickedCh:
                timezone = "America/Mexico_City"
            case <-sfTime.ClickedCh:
                timezone = "America/Los_Angeles"
            case <-mQuit.ClickedCh:
                systray.Quit()
                return
            }
        }
    }()
}

func onExit() {
    // Cleaning stuff here.
}

func getClockTime(tz string) string {
    t := time.Now()
    utc, _ := time.LoadLocation(tz)

    hour, min, sec := t.In(utc).Clock()
    return ItoaTwoDigits(hour) + ":" + ItoaTwoDigits(min) + ":" + ItoaTwoDigits(sec)
}

// ItoaTwoDigits time.Clock returns one digit on values, so we make sure to convert to two digits
func ItoaTwoDigits(i int) string {
    b := "0" + strconv.Itoa(i)
    return b[len(b)-2:]
}

func getIcon(s string) []byte {
    b, err := ioutil.ReadFile(s)
    if err != nil {
        fmt.Print(err)
    }
    return b
}


🎉

이 기능을 구현하는 다른/더 나은 방법을 알고 계십니까?
시간대 선택/채널을 하드코딩하는 것 같은데 이 부분을 최적화할 수 있는 방법을 찾을 수 있을까요?

실행할 준비가 된 모든 코드는 github.com/Osuka42g/simple-clock-systray 에서 찾을 수 있습니다. 해킹! ðŸ»

좋은 웹페이지 즐겨찾기