EasyFlow系 列 五
TK程 式 库 简 介

本 期 开 始 要 连 续 二 期 来 介 绍 如 何 将 TK整 合 进 应 用 程 式 中 , 让 EasyFlow原 本 以 命 令 列 模 式 为 主 的 系 统 可 使 用 视 窗 介 面 。 这 期 先 要 介 绍 TK这 个 程 式 库 的 使 用 方 法 , 下 一 期 再 介 绍 如 何 将 它 整 合 入 EasyFlow中 , 并 完 成 一 个 简 单 的 使 用 者 介 面 以 代 替 原 先 命 令 列 的 选 项 。

王 佑 中

 近 年 来 TCL/TK逐 渐 在 视 窗 介 面 建 立 工 具 中 取 得 一 定 的 地 位 。 主 要 原 因 是 它 非 常 容 易 使 用 及 上 手 , 一 个 有 经 验 的 UNIX程 式 师 可 以 在 一 个 小 时 内 学 会 TCL/TK的 语 法 , 而 在 数 小 时 内 建 立 第 一 个 程 式 , 一 个 星 期 内 就 可 用 它 来 增 进 工 作 生 产 力 。

  本 文 用 意 就 在 提 供 一 个 快 速 方 法 为 已 经 了 解 TCL语 法 的 人 快 速 地 简 介 整 个 TCL /TK的 使 用 方 法 , 最 後 并 提 出 一 个 简 单 的 范 例 说 明 TCL/TK在 实 际 使 用 上 的 状 况 , 以 做 为 下 一 期 TK在 EasyFlow中 的 应 用 基 础 。

TK中 有 些 什 麽

  TCL在 设 计 时 的 目 的 就 是 做 为 任 何 一 个 系 统 的 巨 集 语 言 , 很 多 应 用 程 式 都 需 一 个 巨 集 语 言 。 但 对 很 多 应 用 程 式 而 言 , 自 己 建 立 一 个 巨 集 语 言 实 在 是 太 复 杂 的 一 件 事 , TCL以 程 式 库 的 形 式 出 现 , 且 它 的 架 构 可 以 让 程 式 师 很 容 易 地 为 它 加 入 新 的 命 令 , 故 很 多 系 统 , 尤 其 是 非 商 业 系 统 都 使 用 它 做 为 内 建 巨 集 。

  TK实 际 上 就 是 一 个 外 观 上 很 像 Motif的 X程 式 库 , 不 过 它 并 不 是 建 立 在 X Toolkit上 , 而 是 直 接 使 用 Xlib来 完 成 所 有 的 功 能 。 所 以 直 接 使 用 它 并 不 是 一 件 容 易 的 事 , 而 这 也 不 是 它 原 先 的 目 的 。

  TK一 开 始 便 和 TCL结 合 , 使 用 TCL来 设 定 每 一 个 萤 幕 物 件 的 属 性 。 一 个 使 用 者 介 面 的 设 计 通 常 需 要 不 少 尝 试 错 误 的 过 程 , 所 以 一 个 像 TCL般 直 译 式 的 语 言 便 很 适 合 做 这 件 事 。

  TK在 使 用 上 很 有 物 件 导 向 的 味 道 , 虽 然 TCL/TK并 不 是 一 个 物 件 导 向 式 的 发 展 环 境 。 TK程 式 库 为 每 一 个 萤 幕 物 件 , 如 按 键 功 能 表 等 都 维 护 了 一 份 属 性 资 料 , 这 些 资 料 可 能 是 由 程 式 师 用 TCL命 令 加 以 设 定 , 但 大 多 数 是 由 TK的 设 计 者 给 定 一 个 合 理 的 数 值 。 程 式 师 只 需 要 改 变 需 要 的 部 份 , 而 不 必 巨 细 靡 遗 地 设 定 每 一 个 参 数 。

  TK把 所 有 的 萤 幕 物 件 都 放 在 一 个 树 状 结 构 中 , 但 不 要 把 它 和 物 件 导 向 式 语 言 中 的 阶 层 树 搞 混 , 虽 然 它 们 在 功 能 上 有 些 许 类 似 , 但 它 们 是 完 全 不 相 干 的 。 在 一 个 GUI介 面 上 , 我 们 常 用 阶 层 的 方 式 组 织 萤 幕 上 众 多 的 物 件 , 一 个 档 案 选 择 器 可 能 包 含 了 一 个 标 签 (Label), 二 个 列 表 (Listbox)及 一 个 输 入 栏 位 (Entry)。 也 许 还 有 几 个 如 OK、 Cancel等 的 按 键 。 标 签 和 输 入 栏 位 常 是 同 一 个 父 物 件 的 子 代 , 二 个 列 表 可 能 是 同 一 组 , 而 其 他 的 按 键 可 能 是 同 一 组 。 这 里 的 分 组 常 是 依 据 {\bf{在 萤 幕 上 的 相 关 位 置 }}来 分 组 , 和 实 际 上 的 功 能 可 能 不 太 有 关 系 。 如 输 入 栏 位 的 值 可 能 决 定 列 表 内 容 , 但 它 们 并 不 是 分 成 一 组 。 这 点 在 最 後 范 例 中 将 可 看 得 更 清 楚 。

