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表单中正常工作。
实施它的正确方法是什么?
我找到了一种定义过程的方法,该过程可以按照我想使用的方法来使用:
(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 panel或message,因为它们的范围是过程。