I am trying to create a simple form box, ultimately to place data in a database. Right now I am simply testing it with puts statements, as follows:
package require Tk
wm title . "Add"
grid [ttk::frame .c -padding "3 3 12 12"] -column 0 -row 0 -sticky nwes
grid columnconfigure . 0 -weight 1; grid rowconfigure . 0 -weight 1
grid [ttk::label .c.idlbl -width 7 -text "id"] -column 1 -row 1 -sticky we
grid [ttk::entry .c.id -width 7 -textvariable id] -column 2 -row 1 -sticky we
grid [ttk::label .c.txtlbl -text "text"] -column 1 -row 2 -sticky w
grid [ttk::entry .c.txt -width 7 -textvariable text] -column 2 -row 2 -sticky we
grid [ttk::button .c.calc -text "Add!" -command db_add] -column 1 -row 3 -sticky w
foreach w [winfo children .c] {grid configure $w -padx 5 -pady 5}
focus .c.id
proc db_add {} {
set id $::id
set text $::text
puts $id
puts $text
}
My question: why do I need to do set into another variable name, before I can do anything with the value? Why can I not just do puts $::id?
I have tried puts expr{$::id}, which gives an output like expr{Whatever Text Was Entered}, leaving me unsure why the expr does not go away. It seems my concept of variables in TCL is very murky at the moment.
You can use puts $::id, but until you have entered text into the entry fields, the variables don't exist. You can initialize them in parallel with creating the widgets, or test them for existence:
if {![info exists ::id]} {
set ::id {}
}
puts \$::id=$::id
Related
I want to create and destroy a widget with a checkbutton. The widget will be created when then checkbutton is checked and should be destroyed when the checkbutton will be unchecked. The creation works fine, but when the widget should be destroyed the error message Error: window name "ser" already exists in parent will be displayed.
package require Tk
wm title . "Some Test"
grid[ttk::frame .c -padding "3 3 12 12"] -column 0 -row 0 -sticky nwes
grid columnconfigure . 0 -weight 1; grid rowconfigure . 0 -weight 1
grid [ttk::checkbutton .c.checkSer -command createWidget \
-variable CB -onvalue 1 -offvalue 0] -column 1 -row 3 -sticky w
set CB 0
proc createWidget {} {
if {[catch {info exists $::ser} fid]} {
grid [ttk::entry .c.ser -width 12 -textvariable ser] -column 2 -row 2 -sticky we
grid [ttk::label .c.serlbl -text "Ser"] -column 1 -row 2 -sticky w
} else {
destroy .c.ser .c.serlbl
}
}
How can the widget be destroyed without this error?
The problem is your statement info exists $::ser. This tries to read the global variable ser and will then check if a variable exists with the name stored in that variable.
So you probably intended to use info exists ::ser (without the $). But that also won't work like you want. A ttk::entry widget doesn't actually create its textvariable until the user types something in the entry, and the variable doesn't get deleted when the widget is destroyed.
You will need a different method to determine whether to create or destroy the widgets. For example:
if {![winfo exists .c.ser]} {
# Create the widgets
} else {
# Destroy the widgets
}
I want to put a combobox over a frame of a tk notebook. I arrange the frame and the components using grid. When i place the combobox over the frame, the frame in the background disappears. What can be the reason for this? My code is as follows:
ttk::notebook .f.n -width 1600 -height 800
frame .f.n.f1
frame .f.n.f2
.n add .f.n.f1 -text "TabOne"
.n add .f.n.f2 -text "TabTwo"
grid .f.n -sticky news -row 0 -column 0
#Code to create a side menu
grid [frame .f.n.TabOne.m -width 200 -height 800] -sticky news -row 0 -column 0
grid [ttk::combobox .f.n.Tabone.m.d -values {"val 1" "val 2"}] -sticky news
To put a combobox within a tab's pane, you have to make it a child of the widget (usually a frame — and definitely so in your case — but not necessarily) that is the interior of the tab. Otherwise it is not inside, but rather just stacked on top.
The easiest way of getting this consistently right is to build widget names from variables that reference their parents. Idiomatically, you store the name returned by the widget construction function and then build the child names by simple concatenation, like this:
set nb [ttk::notebook .f.n -width 1600 -height 800]
set tab_one [frame $nb.f1]
set tab_two [frame $nb.f2]
$nb add $tab_one -text "TabOne"
$nb add $tab_two -text "TabTwo"
grid $nb -sticky news -row 0 -column 0
#Code to create a side menu
grid [frame $tab_one.m -width 200 -height 800] -sticky news -row 0 -column 0
grid [ttk::combobox $tab_one.m.d -values {"val 1" "val 2"}] -sticky news
i would like to know if this method is good for hide or show a widget
maybe a better method ?
thanks in advance
ttk::treeview .tree
.tree insert {} end -id "Item 1" -text "Item 1"
.tree insert {} end -id "Item 2" -text "Item 2"
.tree insert {} end -id "Item 3" -text "Item 3"
text .text -bg green
button .b -text "H" -width 10 -command {grid .text -row 0}
button .b1 -text "B" -width 10 -command {grid .text -row 1}
wm geometry . 500x600
grid .tree -row 0 -columnspan 2 -sticky nsew
grid .text -row 1 -columnspan 2 -sticky nsew
grid .b -row 2 -sticky nsw
grid .b1 -row 2 -column 1 -sticky nse
grid columnconfigure . 0 -weight 1
grid rowconfigure . 0 -weight 1
You can use grid remove. Change the buttons to:
button .b -text "H" -width 10 -command {grid remove .tree}
button .b1 -text "B" -width 10 -command {grid .tree}
Of course if you also want the text area to expand into row 0, you
may also want to modify the text area's row.
grid remove will remember the configuration settings.
References: http://tcl.tk/man/tcl8.6/TkCmd/grid.htm
I think it is depends what you really wants. If you would like to retain the original grid configuration in order to use this widget again, you should use grid remove. But if you don't intend to use the widget after once hidden, you should use grid forget
GUI snapshot
In this code i want to move new_button to right most side.But After changing row, column,columnspan also,it stays there only. What are the changes required in code.
ttk::frame .c
.c configure -borderwidth 7 -relief groove -padding "200 25"
button .c.cancle -text cancel -command {destroy .}
ttk::label .c.l -text "yash"
ttk::checkbutton .c.one -text One -variable oe -onvalue 1
ttk::button .c.ok -text Okay -command sp12
button .c.lop -text New_button
grid .c -column 0 -row 4
grid .c.l -column 0 -row 1 -columnspan 2
grid .c.one -column 0 -row 3 -columnspan 2
grid .c.ok -column 3 -row 3 -columnspan 2
grid .c.cancle -column 9 -row 3 -columnspan 2
grid .c.lop -column 30 -row 10 -rowspan 10 -columnspan 15 -sticky w
grid can be tricky. If there are no widgets in one of the rows or columns, that row and/or column will be considered to have 0 width and/or 0 height. Thus increasing the row number and/or column number will not change anything.
In your current script, the padding to the frame prevents the widgets inside the .c grid to be near the .c border (padding adds a 'layer' of space between the border and the widgets inside it). So this is the first thing to remove. Once done, the widget will lose its size though, because the size of the widget depend on the size of the widgets inside it after all.
So a workaround here would be to define the minimum sizes:
ttk::frame .c
.c configure -borderwidth 7 -relief groove
wm minsize . 656 135 # Set a minimum size here
button .c.cancle -text cancel -command {destroy .}
ttk::label .c.l -text "yash"
ttk::checkbutton .c.one -text One -variable oe -onvalue 1
ttk::button .c.ok -text Okay -command sp12
button .c.lop -text New_button
# I cleaned up the columns
grid .c -row 0 -column 0 -sticky nsew # make it anchor all positions
grid .c.l -column 1 -row 1
grid .c.one -column 1 -row 2
grid .c.ok -column 2 -row 2
grid .c.cancle -column 3 -row 2
grid .c.lop -column 4 -row 3 -sticky se # make it anchor at south east position
# make the .c grid fit to the . window
grid columnconfigure . all -minsize 635 -weight 1
grid rowconfigure . all -weight 1
# force column before column 1 and row before row 1 to have some specific size
grid columnconfigure .c 0 -minsize 200
grid rowconfigure .c 0 -minsize 30
# make the last cell fill any spaces after it, if available
grid columnconfigure .c 4 -weight 1
grid rowconfigure .c 4 -weight 1
Result:
I have a window with widgets inside it. When I re-size the window manually, the widgets will scale them self when the height is reduced, but not when the width is changed or when the height is enlarged beyond the initial height. How do I make the widgets to be stack to the borders of the window?
The code for the creation of the window:
wm title $base "KitKite Sparam Viewer"
set frm_main [frame $base.main_frm]
pack $frm_main
grid [frame $frm_main.graph ] -row 1 -column 1
set g [sparam_graph_widget $frm_main.graph graph]
grid [set frm [frame $frm_main.frm]] -row 1 -column 2
#from and to frame
set from [frame $frm.from -relief ridge -bd 2]
set from_lbl [label $from.lbl -text "From:"]
set f_tbl_frm [frame $from.tbl_f]
set to [frame $frm.to -relief ridge -bd 2]
set to_lbl [label $to.lbl -text "To:"]
set t_tbl_frm [frame $to.tbl_t]
grid $from -column 1 -row 1 -sticky nwe
grid $from_lbl -row 1 -sticky nsew
grid $f_tbl_frm -row 2 -sticky nsew
grid $to -column 2 -row 1 -sticky nwe
grid $to_lbl -row 1 -sticky nsew
grid $t_tbl_frm -row 2 -sticky nsew
set from_t [sparam_table_widget $f_tbl_frm f_tbl]
set to_t [sparam_table_widget $t_tbl_frm t_tbl]
set data [frame $frm.data]
set data_lbl [label $data.lbl -text "Choose data type to show"]
set isi [checkbutton $data.cb_isi -variable cb(isi) -command [list __sp_data_changed isi $g] -text ISI ]
set xt [checkbutton $data.cb_xt -variable cb(xt) -command [list __sp_data_changed xt $g] -text XT ]
set ref [checkbutton $data.cb_ref -variable cb(ref) -command [list __sp_data_changed ref $g] -text Reflection]
set conf_button [button $data.bt_conf -text "Configure connections" -command [list __sp_configure_datapath]]
grid $data -column 1 -row 2 -columnspan 2 -sticky new
grid $data_lbl -column 1 -row 1 -columnspan 2 -sticky nsew
grid $isi -column 1 -row 2 -sticky nsw
grid $xt -column 1 -row 3 -sticky nsw
grid $ref -column 1 -row 4 -sticky nsw
grid $conf_button -column 2 -row 2 -rowspan 3 -sticky nsew
grid rowconfigure $frm 1 -weight 4 -uniform 1
grid rowconfigure $frm 2 -weight 1 -uniform 1
grid rowconfigure $frm_main 1 -weight 5 -uniform 1
$base is the name of the window created using toplevel
sparam_graph_widget and sparam_table_widget are procedures that create and place inside the frame given to them custom widgets of a graph and a table (accordingly)
In order for at least one widget to expand to consume the space, you need to set at least one column to have a non-zero weight.
grid columnconfigure $containerWidget $someWidgetOrIndex -weight 1
Note that once you do that, that column preferentially deals with all the size changes in the horizontal direction. You can adjust this by setting multiple columns to have non-zero weights, and give different columns different weights (-weight 2 will receive twice as large changes as -weight 1).
You might also need to adjust the options used to pack the outer frame. Debug by setting different frames to different colors so you can see what's going on…