TK提 供 了 我 们 下 列 的 物 件 :


        ● 标 签 (Label)

        ● 按 键 (Button)

        ● 检 查 盒 (Checkbutton)

        ● 选 择 钮 (Radiobutton)

        ● 列 表 (Listbox)

        ● 输 入 栏 位 (Entry)

        ● 功 能 表 (Menu)

        ● 文 字 编 辑 区 (Text)

        ● 刻 度 (Scale)

        ● 卷 轴 (Scrollber)

        ● 画 布 (Canvas)

  在 这 里 我 很 难 为 各 位 介 绍 每 一 个 物 件 实 际 如 何 使 用 , 所 以 只 好 请 各 位 自 己 去 看 书 。 下 面 数 节 将 分 别 介 绍 如 何 建 造 、 组 合 和 应 用 这 个 物 件 而 完 成 一 个 使 用 者 介 面 。

如 何 创 造 一 个 物 件

  在 TCL/TK中 增 加 一 个 物 件 是 一 件 很 简 单 的 事 , 如 果 你 有 使 用 C为 任 何 一 种 视 窗 系 统 写 程 式 的 经 验 , 你 更 会 有 深 刻 的 体 验 。 基 本 上 , 下 面 的 命 令 就 是 最 简 单 的 方 法 :


#----- t1.tcl ------

button .b -text “ button1” 

pack .b

#----- end of file -

图 一 、t1.tcl 的 结 果

  这 个 命 令 建 造 了 一 个 名 叫 {\bfseries{.b}}的 物 件 , 它 是 一 个 按 键 。 你 可 以 用 wish这 个 命 令 来 执 行 它 。


# wish -f t1.tcl

  看 到 了 吗 ? 很 简 单 是 吧 , 创 造 一 个 {\bfseries{简 单 }}的 使 用 者 介 面 原 本 就 不 应 是 很 困 难 的 事 , 事 实 上 应 该 比 用 {\bfseries getchar\&printf}来 得 简 单 的 多 , 只 是 要 用 对 工 具 而 已 。

  t1.tcl中 第 一 个 命 令 在 系 统 中 增 加 一 个 叫 .b的 按 键 , 但 此 时 在 萤 幕 上 还 看 不 到 任 何 效 果 。 我 们 必 须 使 用 {\bfseries{pack}}这 个 命 令 将 .b放 到 萤 幕 上 , pack会 为 .b在 萤 幕 上 安 排 适 当 位 置 。 但 它 是 如 何 决 定 的 呢 ? 基 本 上 , TK有 二 个 不 同 的 方 法 来 决 定 物 件 的 位 置 , 它 们 分 别 对 应 到 二 个 不 同 的 命 令 上 。

  第 一 种 是 直 接 用 座 标 位 置 来 决 定 , 这 种 方 法 和 一 般 在 MS-Windows使 用 的 相 似 。 但 在 TCL/TK中 比 较 不 鼓 励 使 用 这 种 方 法 , 所 以 後 面 我 将 不 再 多 做 介 绍 。

  第 二 种 方 法 就 是 前 面 提 到 的 pack命 令 , 它 基 本 上 使 用 的 方 法 很 像 在 排 七 巧 盘 一 样 。 每 一 个 物 件 可 看 成 是 一 块 积 木 , 而 视 窗 便 像 是 一 个 放 积 木 的 盒 子 。 一 块 放 进 盒 子 时 可 以 放 在 上 下 左 右 边 上 , 第 二 个 物 件 放 进 时 就 不 可 占 到 原 先 物 件 占 去 的 位 置 。 如 果 二 个 物 件 都 像 往 左 边 排 , 那 结 果 就 是 二 个 物 件 排 排 站 。 用 文 字 很 难 把 这 些 东 西 说 清 楚 , 大 家 一 起 来 和 我 做 一 些 实 作 吧 。


