球拍GUI标签面板动态内容

Zel*_*ahl 5 user-interface tabpanel racket

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

这是我已经拥有的代码:

#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)
Run Code Online (Sandbox Code Playgroud)

这里的问题是,tab-panel尽管(自然地)仅选择了一个选项卡,但最初的两个子项都是可见的。当我更改选项卡时,该行为由窗体内的lambda纠正case

但是,我不能简单地给那些panel设置为子级的s,parent因为球拍会告诉我我需要指定所需的初始参数parent。这意味着它们将最初添加到中tab-panel。是否有必要创建panels,然后再次将其从中删除tab-panel?那看起来有点脏。我认为可能有更好的方法。

我已经尝试过动态创建面板,如在该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))
Run Code Online (Sandbox Code Playgroud)

可以如下使用:

(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)))]))]))
Run Code Online (Sandbox Code Playgroud)

但是我不明白此过程和另一个带有let表达式的过程之间的区别是什么,这种方法的另一个问题是,我以后不能修改created panelmessage,因为它们的范围是过程。