」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 為 macOS 建立市政廳時鐘應用程式:綜合指南

為 macOS 建立市政廳時鐘應用程式:綜合指南

發佈於2024-11-03
瀏覽:708

Building a City Hall Clock App for macOS: A Comprehensive Guide

准备好为您的 Mac 构建一个很酷的市政厅时钟应用程序了吗?伟大的!我们将创建一个位于菜单栏中的应用程序,每 15 分钟发出一次提示音,甚至可以计算时间。让我们一步步分解,我将解释代码的每一部分,以便您能够理解发生了什么。

项目概况

我们的市政厅时钟应用程序将:

  • 在 macOS 菜单栏中显示时钟图标
  • 每 15 分钟鸣响一次
  • 在每个小时的顶部鸣响小时数
  • 在菜单栏中提供“退出”选项
  • 作为正确的 macOS 应用程序运行,无需打开终端窗口

设置项目

首先,让我们设置我们的项目:

  1. 创建一个新目录:
   mkdir CityHallClock
   cd CityHallClock
  1. 初始化一个新的Go模块:
   go mod init cityhallclock
  1. 安装所需的依赖项:
   go get github.com/getlantern/systray
   go get github.com/faiface/beep

主要代码

现在,让我们创建 main.go 文件并浏览每个函数:

package main

import (
    "bytes"
    "log"
    "os"
    "path/filepath"
    "time"

    "github.com/faiface/beep"
    "github.com/faiface/beep/mp3"
    "github.com/faiface/beep/speaker"
    "github.com/getlantern/systray"
)

var (
    audioBuffer *beep.Buffer
)

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

// ... (other functions will go here)

让我们分解一下每个功能:

1.main()函数

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

这是我们的应用程序启动的地方。它做了两件重要的事情:

  1. 调用 initAudio() 来设置我们的铃声。
  2. 运行我们的系统托盘应用程序,告诉它在准备好(onReady)和退出(onExit)时要做什么。

2.initAudio()函数

func initAudio() {
    execPath, err := os.Executable()
    if err != nil {
        log.Fatal(err)
    }
    resourcesPath := filepath.Join(filepath.Dir(execPath), "..", "Resources")
    chimeFile := filepath.Join(resourcesPath, "chime.mp3")

    f, err := os.Open(chimeFile)
    if err != nil {
        log.Fatal(err)
    }
    defer f.Close()

    streamer, format, err := mp3.Decode(f)
    if err != nil {
        log.Fatal(err)
    }
    defer streamer.Close()

    audioBuffer = beep.NewBuffer(format)
    audioBuffer.Append(streamer)

    err = speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
    if err != nil {
        log.Fatal(err)
    }
}

此函数设置我们的音频:

  1. 它找到我们的应用程序运行的位置并找到铃声文件。
  2. 打开 MP3 文件并对其进行解码。
  3. 创建带有铃声的音频缓冲区。
  4. 初始化音频扬声器。

如果出现任何问题(例如找不到声音文件),它将记录错误并退出。

3.onReady()函数