--------- t2.tcl --------------

button .b1 -text “ button 1” 

button .b2 -text “ button 2” 

pack .b1 -side left

pack .b2 -side right

-------------------------------

图 二 、t2.tcl 的 结 果

  然 後 用 wish去 执 行 它 。 现 在 你 可 以 在 萤 幕 上 看 到 二 个 按 键 了 吧 !

  在 上 面 的 范 例 中 pack後 面 多 了 二 个 参 数 {\bfseries{-side left}}, 第 一 个 我 们 称 为 选 项 名 称 (Option Item), 第 二 个 称 为 选 项 内 容 (Option Context)。 虽 然 并 没 有 任 何 原 因 限 制 , 但 习 惯 上 选 项 名 称 在 TCL的 惯 例 上 用 “ -” 开 头 。 “ -side” 的 用 处 是 告 诉 系 统 要 把 物 件 放 在 视 窗 的 那 一 边 , 如 上 面 我 们 想 要 的 结 果 是 .b1放 在 左 边 , .b2 放 在 右 边 。

  试 试 看 把 萤 幕 上 的 视 窗 放 大 一 下 , 这 时 二 个 按 键 分 别 位 於 视 窗 左 右 二 边 的 中 央 。 记 住 这 个 结 果 。 接 下 来 我 们 修 改 一 下 输 入 档 :


---------- t3.tcl ----------

button .b1 -text “ button 1” 

button .b2 -text “ button 2” 

pack .b1 .b2 -side left

----------------------------

图 叁 、t3.tcl 视 窗 放 大 後 的 结 果

  我 们 把 二 个 都 放 到 左 边 去 , 不 过 实 际 出 来 的 结 果 好 像 并 没 有 什 麽 不 同 。 当 你 放 大 整 个 视 窗 後 , 就 可 以 看 到 不 同 之 处 了 , 此 时 二 个 按 键 都 位 於 视 窗 的 左 边 , 整 个 右 边 是 很 大 的 一 块 空 白 。 这 是 因 为 我 们 的 要 求 是 把 二 个 按 键 都 放 在 视 窗 的 左 边 , 所 以 右 边 自 然 就 留 下 了 一 个 很 大 的 空 白 。

  所 以 经 由 指 定 物 件 放 在 视 窗 的 上 下 左 右 边 就 可 以 组 合 成 任 意 的 对 话 盒 出 来 了 。 不 过 各 位 要 注 意 , 放 的 次 序 是 很 重 要 的 一 件 事 , 例 如 下 面 的 二 个 范 例 只 是 顺 序 调 了 一 下 , 但 结 果 就 不 一 样 了 。


button .b1 -text ‘ button 1’ 

button .b2 -text ‘ button 2’ 

button .b3 -text ‘ button 3’ 



pack .b3 -side top

pack .b1 .b2

另 一 个 范 例 ∶


button .b1 -text ‘ button 1’ 

button .b2 -text ‘ button 2’ 

button .b3 -text ‘ button 3’ 



pack .b1 .b2

pack .b3 -side top

  也 许 你 想 不 出 为 什 麽 不 一 样 , 或 者 是 和 你 想 像 的 结 果 不 同 。 这 种 结 果 , 原 先 并 不 是 十 分 的 自 然 , 它 和 TK处 理 你 给 它 要 求 的 演 算 法 有 关 。 下 一 节 中 我 将 仔 细 地 讨 论 这 个 演 算 法 , 到 时 候 你 再 回 头 看 这 个 例 子 , 想 想 为 什 麽 结 果 是 如 此 。

  这 一 节 的 最 後 我 要 介 绍 另 外 几 个 pack 的 选 项 , 在 开 始 前 先 做 一 个 简 单 的 列 表 。 (参 见 以 下 用 Tex语 法 所 写 的 程 式 )

