第 3 部分 · GUI 开发
GUI 开发入门
GUI 开发入门
使用 racket/gui 库创建跨平台的桌面应用程序。
第一个窗口
#lang racket/gui
;; 创建主窗口
(define frame
(new frame%
[label "我的第一个 Racket GUI"]
[width 400]
[height 300]))
;; 创建消息面板
(define msg
(new message%
[parent frame]
[label "Hello, Racket GUI!"]
[auto-resize #t]))
;; 显示窗口
(send frame show #t)
运行这段代码,你会看到一个带有标题和文本的窗口。
添加交互控件
#lang racket/gui
(define frame
(new frame%
[label "交互示例"]
[width 400]
[height 200]))
;; 文本输入
(define input
(new text-field%
[parent frame]
[label "输入名字:"]))
;; 按钮
(define btn
(new button%
[parent frame]
[label "打招呼"]
[callback
(lambda (button event)
(define name (send input get-value))
(message-box "问候"
(format "你好, ~a!" name)
frame))]))
(send frame show #t)
布局管理
使用水平和垂直面板组织控件:
#lang racket/gui
(define frame
(new frame%
[label "布局示例"]
[width 500]
[height 400]))
;; 垂直面板
(define vpanel
(new vertical-panel%
[parent frame]
[alignment '(center center)]))
;; 水平面板
(define hpanel
(new horizontal-panel%
[parent vpanel]
[alignment '(center center)]))
;; 在水平面板中添加按钮
(new button% [parent hpanel] [label "按钮 1"])
(new button% [parent hpanel] [label "按钮 2"])
(new button% [parent hpanel] [label "按钮 3"])
;; 下方添加一个画布
(define canvas
(new canvas%
[parent vpanel]
[min-height 200]
[paint-callback
(lambda (canvas dc)
(send dc set-brush "blue" 'solid)
(send dc draw-rectangle 50 50 100 100))]))
(send frame show #t)
画布与绘图
#lang racket/gui
(define frame (new frame% [label "绘图示例"] [width 600] [height 400]))
(define my-canvas%
(class canvas%
(inherit get-dc)
(define/override (on-event event)
(when (send event button-down?)
(define dc (get-dc))
(define x (send event get-x))
(define y (send event get-y))
(send dc set-brush (make-object color% (random 256) (random 256) (random 256)) 'solid)
(send dc draw-ellipse (- x 10) (- y 10) 20 20)))
(super-new)))
(define canvas
(new my-canvas%
[parent frame]
[paint-callback
(lambda (canvas dc)
(send dc set-background "white")
(send dc clear))]))
(send frame show #t)
点击画布任意位置,会绘制一个随机颜色的圆形。
菜单和对话框
#lang racket/gui
(define frame (new frame% [label "菜单示例"] [width 400] [height 300]))
;; 菜单栏
(define menu-bar (new menu-bar% [parent frame]))
;; 文件菜单
(define file-menu (new menu% [label "文件"] [parent menu-bar]))
(new menu-item%
[label "打开..."]
[parent file-menu]
[callback
(lambda (m e)
(define path (get-file))
(when path
(printf "选择了文件: ~a\n" path)))])
(new separator-menu-item% [parent file-menu])
(new menu-item%
[label "退出"]
[parent file-menu]
[callback (lambda (m e) (send frame show #f))])
;; 帮助菜单
(define help-menu (new menu% [label "帮助"] [parent menu-bar]))
(new menu-item%
[label "关于"]
[parent help-menu]
[callback
(lambda (m e)
(message-box "关于" "Racket GUI 示例程序 v1.0"))])
(send frame show #t)
事件处理模型
Racket GUI 使用回调函数处理事件:
| 事件类型 | 触发条件 |
|---|---|
| button% | 按钮点击 |
| text-field% | 文本变化 |
| canvas% | 鼠标/键盘交互 |
| timer% | 定时触发 |
;; 定时器示例
(define timer
(new timer%
[interval 1000] ; 每秒触发一次
[notify-callback
(lambda ()
(printf "Tick: ~a\n" (current-seconds)))]))
打包应用
使用 raco exe 将 Racket GUI 程序打包为可执行文件:
# 创建可执行文件
raco exe --gui my-app.rkt
# 生成独立分发的目录
raco dist my-app-dist my-app.exe
这样生成的应用可以在没有 Racket 运行时的机器上运行。