Merci pour l'aide.
Avant tout, un simple avis personnel: sans denigrer l'interet et la
valeur des outils de design d'interface graphique tels que VisualTcl, je
pense qu'il est preferable la plupart du temps (et surtout quand on
(re)decouvre Tcl/Tk) de decrire ses interfaces "a la main". Le plus
souvent, les widgets a utiliser peuvent etre testes en mode interactif,
la logique des gestionnaires d'arrangement des fenetres (pack, grid,
place) puissante et rapidement comprehensible, et surtout on conserve la
maitrise et comprehension totale du code produit. C'est d'autant plus
vrai que l'interface generee est destinee a des devices par nature tres
differents (taille de l'ecran, affichage d'un seul toplevel a la fois)
d'un desktop, pour lequel ils ont ete penses a l'origine.
En corollaire a ces arguments, l'utilisation des BWidgets dans le code
produit par VisualTcl n'est pas le meilleur choix pour l'execution
ensuite sur PDA/Smartphone. BWidgets est puissant et tres utile (m'en
sert depuis tres longtemps, dans nombre de mes codes), mais quitte a
debuter en Tcl/Tk, et developper pour cibles embarquees, mieux vaut tres
certainement preferer les solutions natives, pereine (Tile sera partie
integrante de Tk 8.5), plus rapides et deja embarquees dans eTcl, que de
recourir involontairement a des solutons externes, fortes consommatrices
de memoire precieuse sur ce type d'appareil, et moins veloce (ce qui se
ressent sur un smartphone a 100Mhz).
Bon, ca c'est pour l'opinion personnelle :-) mais temps de repondre qd
meme aux questions posees:
> - la première est simple : quand je lance mon appli sur mon pocket
> elle démarre, le menu s'affiche mais pas le premier écran.... Que
> faut-il faire ?
- faudrait voir le code produit par VisualTcl. Essayer d'ajouter:
# Si un "wm withdraw" ou "wm iconify" a ete issu prealablement
wm deiconify .
# L'appication doit etre celle de tete
raise .
# un petit helper est disponible sous eTcl pour redimensionner la
# fenetre principale en tenant compte de l'etat du SIP (le clavier
# logiciel), la resolution de l'ecran, etc... Le catch est pour ignorer
# l'erreur qd on execute le code sur une machine de bureau
catch {::etcl::autofit .}
> - la deuxième, j'ai mis le widget notebook dans mon programme et etcl
> me dit que le package BWidget n'est pas présent... Comment faut-il
> faire pour le mettre en place ?
- Pour installer BWidget, puisque c'est un package excrit en Tcl
uniquement (vs. une extension C), il suffit de recopier la distribution
dans un endroit recherche par Tcl en standard (voir la variable
auto_path). eTcl reconnait le chemin <repertoire de l'exe>/lib comme un
de ses repertoire. En outre, petite cerise sur le gateau, ce repertoire
peut etre zippe et seul le zip peut etre copie dans ce repertoire. Il
sera automatiquement monte au demarrage de eTcl, et le repertoire ou il
sera monte ajoute a la variable auto_path.
Voila, j'espere que ca aide. Bonne continuation avec (e)Tcl/Tk.
Eric
-----
Eric Hassold
Evolane - http://www.evolane.com/
Donc je vais faire l'essai pour Bwidget aec la procédure que tu
m'indiques, et pour le problème de l'écran qui ne s'affiche pas, je
vais regarder mon code.
Merci pour l'aide
Ci-dessous le code généré par visual tcl (désolé un peu long) :
#!/bin/sh
# the next line restarts using wish\
exec wish "$0" "$@"
if {![info exists vTcl(sourcing)]} {
# Provoke name search
catch {package require bogus-package-name}
set packageNames [package names]
package require BWidget
switch $tcl_platform(platform) {
windows {
}
default {
option add *ScrolledWindow.size 14
}
}
package require Tk
switch $tcl_platform(platform) {
windows {
option add *Button.padY 0
}
default {
option add *Scrollbar.width 10
option add *Scrollbar.highlightThickness 0
option add *Scrollbar.elementBorderWidth 2
option add *Scrollbar.borderWidth 2
}
}
}
#############################################################################
# Visual Tcl v1.60 Project
#
#################################
# VTCL LIBRARY PROCEDURES
#
if {![info exists vTcl(sourcing)]} {
#############################################################################
## Library Procedure: Window
proc ::Window {args} {
## This procedure may be used free of restrictions.
## Exception added by Christian Gavin on 08/08/02.
## Other packages and widget toolkits have different licensing
requirements.
## Please read their license agreements for details.
global vTcl
foreach {cmd name newname} [lrange $args 0 2] {}
set rest [lrange $args 3 end]
if {$name == "" || $cmd == ""} { return }
if {$newname == ""} { set newname $name }
if {$name == "."} { wm withdraw $name; return }
set exists [winfo exists $newname]
switch $cmd {
show {
if {$exists} {
wm deiconify $newname
} elseif {[info procs vTclWindow$name] != ""} {
eval "vTclWindow$name $newname $rest"
}
if {[winfo exists $newname] && [wm state $newname] ==
"normal"} {
vTcl:FireEvent $newname <<Show>>
}
}
hide {
if {$exists} {
wm withdraw $newname
vTcl:FireEvent $newname <<Hide>>
return}
}
iconify { if $exists {wm iconify $newname; return} }
destroy { if $exists {destroy $newname; return} }
}
}
#############################################################################
## Library Procedure: vTcl:DefineAlias
proc ::vTcl:DefineAlias {target alias widgetProc top_or_alias cmdalias}
{
## This procedure may be used free of restrictions.
## Exception added by Christian Gavin on 08/08/02.
## Other packages and widget toolkits have different licensing
requirements.
## Please read their license agreements for details.
global widget
set widget($alias) $target
set widget(rev,$target) $alias
if {$cmdalias} {
interp alias {} $alias {} $widgetProc $target
}
if {$top_or_alias != ""} {
set widget($top_or_alias,$alias) $target
if {$cmdalias} {
interp alias {} $top_or_alias.$alias {} $widgetProc $target
}
}
}
#############################################################################
## Library Procedure: vTcl:DoCmdOption
proc ::vTcl:DoCmdOption {target cmd} {
## This procedure may be used free of restrictions.
## Exception added by Christian Gavin on 08/08/02.
## Other packages and widget toolkits have different licensing
requirements.
## Please read their license agreements for details.
## menus are considered toplevel windows
set parent $target
while {[winfo class $parent] == "Menu"} {
set parent [winfo parent $parent]
}
regsub -all {\%widget} $cmd $target cmd
regsub -all {\%top} $cmd [winfo toplevel $parent] cmd
uplevel #0 [list eval $cmd]
}
#############################################################################
## Library Procedure: vTcl:FireEvent
proc ::vTcl:FireEvent {target event {params {}}} {
## This procedure may be used free of restrictions.
## Exception added by Christian Gavin on 08/08/02.
## Other packages and widget toolkits have different licensing
requirements.
## Please read their license agreements for details.
## The window may have disappeared
if {![winfo exists $target]} return
## Process each binding tag, looking for the event
foreach bindtag [bindtags $target] {
set tag_events [bind $bindtag]
set stop_processing 0
foreach tag_event $tag_events {
if {$tag_event == $event} {
set bind_code [bind $bindtag $tag_event]
foreach rep "\{%W $target\} $params" {
regsub -all [lindex $rep 0] $bind_code [lindex $rep
1] bind_code
}
set result [catch {uplevel #0 $bind_code} errortext]
if {$result == 3} {
## break exception, stop processing
set stop_processing 1
} elseif {$result != 0} {
bgerror $errortext
}
break
}
}
if {$stop_processing} {break}
}
}
#############################################################################
## Library Procedure: vTcl:Toplevel:WidgetProc
proc ::vTcl:Toplevel:WidgetProc {w args} {
## This procedure may be used free of restrictions.
## Exception added by Christian Gavin on 08/08/02.
## Other packages and widget toolkits have different licensing
requirements.
## Please read their license agreements for details.
if {[llength $args] == 0} {
## If no arguments, returns the path the alias points to
return $w
}
set command [lindex $args 0]
set args [lrange $args 1 end]
switch -- [string tolower $command] {
"setvar" {
foreach {varname value} $args {}
if {$value == ""} {
return [set ::${w}::${varname}]
} else {
return [set ::${w}::${varname} $value]
}
}
"hide" - "show" {
Window [string tolower $command] $w
}
"showmodal" {
## modal dialog ends when window is destroyed
Window show $w; raise $w
grab $w; tkwait window $w; grab release $w
}
"startmodal" {
## ends when endmodal called
Window show $w; raise $w
set ::${w}::_modal 1
grab $w; tkwait variable ::${w}::_modal; grab release $w
}
"endmodal" {
## ends modal dialog started with startmodal, argument is
var name
set ::${w}::_modal 0
Window hide $w
}
default {
uplevel $w $command $args
}
}
}
#############################################################################
## Library Procedure: vTcl:WidgetProc
proc ::vTcl:WidgetProc {w args} {
## This procedure may be used free of restrictions.
## Exception added by Christian Gavin on 08/08/02.
## Other packages and widget toolkits have different licensing
requirements.
## Please read their license agreements for details.
if {[llength $args] == 0} {
## If no arguments, returns the path the alias points to
return $w
}
set command [lindex $args 0]
set args [lrange $args 1 end]
uplevel $w $command $args
}
#############################################################################
## Library Procedure: vTcl:toplevel
proc ::vTcl:toplevel {args} {
## This procedure may be used free of restrictions.
## Exception added by Christian Gavin on 08/08/02.
## Other packages and widget toolkits have different licensing
requirements.
## Please read their license agreements for details.
uplevel #0 eval toplevel $args
set target [lindex $args 0]
namespace eval ::$target {set _modal 0}
}
}
if {[info exists vTcl(sourcing)]} {
proc vTcl:project:info {} {
set base .top73
namespace eval ::widgets::$base {
set set,origin 1
set set,size 1
set runvisible 1
}
namespace eval ::widgets::$base.mes76 {
array set save {-justify 1 -text 1 -width 1}
}
namespace eval ::widgets::$base.mes77 {
array set save {-foreground 1 -highlightbackground 1 -text 1
-width 1}
}
namespace eval ::widgets::$base.ent78 {
array set save {-background 1 -relief 1 -textvariable 1}
}
namespace eval ::widgets::$base.m79 {
array set save {-activeborderwidth 1 -borderwidth 1 -tearoff 1}
namespace eval subOptions {
array set save {-command 1 -label 1 -menu 1}
}
}
set site_3_0 $base.m79
namespace eval ::widgets::$site_3_0.men80 {
array set save {-activeborderwidth 1 -borderwidth 1 -tearoff 1}
namespace eval subOptions {
array set save {-command 1 -hidemargin 1 -label 1}
}
}
set site_3_0 $base.m79
namespace eval ::widgets::$site_3_0.men81 {
array set save {-activeborderwidth 1 -borderwidth 1 -tearoff 1}
namespace eval subOptions {
array set save {-command 1 -label 1 -menu 1}
}
}
namespace eval ::widgets::$base.but84 {
array set save {-command 1 -pady 1 -text 1}
}
namespace eval ::widgets::$base.but73 {
array set save {-command 1 -foreground 1 -highlightbackground 1
-highlightcolor 1 -overrelief 1 -pady 1 -relief 1 -text 1}
}
set base .top74
namespace eval ::widgets::$base {
set set,origin 1
set set,size 1
set runvisible 1
}
namespace eval ::widgets::$base.not75 {
array set save {-height 1 -side 1 -width 1}
namespace eval subOptions {
array set save {-text 1}
}
}
set site_4_0 [$base.not75 getframe page1]
namespace eval ::widgets::$site_4_0 {
array set save {-borderwidth 1}
}
set site_4_1 [$base.not75 getframe page2]
namespace eval ::widgets::$site_4_1 {
array set save {-borderwidth 1}
}
set site_4_2 [$base.not75 getframe page3]
namespace eval ::widgets::$site_4_2 {
array set save {-borderwidth 1}
}
set site_4_3 [$base.not75 getframe page4]
namespace eval ::widgets::$site_4_3 {
array set save {-borderwidth 1}
}
namespace eval ::widgets::$base.but76 {
array set save {-command 1 -pady 1 -text 1}
}
namespace eval ::widgets::$base.but77 {
array set save {-pady 1 -text 1}
}
namespace eval ::widgets::$base.ent78 {
array set save {-background 1 -textvariable 1}
}
set base .top79
namespace eval ::widgets::$base {
set set,origin 1
set set,size 1
set runvisible 1
}
namespace eval ::widgets::$base.tre80 {
array set save {}
}
namespace eval ::widgets::$base.but81 {
array set save {-command 1 -pady 1 -text 1}
}
namespace eval ::widgets_bindings {
set tagslist _TopLevel
}
namespace eval ::vTcl::modules::main {
set procs {
init
main
}
set compounds {
}
set projectType single
}
}
}
#################################
# USER DEFINED PROCEDURES
#
#############################################################################
## Procedure: main
proc ::main {argc argv} {
}
#############################################################################
## Initialization Procedure: init
proc ::init {argc argv} {
}
init $argc $argv
#################################
# VTCL GENERATED GUI PROCEDURES
#
proc vTclWindow. {base} {
if {$base == ""} {
set base .
}
###################
# CREATING WIDGETS
###################
wm focusmodel $top passive
wm geometry $top 200x200+154+154; update
wm maxsize $top 1404 1035
wm minsize $top 104 1
wm overrideredirect $top 0
wm resizable $top 1 1
wm withdraw $top
wm title $top "vtcl"
bindtags $top "$top Vtcl all"
vTcl:FireEvent $top <<Create>>
wm protocol $top WM_DELETE_WINDOW "vTcl:FireEvent $top
<<DeleteWindow>>"
###################
# SETTING GEOMETRY
###################
vTcl:FireEvent $base <<Ready>>
}
proc vTclWindow.top73 {base} {
if {$base == ""} {
set base .top73
}
if {[winfo exists $base]} {
wm deiconify $base; return
}
set top $base
###################
# CREATING WIDGETS
###################
vTcl:toplevel $top -class Toplevel \
-menu "$top.m79" -background #990000
wm focusmodel $top passive
wm geometry $top 240x263+425+395; update
wm maxsize $top 1404 1016
wm minsize $top 104 1
wm overrideredirect $top 0
wm resizable $top 1 1
wm deiconify $top
wm title $top "ChaiMaCave - Accueil"
vTcl:DefineAlias "$top" "CMC_Accueil" vTcl:Toplevel:WidgetProc "" 1
bindtags $top "$top Toplevel all _TopLevel"
vTcl:FireEvent $top <<Create>>
wm protocol $top WM_DELETE_WINDOW "vTcl:FireEvent $top
<<DeleteWindow>>"
message $top.mes76 \
-justify center \
-text {Bienvenue dans ChaiMaCave, votre gestionnaire de cave à
vin} \
-width 161
vTcl:DefineAlias "$top.mes76" "Message1" vTcl:WidgetProc
"CMC_Accueil" 1
message $top.mes77 \
-foreground #000000 -highlightbackground #d4d4d0d0c8c8 \
-text {Etat de votre stock :} -width 141
vTcl:DefineAlias "$top.mes77" "Message2" vTcl:WidgetProc
"CMC_Accueil" 1
entry $top.ent78 \
-background white -relief ridge -textvariable "$top\::ent78"
vTcl:DefineAlias "$top.ent78" "Entry1" vTcl:WidgetProc
"CMC_Accueil" 1
menu $top.m79 \
-activeborderwidth 1 -borderwidth 1 -tearoff 1
$top.m79 add cascade \
-menu "$top.m79.men80" -command {} -label Gérer
set site_3_0 $top.m79
menu $site_3_0.men80 \
-activeborderwidth 1 -borderwidth 1 -tearoff 0
$site_3_0.men80 add command \
-command {CMC_Fiche startmodal} -hidemargin 0 -label Nouveau...
$site_3_0.men80 add command \
-command {CMC_Liste startmodal} -hidemargin 0 -label {Liste des
vins}
$site_3_0.men80 add separator \
$site_3_0.men80 add command \
-command exit -hidemargin 0 -label Quitter
$top.m79 add cascade \
-menu "$top.m79.men81" -command {} -label Statistiques
set site_3_0 $top.m79
menu $site_3_0.men81 \
-activeborderwidth 1 -borderwidth 1 -tearoff 0
$site_3_0.men81 add command \
-command {# TODO: Your menu handler here} -label {Etat du
stock}
$site_3_0.men81 add command \
-command {# TODO: Your menu handler here} -label {Réf
épuisées}
$site_3_0.men81 add separator \
$site_3_0.men81 add command \
-command {# TODO: Your menu handler here} -label {A consommer}
$site_3_0.men81 add separator \
$site_3_0.men81 add command \
-command {# TODO: Your menu handler here} -label {Par
Millesime}
$site_3_0.men81 add command \
-command {# TODO: Your menu handler here} -label {Par Couleur}
$site_3_0.men81 add command \
-command {# TODO: Your menu handler here} -label {Par Région}
$site_3_0.men81 add command \
-command {# TODO: Your menu handler here} -label {Par Pays}
$top.m79 add command \
-command {# TODO: Your menu handler here} -label ?
button $top.but84 \
-command {CMC_Fiche startmodal} -pady 0 -text Nouveau
vTcl:DefineAlias "$top.but84" "bt_nouveau" vTcl:WidgetProc
"CMC_Accueil" 1
button $top.but73 \
-command exit -foreground #ff0000 -highlightbackground
#d4d4d0d0c8c8 \
-highlightcolor #ff0000 -overrelief flat -pady 0 -relief groove
\
-text Quitter
vTcl:DefineAlias "$top.but73" "bt_quitter" vTcl:WidgetProc
"CMC_Accueil" 1
###################
# SETTING GEOMETRY
###################
place $top.mes76 \
-in $top -x 35 -y 20 -width 161 -height 46 -anchor nw \
-bordermode ignore
place $top.mes77 \
-in $top -x 10 -y 115 -width 141 -height 21 -anchor nw \
-bordermode ignore
place $top.ent78 \
-in $top -x 100 -y 160 -anchor nw -bordermode ignore
place $top.but84 \
-in $top -x 25 -y 240 -width 74 -height 21 -anchor nw \
-bordermode ignore
place $top.but73 \
-in $top -x 140 -y 240 -width 74 -height 21 -anchor nw \
-bordermode ignore
vTcl:FireEvent $base <<Ready>>
}
proc vTclWindow.top74 {base} {
if {$base == ""} {
set base .top74
}
if {[winfo exists $base]} {
wm deiconify $base; return
}
set top $base
###################
# CREATING WIDGETS
###################
vTcl:toplevel $top -class Toplevel
wm withdraw $top
wm focusmodel $top passive
wm geometry $top 240x320+403+160; update
wm maxsize $top 1404 1035
wm minsize $top 104 1
wm overrideredirect $top 0
wm resizable $top 1 1
wm title $top "Fiche Vin"
vTcl:DefineAlias "$top" "CMC_Fiche" vTcl:Toplevel:WidgetProc "" 1
bindtags $top "$top Toplevel all _TopLevel"
vTcl:FireEvent $top <<Create>>
wm protocol $top WM_DELETE_WINDOW "vTcl:FireEvent $top
<<DeleteWindow>>"
NoteBook $top.not75 \
-height 238 -side top -width 239
vTcl:DefineAlias "$top.not75" "CMCF_onglet" vTcl:WidgetProc
"CMC_Fiche" 1
$top.not75 insert end page1 \
-text Fiche
$top.not75 insert end page2 \
-text {Stock & Prix}
$top.not75 insert end page3 \
-text Producteur
$top.not75 insert end page4 \
-text Consommation
set site_4_0 [$top.not75 getframe page1]
set site_4_1 [$top.not75 getframe page2]
set site_4_2 [$top.not75 getframe page3]
set site_4_3 [$top.not75 getframe page4]
$top.not75 raise page1
button $top.but76 \
-command {CMC_Fiche endmodal} -pady 0 -text Fermer
vTcl:DefineAlias "$top.but76" "BT_FicheFermer" vTcl:WidgetProc
"CMC_Fiche" 1
button $top.but77 \
-pady 0 -text Enregistrer
vTcl:DefineAlias "$top.but77" "BT_Fiche_Enregistrer"
vTcl:WidgetProc "CMC_Fiche" 1
entry $top.ent78 \
-background white -textvariable "$top\::ent78"
vTcl:DefineAlias "$top.ent78" "Entry1" vTcl:WidgetProc "CMC_Fiche"
1
###################
# SETTING GEOMETRY
###################
place $top.not75 \
-in $top -x 0 -y 40 -width 239 -height 238 -anchor nw \
-bordermode ignore
place $top.but76 \
-in $top -x 145 -y 290 -width 74 -height 21 -anchor nw \
-bordermode ignore
place $top.but77 \
-in $top -x 20 -y 290 -width 74 -height 21 -anchor nw \
-bordermode ignore
place $top.ent78 \
-in $top -x 14 -y 10 -width 196 -height 19 -anchor nw \
-bordermode ignore
vTcl:FireEvent $base <<Ready>>
}
proc vTclWindow.top79 {base} {
if {$base == ""} {
set base .top79
}
if {[winfo exists $base]} {
wm deiconify $base; return
}
set top $base
###################
# CREATING WIDGETS
###################
vTcl:toplevel $top -class Toplevel
wm withdraw $top
wm focusmodel $top passive
wm geometry $top 240x320+476+180; update
wm maxsize $top 1404 1035
wm minsize $top 104 1
wm overrideredirect $top 0
wm resizable $top 1 1
wm title $top "Liste des Vins"
vTcl:DefineAlias "$top" "CMC_Liste" vTcl:Toplevel:WidgetProc "" 1
bindtags $top "$top Toplevel all _TopLevel"
vTcl:FireEvent $top <<Create>>
wm protocol $top WM_DELETE_WINDOW "vTcl:FireEvent $top
<<DeleteWindow>>"
Tree $top.tre80
vTcl:DefineAlias "$top.tre80" "CMCL_Liste" vTcl:WidgetProc
"CMC_Liste" 1
bind $top.tre80 <Configure> {
Tree::_update_scrollregion %W
}
bind $top.tre80 <Destroy> {
Tree::_destroy %W
}
bind $top.tre80 <FocusIn> {
after idle {BWidget::refocus %W %W.c}
}
button $top.but81 \
-command {CMC_Liste endmodal} -pady 0 -text Fermer
vTcl:DefineAlias "$top.but81" "BT_Liste_Fermer" vTcl:WidgetProc
"CMC_Liste" 1
###################
# SETTING GEOMETRY
###################
place $top.tre80 \
-in $top -x 0 -y 25 -width 241 -height 256 -anchor nw \
-bordermode ignore
place $top.but81 \
-in $top -x 90 -y 290 -width 64 -height 21 -anchor nw \
-bordermode ignore
vTcl:FireEvent $base <<Ready>>
}
#############################################################################
## Binding tag: _TopLevel
bind "_TopLevel" <<Create>> {
if {![info exists _topcount]} {set _topcount 0}; incr _topcount
}
bind "_TopLevel" <<DeleteWindow>> {
if {[set ::%W::_modal]} {
vTcl:Toplevel:WidgetProc %W endmodal
} else {
destroy %W; if {$_topcount == 0} {exit}
}
}
bind "_TopLevel" <Destroy> {
if {[winfo toplevel %W] == "%W"} {incr _topcount -1}
}
Window show .
Window show .top73
Window show .top74
Window show .top79
main $argc $argv
Merci à tous pour l'aide
"Un peu long" est un joli euphemisme ;-) Et surtout, pas le meilleur
exemple pour illustrer la simplicite et lisibilite habituellement
reconnues aux codes en Tcl/Tk.
Pas eu le temps de regarder le code plus que ca, encore moins de le
tester, mais des choses comme:
wm geometry $top 240x320+476+180;
qui trainent sont un exemple parmi tant d'autres de choses qui sont pour
le moins pas tres souhaitables pour une execution sur PDA et Smartphone
(en fait, je trouve ce genre de hard-codage de positions de fenetres pas
souhaitable ou que ce soit, mais c'est d'autant plus vrai dans ce cas,
ca positionne la fenetre tout simplement en dehors de l'ecran!).
D'autres choses, comme l'utilisation de plusieurs toplevel, bien que
supportees pa eTcl sous WinCE, se pretent mal a l'ergonomie habituelle
sous PDA.
Je ne peux que reiterer mon conseil de preferer le codage "a la main". A
mon humble avis, les qques heures passees initialement a decouvrir les
qques widgets de base (entry, label, text, menu,...) et comprendre la
mecanique de "pack" ou "grid" permettent de gagner bien plus de temps
par la suite. D'autres personnes sauront mieux que moi proposer des
liens vers des references et tutoriaux en francais. Cependant, peut-etre
que les liens disponible sur:
http://www.larochelle-innovation.com/tcltk/1140
sont un bon debut.
J'ai peut être l'air d'en rajouter une couche, mais venant de Delphi, j'ai
attaqué Tcl/Tk avec Visual Tcl... Et je m'en suis débarassé très rapidement.
S'il facilite le développement à un débutant, dès qu'on veut rentrer dans le
code, c'est incompréhensible pour le même débutant...
Un autre conseil serait d'étudier une appli simple codée à la main, par
exemple le petit éditeur de Jean-luc Devinez qui m'a permis de me mettre au
Tk "à la main":
Miko aux gros doigts