\begin{tabular}{|l|p{15cm}|}
\hline
选 项 名 称 &说 明 \\\hline
-after window & 将 物 件 插 入 和 window同 样 的 父 视 窗 中 , 并 好 像 插 在 它 後 面 一 样 常 用 於 动 态 增 加 物 件 的 情 况 下 。 \\\hline
-anchor position & 设 定 物 件 在 分 配 到 区 域 的 位 置 。 \\\hline
-before windows & 将 物 件 插 入 和 window同 样 的 父 视 窗 中 , 并 好 像 插 在 它 前 面 一 样 。 \\\hline
-expand boolean & 当 分 物 件 分 配 到 的 区 域 大 於 物 件 的 大 小 时 是 否 要 放 大 物 件 。 如 果 选 择 不 放 大 时 则 用 -anchor的 值 决 定 放 在 区 域 的 那 一 点 上 。 \\\hline
-fill style & 设 定 当 物 件 需 要 放 大 时 如 何 去 放 大 , 预 设 是 不 放 大 。 style可 以 是 x,y,both其 中 之 一 。 \\\hline
-in window& 将 物 件 排 在 window之 中 , 如 果 没 有 设 定 则 会 依 物 件 名 称 的 路 径 放 在 其 父 视 窗 之 中 。 \\\hline
-ipadx& 在 物 件 的 横 向 上 在 物 件 内 部 加 上 一 个 间 距 , 这 会 使 物 件 看 起 来 大 一 些 。 \\\hline
-ipadx& 在 物 件 的 纵 向 上 在 物 件 内 部 加 上 一 个 间 距 , 这 会 使 物 件 看 起 来 高 一 些 。 \\\hline
-padx& 在 物 件 的 横 向 上 加 上 一 个 间 距 , 这 会 使 物 件 看 起 来 比 较 不 会 那 麽 挤 。 \\\hline
-padx& 在 物 件 的 纵 向 上 加 上 一 个 间 距 , 这 会 使 物 件 看 起 来 比 较 不 会 那 麽 挤 。 \\\hline
-side& 物 件 要 放 在 父 视 窗 的 那 一 边 。 \\\hline
\end{tabular}

  其 中 -in这 个 选 项 的 预 设 值 是 由 物 件 的 名 称 所 决 定 , 一 个 物 件 的 名 称 和 UNIX中 的 路 径 很 类 似 , 例 如 :


.selector.databox.filename

  这 个 物 件 会 被 放 在 .selector.databox这 个 物 件 的 视 窗 之 中 , 而 .selector.databox又 会 被 放 在 .selector之 中 , 而 .selector又 会 被 放 在 根 视 窗 “ .” 之 中 。 所 以 :


pack .selector.databox.filename

就 等 於 ∶


pack .selector.databox.filename -in .selector.databox

  物 件 也 未 必 一 定 要 按 预 设 动 作 进 行 , 最 常 见 的 情 况 是 , 当 我 们 为 了 想 把 几 个 物 件 放 在 一 起 时 , 我 们 必 须 把 它 们 单 独 放 在 一 个 视 窗 之 中 。 这 个 视 窗 除 了 作 为 一 个 容 器 外 , 在 逻 辑 上 并 没 有 特 别 的 意 义 , 所 以 整 个 物 件 树 通 常 不 会 写 成 ∶


frame .f

button .f.b1                                                  

button .f.b2

pack .f

pack .f.b1

pack .f.b2

而 是 ∶


frame .f

button .b1

button .b2

pack .b1 -in .f

pack .b2 -in .f

.f这 个 时 候 或 许 会 被 称 为 虚 拟 框 架 (Virtual Frame)。