func onReady() {
    systray.SetIcon(getIcon())
    systray.SetTitle("City Hall Clock")
    systray.SetTooltip("City Hall Clock")

    mQuit := systray.AddMenuItem("Quit", "Quit the app")

    go func() {
        



该函数设置我们的菜单栏图标:

  1. 设置图标(使用 getIcon())。
  2. 设置标题和工具提示。
  3. 在菜单中添加“退出”选项。
  4. 单击“退出”选项时开始侦听。
  5. 开始运行我们的时钟(在一个单独的 goroutine 中,这样它就不会阻塞)。

4.onExit()函数

func onExit() {
    // Cleanup tasks go here
}

当应用程序退出时调用此函数。我们在这里不做任何事情,但您可以根据需要添加清理任务。

5.runClock()函数

func runClock() {
    ticker := time.NewTicker(time.Minute)
    defer ticker.Stop()

    for {
        select {
        case t := 



这是我们时钟的“心脏”:

  1. 它创建了一个每分钟“滴答”的股票代码。
  2. 在无限循环中,它每分钟检查一次时间。
  3. 如果是整点或一刻钟,则会触发铃声。

6. chime()函数

func chime(t time.Time) {
    hour := t.Hour()
    minute := t.Minute()

    var chimeTimes int
    if minute == 0 {
        chimeTimes = hour % 12
        if chimeTimes == 0 {
            chimeTimes = 12
        }
    } else {
        chimeTimes = 1
    }

    for i := 0; i 



此功能播放我们的铃声:

  1. 它计算出鸣响多少次(每刻钟一次,或整点的小时数)。
  2. 然后它会多次播放铃声,并在铃声之间短暂停顿。

7. getIcon()函数

func getIcon() []byte {
    execPath, err := os.Executable()
    if err != nil {
        log.Fatal(err)
    }
    iconPath := filepath.Join(filepath.Dir(execPath), "..", "Resources", "icon.png")

    // Read the icon file
    icon, err := os.ReadFile(iconPath)
    if err != nil {
        log.Fatal(err)
    }

    return icon
}

该函数获取我们的菜单栏图标:

  1. 它找到我们的应用程序正在运行的位置。
  2. 在资源目录中找到图标文件。
  3. 读取图标文件并返回其内容。

创建 macOS 应用程序包

为了使我们的应用程序成为真正的 macOS 公民,我们需要创建一个应用程序包。这涉及创建一个 Info.plist 文件:





    CFBundleExecutable
    CityHallClock
    CFBundleIconFile
    AppIcon
    CFBundleIdentifier
    com.yourcompany.cityhallclock
    CFBundleName
    City Hall Clock
    CFBundlePackageType
    APPL
    CFBundleShortVersionString
    1.0
    CFBundleVersion
    1
    LSMinimumSystemVersion
    10.12
    LSUIElement
    
    NSHighResolutionCapable
    


将其另存为项目目录中的 Info.plist。

添加自定义图标

我们需要两个图标:

  1. 菜单栏图标:创建一个 22x22 像素的 PNG,命名为 icon.png。
  2. 应用程序图标:创建.icns文件:
    • 使图像大小为 16x16 到 1024x1024 像素。
    • 将它们保存在 AppIcon.iconset 中,名称如 icon_16x16.png。
    • 运行:iconutil -c icns AppIcon.iconset

建筑和包装

让我们创建一个构建脚本(build.sh):

#!/bin/bash

# Build the Go application
go build -o CityHallClock

# Create the app bundle structure
mkdir -p CityHallClock.app/Contents/MacOS
mkdir -p CityHallClock.app/Contents/Resources

# Move the executable to the app bundle
mv CityHallClock CityHallClock.app/Contents/MacOS/

# Copy the Info.plist
cp Info.plist CityHallClock.app/Contents/

# Copy the chime sound to Resources
cp chime.mp3 CityHallClock.app/Contents/Resources/

# Copy the menu bar icon
cp icon.png CityHallClock.app/Contents/Resources/

# Copy the application icon
cp AppIcon.icns CityHallClock.app/Contents/Resources/

echo "Application bundle created: CityHallClock.app"

使用 chmod x build.sh 使其可执行,然后使用 ./build.sh 运行它。

结论

这就是你得到的!您已经为 macOS 构建了功能齐全的市政厅时钟应用程序。您已了解:

  • 使用 Go 创建菜单栏应用程序
  • 以特定间隔播放声音
  • 将 Go 应用程序打包为原生 macOS 应用程序

请随意扩展这一点。也许添加自定义铃声或不同铃声间隔的首选项。天空是极限!

您可以在这里找到完整的源代码 https://github.com/rezmoss/citychime

快乐编码,享受你的新时钟!

版本聲明 本文轉載於:https://dev.to/rezmoss/building-a-city-hall-clock-app-for-macos-a-comprehensive-guide-48k4?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • CSS強類型語言解析
    CSS強類型語言解析
    您可以通过其强度或弱输入的方式对编程语言进行分类的方式之一。在这里,“键入”意味着是否在编译时已知变量。一个例子是一个场景,将整数(1)添加到包含整数(“ 1”)的字符串: result = 1 "1";包含整数的字符串可能是由带有许多运动部件的复杂逻辑套件无意间生成的。它也可以是故意从单个真理...
    程式設計 發佈於2025-05-05
  • 如何在Chrome中居中選擇框文本?
    如何在Chrome中居中選擇框文本?
    選擇框的文本對齊:局部chrome-inly-ly-ly-lyly solument 您可能希望將文本中心集中在選擇框中,以獲取優化的原因或提高可訪問性。但是,在CSS中的選擇元素中手動添加一個文本 - 對屬性可能無法正常工作。 初始嘗試 state)</option> < o...
    程式設計 發佈於2025-05-05
  • 在Oracle SQL中如何提取下劃線前的子字符串?
    在Oracle SQL中如何提取下劃線前的子字符串?
    [ 在oracle sql 解決方案: Explanation:SUBSTR function extracts a substring starting from the specified position (0) and continuing for a specified length.IN...
    程式設計 發佈於2025-05-05
  • Java中如何使用觀察者模式實現自定義事件?
    Java中如何使用觀察者模式實現自定義事件?
    在Java 中創建自定義事件的自定義事件在許多編程場景中都是無關緊要的,使組件能夠基於特定的觸發器相互通信。本文旨在解決以下內容:問題語句我們如何在Java中實現自定義事件以促進基於特定事件的對象之間的交互,定義了管理訂閱者的類界面。 以下代碼片段演示瞭如何使用觀察者模式創建自定義事件: args...
    程式設計 發佈於2025-05-05
  • 如何在php中使用捲髮發送原始帖子請求?
    如何在php中使用捲髮發送原始帖子請求?
    如何使用php 創建請求來發送原始帖子請求,開始使用curl_init()開始初始化curl session。然後,配置以下選項: curlopt_url:請求 [要發送的原始數據指定內容類型,為原始的帖子請求指定身體的內容類型很重要。在這種情況下,它是文本/平原。要執行此操作,請使用包含以下標頭...
    程式設計 發佈於2025-05-05
  • 如何將多種用戶類型(學生,老師和管理員)重定向到Firebase應用中的各自活動?
    如何將多種用戶類型(學生,老師和管理員)重定向到Firebase應用中的各自活動?
    Red: How to Redirect Multiple User Types to Respective ActivitiesUnderstanding the ProblemIn a Firebase-based voting app with three distinct user type...
    程式設計 發佈於2025-05-05
  • 如何在其容器中為DIV創建平滑的左右CSS動畫?
    如何在其容器中為DIV創建平滑的左右CSS動畫?
    通用CSS動畫,用於左右運動 ,我們將探索創建一個通用的CSS動畫,以向左和右移動DIV,從而到達其容器的邊緣。該動畫可以應用於具有絕對定位的任何div,無論其未知長度如何。 問題:使用左直接導致瞬時消失 更加流暢的解決方案:混合轉換和左 [並實現平穩的,線性的運動,我們介紹了線性的轉換。...
    程式設計 發佈於2025-05-05
  • 如何高效地在一個事務中插入數據到多個MySQL表?
    如何高效地在一個事務中插入數據到多個MySQL表?
    mySQL插入到多個表中,該數據可能會產生意外的結果。雖然似乎有多個查詢可以解決問題,但將從用戶表的自動信息ID與配置文件表的手動用戶ID相關聯提出了挑戰。 使用Transactions和last_insert_id() 插入用戶(用戶名,密碼)值('test','tes...
    程式設計 發佈於2025-05-05
  • 如何檢查對像是否具有Python中的特定屬性?
    如何檢查對像是否具有Python中的特定屬性?
    方法來確定對象屬性存在尋求一種方法來驗證對像中特定屬性的存在。考慮以下示例,其中嘗試訪問不確定屬性會引起錯誤: >>> a = someClass() >>> A.property Trackback(最近的最新電話): 文件“ ”,第1行, AttributeError: SomeClass...
    程式設計 發佈於2025-05-05
  • 左連接為何在右表WHERE子句過濾時像內連接?
    左連接為何在右表WHERE子句過濾時像內連接?
    左JOIN CONUNDRUM:WITCHING小時在數據庫Wizard的領域中變成內在的加入很有趣,當將c.foobar條件放置在上面的Where子句中時,據說左聯接似乎會轉換為內部連接。僅當滿足A.Foo和C.Foobar標準時,才會返回結果。 為什麼要變形?關鍵在於其中的子句。當左聯接的右側...
    程式設計 發佈於2025-05-05
  • 如何從Python中的字符串中刪除表情符號:固定常見錯誤的初學者指南?
    如何從Python中的字符串中刪除表情符號:固定常見錯誤的初學者指南?
    從python import codecs import codecs import codecs 導入 text = codecs.decode('這狗\ u0001f602'.encode('utf-8'),'utf-8') 印刷(文字)#帶有...
    程式設計 發佈於2025-05-05
  • 如何在Java的全屏獨家模式下處理用戶輸入?
    如何在Java的全屏獨家模式下處理用戶輸入?
    Handling User Input in Full Screen Exclusive Mode in JavaIntroductionWhen running a Java application in full screen exclusive mode, the usual event ha...
    程式設計 發佈於2025-05-05
  • 如何在Java中正確顯示“ DD/MM/YYYY HH:MM:SS.SS”格式的當前日期和時間?
    如何在Java中正確顯示“ DD/MM/YYYY HH:MM:SS.SS”格式的當前日期和時間?
    如何在“ dd/mm/yyyy hh:mm:mm:ss.ss”格式“ gormat 解決方案:的,請訪問量很大,並應為procectiquiestate的,並在整個代碼上正確格式不多: java.text.simpledateformat; 導入java.util.calendar; 導入java...
    程式設計 發佈於2025-05-05
  • Java開發者如何保護數據庫憑證免受反編譯?
    Java開發者如何保護數據庫憑證免受反編譯?
    在java 在單獨的配置文件保護數據庫憑證的最有效方法中存儲憑據是將它們存儲在單獨的配置文件中。該文件可以在運行時加載,從而使登錄數據從編譯的二進製文件中遠離。 使用prevereness class import java.util.prefs.preferences; 公共類示例{ 首選...
    程式設計 發佈於2025-05-05
  • 為什麼我在Silverlight Linq查詢中獲得“無法找到查詢模式的實現”錯誤?
    為什麼我在Silverlight Linq查詢中獲得“無法找到查詢模式的實現”錯誤?
    查詢模式實現缺失:解決“無法找到”錯誤在Silverlight應用程序中,嘗試使用LINQ建立LINQ連接以錯誤而實現的數據庫”,無法找到查詢模式的實現。”當省略LINQ名稱空間或查詢類型缺少IEnumerable 實現時,通常會發生此錯誤。 解決問題來驗證該類型的質量是至關重要的。在此特定實例...
    程式設計 發佈於2025-05-05

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3