User interface Racket GUI选项卡面板“动态内容”

User interface Racket GUI选项卡面板“动态内容”,user-interface,racket,tabpanel,User Interface,Racket,Tabpanel,我正在研究用Racket开发GUI。我想创建一个带有多个选项卡的选项卡面板%。文档中说,切换tab只调用一个过程,不会自动进行内容更改。我认为这是一个非常聪明的行为,但是我在实现一个最初为空的选项卡面板时遇到了一个问题,当我选择其中一个选项卡时,它只获取内容(子项) 这是我已有的代码: #lang racket/gui (require racket/gui/base) (define nil '()) (define application-frame (new frame%

我正在研究用Racket开发GUI。我想创建一个带有多个选项卡的
选项卡面板%
。文档中说,切换tab只调用一个过程,不会自动进行内容更改。我认为这是一个非常聪明的行为,但是我在实现一个最初为空的选项卡面板时遇到了一个问题,当我选择其中一个选项卡时,它只获取内容(子项)

这是我已有的代码:

#lang racket/gui

(require racket/gui/base)

(define nil '())

(define application-frame
  (new frame%
    [label "Example"]
    [width 400]
    [height 300]))

(define menu-bar
  (new menu-bar%
    [parent application-frame]))

(define file-menu
  (new menu%
    [label "&File"]
    [parent menu-bar]))

(new menu%
  [label "&Edit"]
  [parent menu-bar])

(new menu%
  [label "&Help"]
  [parent menu-bar])

(new menu-item%
  [label "E&xit"]
  [parent file-menu]
  [callback
    (λ (m event)
      (exit nil))])

(define tab-panel
  (new tab-panel%
    [parent application-frame]
    [choices '("&Lookup" "&Training")]
    [callback
      (λ (tp event)
        (case (send tp get-item-label (send tp get-selection))
          [("&Lookup")
            (send tp change-children
              (λ (children)
                (list lookup-panel)))]
          [("&Training")
            (send tp change-children
              (λ (children)
                (list training-panel)))]))]))

(define get-lookup-panel
  (lambda (children)
    (let
      [(lookup-panel (new panel% [parent tab-panel]))]
      [(new message%
        [parent lookup-panel]
        [label "The content of the lookup panel for the lookup tab."])
      lookup-panel])))

(define lookup-panel (new panel% [parent tab-panel]))
(define lookup-panel-content
  (new message%
    [parent lookup-panel]
    [label "The content of the lookup panel for the lookup tab."]))

(define training-panel (new panel% [parent tab-panel]))
(define training-panel-content
  (new message%
    [parent training-panel]
    [label "The content of the training panel for the training tab."]))

(define status-message
  (new message%
    [parent application-frame]
    [label "No events so far..."]
    [auto-resize #t]))

(send application-frame show #t)
这里的问题是,最初
选项卡面板
的两个子项都是可见的,尽管(自然)只选择了一个选项卡。当我更改选项卡时,行为由
案例中的lambda更正

然而,我不能简单地给那些
面板
s,我将其设置为children no
parent
,因为racket会告诉我,我需要指定所需的初始参数
parent
。这意味着它们将首先添加到
选项卡面板
。是否需要创建
面板
s,然后再次从
选项卡面板
中删除它们?那看起来有点脏。我想可能有更好的办法

我已经尝试动态创建面板,如
get lookup panel
过程中所示,但在
case
表单中无法实现

正确的实施方法是什么

编辑1 我找到了一种定义过程的方法,它可以按照我想要的方式使用:

(define (get-lookup-panel4 children)
  (define lookup-panel (new panel% [parent tab-panel]))
  (define lookup-panel-message (new message% [parent lookup-panel] [label "LOOKUP"]))
  (list lookup-panel))
可按如下方式使用:

(define tab-panel
  (new tab-panel%
    [parent application-frame]
    [choices '("&Lookup" "&Training")]
    [callback
      (λ (tp event)
        (case (send tp get-item-label (send tp get-selection))
          [("&Lookup")
            (send tp change-children get-lookup-panel4)]
          [("&Training")
            (send tp change-children
              (λ (children)
                (list training-panel)))]))]))

但我不明白此过程与另一个使用
let
表达式的过程之间的区别是什么,此方法的另一个问题是,我以后无法修改创建的
面板
消息
,因为它们的范围是过程。

我在浏览器中使用的方法是有一个自定义对象列表,其中每个对象都可以根据请求提供选项卡标签,并可以请求由选项卡面板%和几个其他对象组成的对象重新读取其标签。但这可能无法解决您的问题,因为我的浏览器从不允许少于1个选项卡(关闭最后一个选项卡将关闭窗口。窗口始终以>=1个选项卡开始)。