如何将一个物件放置到萤幕上

  上 一 节 中 我 们 已 经 知 道 用 pack这 个 命 令 可 以 将 一 个 物 件 放 到 萤 幕 中 的 视 窗 上 , 这 一 节 中 我 将 详 细 的 说 明 TK用 来 决 定 如 何 安 排 物 件 在 视 窗 中 位 置 及 大 小 的 演 算 法 。 整 个 演 算 法 可 以 分 成 叁 个 步 骤 :

  1. 由 整 个 视 窗 的 可 用 部 份 割 出 一 块 方 型 区 域 , 这 个 区 域 根 据 使 用 者 所 设 定 的 - side选 项 由 视 窗 的 四 边 中 割 出 一 整 个 来 。 一 般 来 说 , 割 出 的 区 域 大 小 正 好 和 物 件 所 需 的 大 小 一 样 , 但 如 果 -fill,- pad -ipad有 设 定 , 则 按 设 定 分 割 。

  2. 设 定 物 件 的 大 小 , 一 般 来 说 它 和 物 件 希 望 的 大 小 一 样 。 但 是 如 果 -expand或 - ipad选 项 有 设 定 , 则 按 设 定 放 大 物 件 。

  3. 将 物 件 放 在 第 一 步 中 所 取 得 的 区 域 中 , 如 果 区 域 比 物 件 来 得 大 , 则 按 照 -anchor 的 设 定 来 放 置 物 件 。 物 件 根 据 要 求 可 以 放 在 区 域 的 上 下 左 右 四 个 角 及 中 央 。

  每 一 个 用 pack命 令 插 入 的 物 件 位 次 , 根 据 它 们 的 属 性 执 行 上 面 的 演 算 法 来 决 定 其 位 置 。 每 个 物 件 完 成 後 , 视 窗 便 缩 小 成 一 个 比 较 小 的 方 型 区 域 , 再 对 下 一 个 物 件 做 相 同 的 步 骤 。 所 以 , 你 可 以 看 见 次 序 是 非 常 重 要 的 。

  你 可 以 把 物 件 放 在 视 窗 的 四 边 , 但 是 只 有 这 样 是 无 法 得 到 很 复 杂 的 排 列 的 , 如 图 四 是 无 法 完 成 的 。 其 原 因 是 pack没 有 提 供 放 在 左 上 角 这 种 功 能 , 因 为 如 此 分 割 会 使 剩 馀 的 区 域 变 成 不 规 则 形 。

  不 过 , 这 种 效 果 还 是 可 以 做 到 的 , 就 是 在 视 窗 内 引 进 框 架 (Frame)的 观 念 。 把 上 端 的 二 个 物 件 看 成 是 一 个 物 件 的 话 , 我 们 可 以 用 放 在 上 端 的 方 法 放 在 视 窗 的 上 端 , 如 ∶


frame .f

label .la -text “ filename:” 

entry .en 

pack .la -in .f -side left

pack .en -in .f -side left -fill x

pack .f -side top

listbox .l1 

listbox .l2

pack .l1 -side left

pack .l2 -side right

  其 他 的 可 以 类 比 得 到 , 原 则 就 是 把 视 窗 中 的 区 域 分 成 一 个 一 个 方 型 区 域 , 如 图 五

如 何 将 物 件 和 外 部 程 式 连 结

  如 果 你 写 过 X Toolkit的 程 式 , 或 是 在 MS-Windows下 使 用 MFC或 OWL等 程 式 库 写 程 式 , 你 应 该 知 道 物 件 动 作 实 际 上 是 由 程 式 师 所 提 供 的 回 叫 函 数 (Callback Function)来 执 行 。 在 TK中 也 是 一 样 , TK回 叫 函 数 实 际 上 是 个 TCL程 式 。 它 们 以 下 面 的 形 式 存 在 , 例 如 我 们 定 义 一 个 按 键 的 动 作 函 数 如 :


.button .b1 -command {out_string}



proc out_string {} {

        puts “ Button is pressed\n” 

}

  其 中 我 们 用 选 项 “ -command” , 为 按 键 按 下 这 个 动 作 定 义 一 个 回 叫 函 数 {\bfseries {out_string}}。 不 同 型 态 的 物 件 有 不 同 的 回 叫 函 数 可 用 , 在 本 节 最 後 , 我 们 整 理 出 一 个 所 有 物 件 的 回 叫 函 数 的 列 表 。

  除 了 回 叫 函 数 外 , 我 们 还 对 任 何 物 件 定 义 系 结 事 件 (Event Binding)。 例 如 定 义 当 物 件 为 焦 点 时 , 万 一 某 个 按 键 出 现 时 如 何 处 理 , 如 在 一 个 输 入 栏 位 (Entry)中 按 下 (Return)键 时 如 何 通 常 代 表 输 入 完 成 , 在 一 个 档 案 开 启 对 话 盒 上 , 通 常 的 动 作 就 代 表 档 案 被 选 择 。 但 预 设 的 Entry并 不 会 做 任 何 动 作 , 此 时 我 们 就 会 用 下 列 的 程 式 来 将 (Return)按 键 事 件 系 结 到 Entry上 。


entry .filename

bind .filename 〈 ENTER)  {read_directory_context}

  当 (ENTER)键 被 按 时 , 我 们 会 执 行 一 段 TCL程 式 , 通 常 是 一 个 程 式 呼 叫 , 而 把 实 际 的 工 作 交 给 那 个 程 式 来 做 , 在 这 里 是 \verb +read_directory_context+这 个 TCL 程 式 , 它 负 责 读 入 所 有 符 合 刚 刚 输 入 的 档 名 样 式 , 并 将 它 加 入 列 表 中 。

  {\tt\bfseries{bind}}有 叁 个 参 数 , 第 一 个 是 一 物 件 名 称 , 第 二 个 是 事 件 样 式 (pattern), 最 後 一 个 是 一 个 TCL命 令 。 事 件 的 样 式 和 X中 定 义 一 样 , 可 以 由 X相 关 的 手 册 中 取 得 所 有 的 样 式 。 这 里 我 对 几 个 常 用 样 式 做 说 明 。 最 简 单 样 式 就 是 一 个 字 元 本 身 , 如 :


bind .ee a {.ee insert insert alloc}

  除 此 之 外 的 样 式 , 都 必 须 放 在 一 对 方 括 号 之 内 , 如 (RETURN)。 中 括 号 内 可 用 的 样 式 在 X中 有 详 细 的 规 定 , 其 格 式 可 由 ‘ -’ 分 成 数 个 部 份 , 最 後 一 个 部 份 必 须 能 对 映 到 X定 义 的 逻 辑 按 键 上 去 。 其 他 的 部 份 都 叫 做 修 饰 词 (Modifier), 它 们 可 以 是 :


● Button, ButtonRelease, ButtonPress

● Key, KeyRelease, ButtonPress

● Motion

● Enter, Escape

● Ctrl, Alt, Shift

● Any

● Double, Triple

  有 时 我 们 可 能 希 望 得 到 事 件 发 生 时 更 详 细 的 状 况 , TK提 供 了 一 些 预 先 定 义 的 巨 集 变 数 。 它 们 是 :

范 例 应 用 档 案 选 择 器

  看 了 上 面 的 说 明 後 , 现 在 我 们 用 一 个 常 见 的 对 话 盒 做 范 例 , 让 大 家 体 会 一 下 使 用 TCL /TK来 发 展 使 用 者 介 面 是 多 麽 容 易 的 一 件 事 。 我 们 的 目 标 是 设 计 一 个 函 数 , 让 使 用 者 由 目 前 的 档 案 系 统 中 取 得 一 个 档 案 名 称 , 为 了 简 单 起 见 , 很 多 错 误 检 查 的 动 作 都 省 略 了 。 但 即 使 是 省 略 了 这 些 动 作 , TK对 错 误 状 况 预 设 的 处 理 方 式 , 往 往 也 都 令 人 还 可 以 接 受 , 只 是 比 较 难 看 而 已 。

  我 将 把 焦 点 放 在 视 觉 物 件 的 建 立 上 , 程 式 中 用 到 了 一 些 TCL的 函 数 来 由 作 业 系 统 取 得 档 案 列 表 的 程 式 将 不 多 加 介 绍 , 不 过 它 们 应 该 是 很 简 明 的 。 (此 部 份 程 式 参 见 第 22期 光 碟 片 \AUTHOR\TK\TK.TXT档 )


# ---- test procedure ------------

# uncomment below two lines for testing

#   puts [getfile .aa “ /root/*” ]

#   exit

# ---- end of test procedure ------

  整 个 对 话 框 如 图 六 被 分 成 叁 个 框 架 , 上 方 是 pattern的 静 态 文 字 和 栏 位 及 一 个 显 示 目 前 目 录 的 地 方 , 右 方 有 二 个 方 块 , 左 方 则 是 二 个 列 表 盒 。 所 以 你 可 以 看 到 在 程 式 中 , 我 们 产 生 了 二 个 额 外 的 框 架 物 件 \verb+$base.f1 $base.f2+, 它 们 的 关 系 如 图 七

  所 以 可 以 验 证 前 面 说 过 的 由 物 件 名 称 所 形 成 的 物 件 树 , 通 常 和 实 际 在 X内 物 件 的 隶 属 关 系 无 关 。

  在 getfile一 开 始 先 用 传 进 的 参 数 \verb+$base+做 为 对 话 框 名 称 , 它 被 宣 告 成 一 个 toplevel物 件 。 一 个 toplevel的 物 件 可 以 被 直 接 看 成 是 一 个 独 立 的 视 窗 , TK系 统 在 一 开 始 时 会 自 动 把 ‘ .’ 设 定 成 一 个 toplevel的 物 件 。 因 为 档 案 选 择 器 是 一 个 对 话 框 , 所 以 像 上 面 程 式 的 做 法 是 很 常 见 的 做 法 , 如 此 可 以 允 许 多 个 对 话 框 存 在 而 不 相 互 干 扰 。 这 对 於 一 些 非 模 式 化 (modaless)的 视 窗 或 对 话 框 尤 其 重 要 。 因 为 如 此 做 可 以 允 许 同 一 个 函 数 被 重 复 呼 叫 。 \footnote{上 面 的 程 式 是 不 可 以 被 重 复 呼 叫 的 , 因 为 它 用 了 一 个 整 体 变 数 selected\_file, 来 记 录 选 择 结 果 。

  接 下 来 一 一 创 造 所 有 的 物 件 , 并 为 它 们 设 定 初 值 。 然 後 用 pack指 令 建 立 整 个 对 话 盒 , 藉 由 调 整 pack指 令 的 顺 序 及 参 数 , 我 们 可 以 很 容 易 地 建 立 不 同 的 介 面 格 式 。 当 你 多 练 习 几 次 後 , 你 会 发 现 用 TCL/TK来 建 立 使 用 者 介 面 是 多 容 易 的 一 件 事 , 当 然 我 是 指 建 立 介 面 本 身 而 言 , 至 於 介 面 所 代 表 的 意 义 就 不 是 同 一 回 事 了 。

  建 立 介 面 绝 对 是 一 件 容 易 的 事 , 但 传 统 的 C语 言 常 使 这 样 一 件 简 单 的 事 变 得 很 复 杂 。 也 许 这 不 能 怪 C, 视 窗 系 统 设 计 者 为 了 给 程 式 师 最 大 的 方 便 , 它 必 须 允 许 我 们 控 制 图 形 介 面 的 每 一 个 细 节 , 以 至 於 它 必 须 提 供 一 大 串 的 参 数 。

  相 反 地 , 使 用 TCL/TK就 容 易 多 了 , 我 们 只 需 设 定 不 一 样 的 部 份 , 所 有 一 样 的 部 份 都 由 TK程 式 库 代 劳 。 这 种 情 况 很 像 是 在 Delphi或 Visual Basic设 计 程 式 时 的 状 况 , 差 别 在 TK不 是 使 用 交 谈 式 的 方 法 建 立 介 面 , 而 是 由 pack指 令 来 做 。

  其 实 TCL/TK也 有 一 个 叫 XF的 交 谈 式 建 立 环 境 , 它 的 使 用 和 Visual Basic就 有 些 雷 同 了 。 不 过 , 因 为 这 个 程 式 本 身 是 用 TCL/TK写 成 的 , 其 速 度 并 非 完 全 尽 如 人 意 。 但 已 经 十 分 可 用 就 是 了 , 且 它 本 身 的 架 构 十 分 有 弹 性 , 可 以 依 需 要 而 扩 充 , 这 有 些 像 在 Visual Basic中 使 用 VBX一 样 了 。

  无 论 使 用 那 一 种 方 法 来 建 立 图 形 使 用 者 介 面 , 都 不 是 一 件 容 易 的 事 。 使 用 TCL/TK可 以 使 学 习 曲 线 比 较 平 缓 , 但 这 并 不 代 表 使 用 TCL/TK就 可 以 很 轻 易 地 建 立 一 个 好 的 图 形 使 用 者 介 面 。 唯 有 不 断 地 练 习 , 才 有 可 能 做 出 一 个 良 好 的 使 用 者 介 面 。 这 一 次 就 到 此 为 止 了 , 你 是 否 想 立 刻 去 写 一 个 TK的 程 式 呢 ? 如 果 是 , 那 作 者 这 篇 文 章 的 介 绍 就 成 功 了 。

(相 关 程 式 见 第 22期 光 碟 片 \AUTHOR\TK子 目 录 )