Questions that that have been moved around recently during the "big November shuffle"

RA2 For whichever reason, MAK rushed to delete about 25 pages a few days ago instead of copying those questions to "Ask and it shall be given".

We might therefore have lost some of the formatting (bold, italics).

Nevertheless, I am putting here all the questions and answers that have been moved around recently. They are ready to be moved to any destination by anyone who wants to take this responsibility or when the Community will decide what system it wants to use (if any).

But please make sure the question is not already in the huge Ask and it shall be given. file before you move it elsewhere. If if is, it's better to use the question at Ask and it shall be given for it has the right formatting.

Thanks to all!


The following Q&As were at: Answered questions on: Advanced Tcl

Lists - The Lrange Command - Complex Data Structures Using Lists

2003/01/20

Is there a real way to do the following?

 proc lranges {list args} {

     set start 0
     set newlist {}
     foreach size $args {
         set end [expr {$start + $size - 1}]
         lappend newlist [lrange $list $start $end]
         incr start $size
     }
     if {$start <= [llength $list]} {
         lappend newlist [lrange $list $start end]
     }
     return $newlist
 }

 % lranges "1 2 3 4 5 6 7" 2 3 5
 {1 2} {3 4 5} {6 7}

I was getting tired of parsing things with continual lranges, and I kept wishing I could foreach over a however many elements I wanted to grab for the next variable instead of just one.

Not sure this has a good default behavior, and I should probably error handle non integer args.

BR 2004-01-21 - Can you give an real example of what you want to do? Are you looking for something like:

  foreach {label value} {firstname "Benny" lastname "Riefenstahl"} {
      # Do something with $label and $value
  }

sheila 2004-01-21 - I'd like to be able to do this:

  foreach {opcode control data1 data2} {01 02 89 24 35 87 52 45 38 48} {break}

opcode will be 01, control 02, data1 {89 24 35 87 52}, and data2 {45 38 48}

assuming that I know the byte count of each field. iow:

  set message {01 02 89 24 35 87 52 45 38 48}
  foreach {opcode control data1 data2} [lranges $message 1 1 5] {break}

instead of

  set opcode [lrange $message 0 0]
  set control [lrange $message 1 1]
  set data1 [lrange $message 2 6]
  set data2 [lrange $message 7 end]

There are more complicated uses (like with a byte count field, and then foreaching based on that), but is this example sufficient?

BR 2004-01-22 - To answer the original question, no I don't think there is a built-in solution for this. But if you are ok with the concept, your proc is o.k., isn't it? I personally would probably prefer to write it out as you do above, unless I have lots of repeating code in a specific module.

Notes:

In the abstract there are no "byte counts" in this, unless the numbers are byte values in your specific example. If you are starting out with binary data, you may want to consider more involved uses of binary scan. The first two items in your example results are logically lists. This will make a difference with more complicated list items. In theory Tcl is even allowed to represent these lists differently in this very example today, e.g. as {01} {02}. Although it is unlikely Tcl will ever change here, as this would expose bugs in too many applications. ;-) sheila 2004/01/22 - Thanks. I wanted to make sure I wasn't overlooking some tcl function. The reason I want the proc is that I don't like all of the hard coded numbers making my parsers unreadable. I make data structures for the commands, and then I have retrieval proc to return whatever value of the command I specify in the structure, i.e. byte length, length of a field, etc. That way I can have self-documenting code. Also, when I do pass in a value in a message that represents a byte length, and the message I'm parsing is variable length based on another value that is the number of foobar in the message. Then using the lranges command makes it a lot easier to read rather than many lrange calls for however many fields are in the fields that I'm parsing. (once I asked in the newsgroup whether there was a package anyone had written to already do this, but there wasn't.)

I suppose I make the trade off in efficiency for readability, but I don't think it will slow down the parsing enough to be a problem.

Is there a better way to do this? (am I making this question too long for this page? apologies. I could move it somewhere else.)


Tcl String Command Syntax/Usage: Concat - Subst - Args

14/Aug/2003

I am trying to define a data structure recursively and can't get it to work.

Any suggestions?

The idea is from: http://users.pandora.be/koen.vandamme1/papers/tcl_fileformats/tcl_fileformats.html

I would expect "A=atts" I would expect "B={atta bttb} {cttc dttd}" Then I would expect "A=pins" I would expect "B={pin4 four} {pin5 five}"

I do not get that. I have also tried numerous other things like concat, subst, etc... to no avail.

   proc mycommand { args } {

    foreach { a b } [concat $args] {
        puts "A=$a"
        puts "B=$b"
    }
   }

   mycommand {
    atts {
        { atta bttb }
        { cttc dttd }
    }

    pins {
        { pin4 four }
        { pin5 five }
    }
   }

tje Aug 20 2003 - Try this:

    proc mycommand {in} {foreach {a b} $in { puts "A=$a" ; puts "b=$b" } }

Remember that args is a special argument that wraps multiple arguments into one.


The following Q&As were in: "Answered Questions on Basic TCL

Why Does The Last Line Of Standard Output Sometimes Disappear?

(18/11/3) puts -nonewline

This is so simple it's embarrasing. I have a library routine

 proc warn {message} {
    puts "WARNING: $message"
    puts -nonewline "Continue? (y/N):"
    gets stdin a

...etc. The problem is that the "Continue" message does not appear until I press return...

RS stdout is flushed on newline - or explicitly by

 flush stdout

What's The Difference Between "==" And "Eq"?

MG April 22nd 2004 - Out of pure curiousity, what (if anything) are the pros and cons of using these different checks in an if {} statement?

  if { $str1 == $str2 } { # do something }
  if { $str1 eq $str2 } { # do something }
  if { [string equal $str1 $str2] } { # do something }

Peter Newman 26 April 2004: I have a Perl background; so have always assumed that "==" is for numbers and "eq" is for strings. So:-

 if { "01" == "1" } should return TRUE, and;
 if { "01" eq "1" ) should return FALSE.

But looking at the expr manpage, who knows? And I'm too lazy to fire up wish and check it out. But I always code on that assumption, and haven't yet encountered anything that suggests it's wrong. Also, I think "eq" is relatively new (Tcl 8.3 for example). So perhaps that explains the apparently redundant string equal $str1 $str2. But don't quote me on any of this. MG Apr 28 2004 - I just checked that in wish, and it seems you're absolutely right. Thanks for the help :)


Did You Forget "Package Require"?

I'm using the BatteriesIncluded Tcl/Tk for Jaguar, so this is Macintosh Tcl/Tk. According to the docs there's a resource keyword. However, I can't seem to use it. wish and tclsh don't seem to know anything about a "resource" keyword. I want access to the resource fork of files, if only simply to get a hold of the resource data in a block rather than as types and ids. How? BMA

Lars H: Under OS X the resource command is in the TclResource package, which was new in the 8.4.5 BI distribution. Try

  package require TclResource

Why Can't I Execute Tcl Commands From The DOS Prompt?

masCh: Hola. I downloaded the file lpttcl.zip, there's 2 files in it. The .sys file went into e:\windows\system32 and the .dll file is on my desktop. How do I run the program? I went to dos prompt and typed "load lpttcl" and all it said is "'Load' is not recognized as an internal or external command, operable program or batch file" Please help.

MG July 20th 2004 - Basically, the DOS prompt isn't what you want :) You need to be running the Tcl interpreter; there are two ways you can do that. (Assuming you're on MS Windows 95 or higher,) you can either launch 'tclsh' - either from the DOS prompt, or Start->Run and enter 'tclsh'. Then, with the prompt that comes up, use 'load lpttcl'. Or, you can run wish (which is, basically, tclsh but without the prompt, and with the Tk package loaded, so you can use a GUI). The best way to do that is to create a file called 'console.tcl', which has the single line:

 console show

and double-click it (when you install ActiveTcl, .tcl files are automatically associated with wish). Then you can enter commands into the console window that comes up.


How Do I Search Strings Using Regular Expressions?

Adi: Hi. How can I use regular expressions in searching the index of a pattern in strings. e.g. something like:-

 string first {^fg[a-zA-Z]* $} tipfgt

where

 {^fg[a-zA-Z]* $}

is a regular expression, and the string is tipfgt. Thanks

July 15 04 - MG Try this...

 set str tipfgt
 regexp {(fg[a-ZA-Z]*)} $str someVar
 string first $someVar $str

How Do I Run A Second Tcl Script - From My First Tcl Script - As A Separate Process? How Do I Start Another Copy Of My Tcl Program - As A Separate Stand-Alone Process? Exec Is Too Confusing - Is There An Alternative? 06/29/2004

Problem with command.exe /c start on Windows NT. I have a wish application that opens a ct data set and displays it. At the top of the main window I have a File menu with an option "new." When I execute this command I want a completely separate process to begin (exactly as if i started a different instance of the dos prompt and began my program again--using a wrapped wish interpreter with the Visualization Toolkit.) I don't want to use the -exec command (I don't think.) I have read so many different "how to" pages but have not been able to put the right combination of answers together. Help please! -kate

Peter Newman 30 June 2004: exec totally sucks on Windows. But the answer is the winutils shell and launch commands. These are so excellently brilliant it's just not funny. But whether they'll work on NT, I don't know (the docs don't say either way). But I think so.

MG - exec isn't so bad in my opinion, especially if you want/need to do it without any extensions for some reason. The code (in 8.4) would be this, I believe:

 set path [file attributes "c:/directory/your file.tcl" -shortname]
 eval exec [auto_execok start] $path &

hi, in 02/19/2004 I asked for saving contents of canvas-widgets. follwing lines should help, but it doesn't:

 package require Img
 ...
 set im [image create photo -format window -data .canvas]
 $im write mycanvas.gif -format GIF

Interpreter says 'couldn't recognize image data'. Interpreters I checked out are wish82.exe and itkwish31.exe running under XP.

 package require base64
 package require Img

 canvas .cv
 pack .cv

 proc inlineGIF {img {name ""}} {
    set f [open $img]
    fconfigure $f -translation binary
    set data [base64::encode [read $f]]
    close $f
    if {[llength [info level 0]] == 2} {
        set name [file root [file tail $img]]
    }
    set image [image create photo [list $name] -data {\n$data\n}]
    .cv create image 32 32 -image $image
 }

 inlineGIF ./test.gif testgif

What is the problem? Thanks for all answers!

MG Apr 30th 2004 - As long as you have a window called .canvas, the first piece of code should work fine. At a glance, so should your second; if all you're doing with your $data variable is using it to create an image, though, why not simply use...

  canvas .cv
  pack .cv
  .cv create image 32 32 -image [image create photo testgif -file ./test.gif]

Data will produced in a canvas-widget. (e.g. barcode). Another application for printing labels only can handle .GIF-Files. So I need a possibility to create a GIF-Files from Canvas-Content to print it later ...


on 17/08/2004 How can I see the value of some tcl environment varialbe at tcl prompt which I set through C program (using Tcl_Setvar)

Manu

17/8/04 MG - Looking at the man page for Tcl_SetVar, it looks as if, if you did...

  Tcl_SetVar('','somevar','value')

In your C code, then you could (in your Tcl code) call the variable with either of

  $somevar
  set somevar

With '$somevar' and 'set somevar' being the equiv. of the C Tcl_GetVar() function, and 'set somevar value' the equiv. of the C Tcl_SetVar().


The following Q & As were at "Answered questions on the TCL GUI"

How Do I Maximize/Zoom A Window?

(15/1/04) Hi all, does anyone know what is the TCL command for maximizing a window? I prefer not to use the wm geometry, since I wish the window to spread on the whole screen. Please send your reply to [email protected] 10x, Asi

FW: (also sent by email) Maximizing is discussed at Maximizing a toplevel window. wm state . zoomed is the standard command and works fine on Windows and (I think) Mac, but some window managers don't support it and you need to resize the window instead. That page provides commands that'll do it for you. If you're not targeting UNIX, of course, you can just do wm state . zoomed but you might as well.


How Do I Enable/Disable Parts Of My GUI?

Oct 11, 2004

Hi,

Does anyone know hot to enable/disable parts of a GUI being created in tk, based on user input on the same screen. What I mean is, I have all the frames created in a single window, and want to enable some frames as and when a user requires that option. For example, I have an option menu (tk_optionMenu) with 2 values, asking the user if he wants random numbers to be used. If he does, then I want the frame with the options of the type of random numbers to be enabled, otherwise, I want it to be disabled. Pls help. I can't seem to find anyway of doing this.

Thanks

GPS

Oct 11 2004 - MG You can watch the variable assigned to the tk_optionMenu via trace, and enable/disable your GUI when it changes. For instance...

  pack [frame .l] -side left
  pack [label .l.l -text "Random number?"] -side left
  pack [tk_optionMenu .l.m ranNum "Yes" "No"] -side left
  proc enableGUI {{args ""}} {
    global ranNum

    if { $ranNum == "Yes" } {
         # $gui configure -state normal
       } else {
         # $gui configure -state disabled
       }
  };# enableGUI
  trace add variable ranNum write enableGUI

Oct 12 2004 - Thanks a lot, MG. This piece of code is exactly what I needed. GPS


How Do I Detect When The Value Of An Entry/EntryField Type Widget Changes?

CT - Hi, I am having trouble with the 'entryfield' itk widget. I am trying to catch when the widgets value changes. So far I have been using the -validate command to notify when the field changes and this works fine unless you go straight into the field and paste or select some or all of the data and use the 'del' key to delete it. Somehow the -validate command is not picking this up and therefore not giving me the notification I need. I have accessed the underlying 'entry' component to use -validate all and -validatecommand but this fires an event even when I am initially setting the field which is undesirable. The -validate from the higher level of the itk widget was perfect until I discovered that it just completely ignores certain update events like pasting or using the 'del' key.

Anyone have any ideas on this please? Or any ideas on how I might be able to get a reliable notification of when the user changes the contents of the entry widget? Thanks in advance. - CT

CT * EDIT * No worries, I solved the problem by completely reworking it with a <KeyRelease> binding. I wanted to avoid this for other reasons but they were unfounded, so no problems now... - CT


Why Do Changes I've Made To The Screen Not Appear #1?

2004/09/21 pcor

Platform: Mandrake Linux 9.2

Interpretor: tixwish8.1.8.4

I have been trying to use a canvasprintdialog to print a canvas embedded in a Toplevel window but whenever the canvasprintdialog is positioned in front of the canvas I get the dialog in the printout. How can I exclude the dialog without having to position it elsewhere on the screen. I have tried hiding the dialog and using tkwait before issuing the "print" command but so far to no avail. Any help will be much appreciated. Thanks.

Peter Newman 21 September 2004: I haven't tested it, but surely:-

 ...hide the dialog ---or--- `raise canvasToplevel' ...
 update
 ...print the canvas...

would work.

pcor: Thanks Peter. Yes it does. Being a newbie with Tcl I didn't know about update.


Why Do Changes I've Made To The Screen Not Appear #2?

2004/10/22 KBH

I'm getting some behavior I don't expect and I was wondering if anyone could explain it. In the following example, I create a button and setup a binding so that it can be dragged around the window. Just before I move it to the new position, though, I move it to (0,0) so I can see what window it's over (in this case, just the main window). So I would expect it to print "." before moving the button back to the new drag location. However, it always prints ".b", as if the button were moved back before the winfo containing statement was executed. Is there something going on I don't know about?

 proc moveb { x y } {
     set lx [expr $x - [winfo rootx .]]
     set ly [expr $y - [winfo rooty .]]

     place configure .b -x 0 -y 0

     puts [winfo containing $x $y]

     place configure .b -x $lx -y $ly
 }

 wm geometry . 800x600
 place [button .b -text "Test"] -anchor c
 bind .b <B1-Motion> [list moveb %X %Y]

MG - I haven't been awake long enough to offer any code, but using a canvas widget with the button on it and moving it around that sounds like it might be a better idea. The reason it always prints .b is because, unless you click on the very last pixel at the edge of the button, moving the mouse one pixel still has the cursor over .b . If you used a canvas, you could use the find subcommand (I believe $canvas find overlapping $x $y, though might be wrong) to see which other objects/windows/widgets are at that location.

KBH - I agree that using a canvas to find the widgets underneath would be a more practical way to do what this code is attempting, but that wasn't the point of my question. I merely used this code to illustrate what seems to me to be a bug in Tk. What I expect when dragging the button is this:

move the button to 0,0 print the name of the window at x,y move the button back to x,y It seems that step 1 isn't even being executed. Even more odd, if you remove the second place, the button does get moved to 0,0 (but then it just stays there, of course).

This was the real intention of my question. To ask if there were something else I hadn't realized that was causing it. And I found out what it is. Calling update just after the first place makes it work like I expected. I forgot that during callbacks the internal state isn't necessarily consistent because Tk might not have had time yet to update things.


"Balloon Help"/"Tooltip" Type Widgets

Florian Boesch 25 June 2004: The Menu widget can be used to make popup menues. What widget can be used to make small popup ( tooltip style ) text messages? And what about popup selection-lists?

Peter Newman 25 June 2004: Most Tcl'ers seem to refer to those pop-up help widgets as "balloon help". There are just over 3 zillion such widget packages available. Search for "balloon help" on the Wiki. But the ones I've tried were all way too complicated and unreliable. People seem to put zillions of binding on them, and Tk very quickly gets confused. Try some of the others. But you might be better off to roll your own. It's only about 10 lines of code. Something like (off the top of my head):-

 proc PopupHelp_forThisButton { } {
 toplevel .myPopup ;
 wm overrideredirect .myPopup          (Gets rid of the Border)
 frame .myPopup.onePixelBlackBorder -background Black -borderwidth 1
 label .myPopup.onePixelBlackBorder.text -background LightYellow -text {Blah blah blah}
 }

Bind it so that mouse entry/exit to the button/widget you want the help for, pops up the help box, with:-

 bind .thisButton <Enter> PopupHelp_forThisButton
 bind .thisButton <Leave> {destroy .myPopup}

And you'll need to position it near whatever it gives help for with winfo, etc. Sorry it's a bit crude & incomplete. But hopefully gives you the idea. Popup selection boxes are the same. But just use a listbox instead of a label.

Florian Boesch 25 June 2004: Thank you! This gives me a good idea how to go about it. I may translate a little.

 from Tkinter import *

 def coords( geometry ):
     return map( int, geometry.split( '+' )[1:] )

 class baloon( Toplevel ):
     def __init__( self, text ):
         Toplevel.__init__( self )
         Wm.overrideredirect( self, 1 )
         self.border = Frame( self, background='black', borderwidth=1 )
         self.border.text = Label( self.border, text=text )
         self.border.text.pack()
         self.border.pack()
     def set_pos( self, x, y ):
         Wm.geometry( self, '+%s+%s'%(x,y) )
     def show( self ):
         pass
     def hide( self ):
         pass

 class application( Tk ):
     def update_baloon( self, event ):
         x, y = coords(  Wm.geometry( self ) )
         self.baloon.set_pos( event.x+x, event.y+y )
     def __init__( self ):
         Tk.__init__( self )
         self.frame = Frame( self, width=512, height=512 )
         self.frame.pack()
         self.bind("<Button-3>", self.update_baloon)
         self.baloon = baloon( 'blahblubber' )

 app = application()
 app.mainloop()

This works for me. Now what I intend to do is to use this balloons to give hints about marks in my text, given that the position of a mark in the text lies within the windows borders and the user has chosen to show the balloons (on a sidenote, can I make toplevel windows transparent?). Also I have a problem with this since on windows the balloon is spawned behind the main window, how to resolve this?

How Do I Make A Child Toplevel Pop-Up Over Its Parent?

Peter Newman 26 June 2004: To position the balloon over the main toplevel, make the balloon toplevel a child of the main toplevel. Ie:-

 toplevel .myMainToplevel
 ...
 toplevel .myMainToplevel.balloonHelp

Alternatively, use the raise command.

Toplevel Transparency

As regards toplevel transparency, see Transparent Toplevel. But that technique's not really a good solution. On Windows (95 to XP inclusive) however, transparent toplevels are a piece of cake. See the absolutely brilliant "Win32 Window Skinning" tutorial by Vander Nunes at 4. Access the Win32 API with eg; Ffidl, critcl or SWIG.

Balloon Help With Place (Instead Of Toplevels)

An alternative to the toplevel method of creating balloon help, is to simply place the label (or text or html or canvas) widget containing your help text in the same place you'd pop-up the toplevel. It's faster and simpler to code than the toplevel - and better still is linked to the parent widget it's been placed in/over. In other words, if you move or minimise etc your text widget, the help popup does the same with it. And since you can place more than one widget anywhere you like over your main widget, your help pop-up is effectively a transparent toplevel.


How Do I Keep Dialog Boxes (And Other Popups/Toplevels,) In Front Of Their Parent Window? Why Does My Dialog Box Keep Disappearing Behind Other Windows?

Mth on Aug-27-2003, Hey Guys I have a Tcl/tk application done by a diff developer using VisualTcl. Later on I have added some Iwidget::dialog boxes to this application. I have blocked/frozen the dialog with "modality=application" parameter. My problem is sometimes these dialog box loses its focus and goes behind the main window & leaving me with only one solution of killing and restarting the application.

- Is there a way to bind a key so that if it goes in the back, by pressing a key (say Ctrl+F5) will bring it to the front.

- Is there a command I could use to keep these dialogs always on top (see that page :)

- Is there any other alternate solutions to it.

Please let me know your suggestions, as I am really desperate to have this issue resolved. Thank you all in advance!

FW: All you need to do is determine the Tk path (ie .dialog1 or however IWidgets names them) of the dialog boxes. Then it becomes pretty easy. Otherwise, it's probably literally impossible. Are you able to do this? I'm not that familiar with IWidgets.

Peter Newman 29 October 2004: In other words, if you want:-

.fileManager.selectFileToDelete.confirm to popup (and stay) in front of (its parent):-

.fileManager.selectFileToDelete name it as a child of that parent. Eg, call it-

.fileManager.selectFileToDelete.confirm If you called it:-

.confirm (for example), then it's a child of "." - and it'll diappear behind:-

.fileManager.selectFileToDelete to stay in front of ".".


How Do I Save Canvas Content In Bitmap Format?

02/19/2004

Just two questions: It is possible to save canvas-content as bitmap and if it so how? thanks 4 each hint ... - RS: You get that with the Img extension:

 set im [image create photo -format window -data .my.canvas]
 $im write mycanvas.gif -format GIF

Sorry, but it doesn't work. "-format window" isn't supported and "-data" from canvas-object couldn't be recognized ... RS: Well, my hint above was too subtle - put the line

 package require Img

somewhere early in your program, and make sure you have that extension.


How Do You Add Cascade Menus, With The Menu Command?

02/12/2004

Hi, I've a problem by building cascade menus with menu-command:

 text .txt -background white -wrap none -yscroll {.sbary set} -xscroll {.sbarx set}
 scrollbar .sbary -command {.txt yview} -orient vertical
 scrollbar .sbarx -command {.txt xview} -orient horizontal
 grid .txt .sbary -sticky news
 grid .sbarx -sticky news
 grid columnconfigure . 0 -weight 1
 grid rowconfigure . 0 -weight 1

 menu .mnu -tearoff 0
 .mnu add cascade -label "menu 1" -menu {
        .mnu add command -label "menu 1.1"          ;# isn't displayed
 }
 .mnu add separator
 .mnu add command -label "exit" -command { exit }

 bind .txt <ButtonPress-3> {
        tk_popup .mnu %X %Y
 }

Unfortunately, I could't find any help or example for it... KD

PB: It's easier than you believe...

 ...
 menu .mnu1 -tearoff 0
 .mnu1 add command -label "menu 1.1"

 menu .mnu -tearoff 0
 .mnu add cascade -label "menu 1" -menu .mnu1
 .mnu add separator
 .mnu add command -label "exit" -command { exit }
 ...

Listbox Binding Problems

01-Dec-2003

I have set a bind to a listbox and bind should return the current index of a choosen line (button-1-event). But bind fails at first and returns an empty string. For each further one bind returns the index of the selection before not the current. How I can change this behavior? Thanks for each idea ...

 # Listbox
 scrollbar .sbary -command {.lbox yview}
 scrollbar .sbarx -command {.lbox xview} -orient horizontal
 pack .sbary -side right -fill y
 pack .sbarx -side bottom -fill x
 listbox .lbox -width 30 -height 10 -font {CourierNew 8} -background white \
        -selectmode single -yscroll {.sbary set} -xscroll {.sbarx set}
 grid .lbox -row 0 -column 0 -rowspan 1 -columnspan 1 -sticky news
 grid .sbary -row 0 -column 1 -rowspan 1 -columnspan 1 -sticky news
 grid .sbarx -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news

 # Filling with real indizes
 .lbox delete 0 end
 for {set i 0} {$i < 4} {incr i} {
        .lbox insert end "Listbox Index: $i"
 }

 # Binding
 bind .lbox <Button-1> {
         set index [.lbox curselection]
         tk_messageBox -message $index
 }

K: Try 'ButtonRelease' instead of 'Button' ...


Is Tcl/Tk Buggy? Or Is It Your Memory (Or Other Hardware) That's On The Blink?

I'm running a GUI to test some hardware. The GUI takes input from a touchscreen. Several buttons on the GUI control the action. All tests work fine, but there was a problem during an extreme temperature test. I think this has exposed a weakness in the button.tcl script.

The GUI contains a spinwheel, and 2 separate buttons that can also control the wheel.

This is the button code:

 button $a.prev -text "Prev" -command "$a.spin invoke buttondown"

This is the error message that pops up:

 expected boolean value but got ""
 expected boolean value but got ""
 while executing
 7        "if {[info exists Priv($w,relief)]} {
 8            if {[info exists Priv($w,prelief)] && \
                    $Priv($w,prelief) eq [$w cget -relief]} {
 9                $w configure -relief $Priv($w,relief)
 10            }
 11           unset -nocomplain Priv($w,relief) Priv($w,prelief)
 12        }
 "
 (procedure "tk::ButtonUp" line 8)

This code stems from button.tcl (tcl 8.4).

My theory is that the error is caused by the $Priv($w,prelief) expression, which is not defined (see below for explanation), and the fact that the expression is part of an if{} statement, where all expressions are evaluated before decision making. I know tcl is supposed to use a lazy &&, but only if the expression is enclosed in {} and the {} that is used here seems to belong to the if{} syntax.

My questions:

Does this make sense? Would the reported error be caused by something like this? Since button.tcl is part of the tcl/tk package, who is going to fix this? To fix this I would just break up the compound if into two statements, instead of using the &&.

Explanation for prelief not defined - I think our low temperature test on the touch screen caused the button down not to be sent out. The button down routine in button.tcl is the place where the prelief is actually set.

Thanks, Matthias

RS: && is short-circuit evaluated (e.g. stopped after the first 0) in if too, as can easily be tested:

 % if {[info exists Utopia] && $Utopia eq "here"} {puts yes!}

Also, the rror message is not about a missing variable, but "" as illegal Boolean value - but info exists returns 1 or 0. So, the error is a bit mysterious. Also, the second info exists test is certainly redundant.

Matthias: Thanks for the reply! I figured I'm getting the illegal Boolean, because the info exists failed, the var didn't exist and then an eq was attempted on the non-existing var. But if && is indeed lazy, even without the extra {} then that theory doesn't work out. Further testing showed another funky error, where a var seemed to disappear in the middle of a function, i.e. it got defined at the top, and a subsequent access couple lines later failed. I guess our memory chips don't do too well in extreme temperatures.


rdt I've seen this same error this very week and a room temp on a regular system. But only checking an array variable. I had to move the test outside of the if & that solved it!


How Do I Move A Parent Window, So That A Child Window Keeps Its Relative Position?

02/09/03

Hi,following piece of code shows the creation of a toplevel-widget (child) inbound a frame of another toplevel-widget (parent). I asked me how I can move the parent-window so that the child-window keep its relative position.

 set xmax [winfo screenwidth .]
 set ymax [winfo screenheight .]
 set xsize 480
 set ysize 360
 set xpos [expr ($xmax/2)-($xsize/2)]
 set ypos [expr ($ymax/2)-($ysize/2)]

 wm title . "parent"
 wm geometry . +$xpos+$ypos
 wm minsize . $xsize $ysize

 frame .main -borderwidth 1 -relief sunken
 pack .main -expand yes -fill both -anchor nw

 toplevel .child -class children
 wm title .child "child"
 wm transient .child .

 bind children <Visibility> {
         raise %W
         after idle {
                 update idletasks
                 set wx [expr [winfo rootx .main]+1]
                 set wy [expr [winfo rooty .main]+1]
                 wm geometry %W +$wx+$wy
         }
 }

I've tried to bind child on parent over motion-event but it doesn't work. Has someone any ideas to solve the problem?

FW: Well, first of all, your code binds for visibility, which will trigger just once when the window becomes visible. To bind for any time the window is redrawn (for example, when it is moved or resized) use the <Configure> event. Your code doesn't have anywhere near all the functionality needed for relative window moving, but I can give you a complete example (I've been meaning to implement this myself as an exercise for a good while too). I just need to know - besides moving relative to the window, do you also want the subwindow to be trapped within it? Or should it be allowed to leave the larger window, but still move relatively?

tje: Does this help at all? Toplevel Geometry Manager includes the <Configure> bindings, etc. needed to make two toplevels "tied" together.

I've cutted out all uninteresting code for that problem. Configure-event I use just to control maximumsize of smaller window, but if I can use it for more ... I'll do it.

Okay, conditions for smaller window are:

* start position should be the upper left corner of frame. It should work like ...

 place .child -x 0 -y 0 -anchor nw

(... but that doesn't work for toplevel-widgets. It would be nice if I could change a toplevel-widget into a frame OR if I could bind a frame onto a toplevel-widget because a frame as container for toplevel is easier to handle than a pure toplevel ...)

* size should be <;= frame of larger window

* if larger window have been moving, smaller window have to keep its position.

* and last but not least: smaller window is inbound the frame of larger window at home, that means it's not allowed for it to leave domestic frame.

FW. It would be nice if I could see your example code. I'm just interested in the way how you handle your toplevels.

tje. Do you know how I can two toplevels tied together? Seems to be a way to place toplevels like other widgets with place-command. Do you show me that?

FW: Is the smaller window to be resizable? If so, how should it being resized be handled? Should it snap back to the edge of the frame if you try to resize it beyond the edge?

FW. What's wrong? I thought concept of this formum is: "Ask, and it shall be given", not "Ask, and it shall be asked again". Conditions for smaller window are clearly defined. Sorry, but I only would have an answer of my questions or an idea or hint. My suggestion if you really want to help: read again. it's not so difficult. If you want to talk about programming in tcl, c, pascal or general about developing software send email to: [email protected]

FW: No, it was just a simple addendum question. You didn't specify the case of window resizing, which is rather different. I'm just going to take my best guess, since there seems to be a communication problem here.

FW (again): You're right, I thought you were talking about how to implement the task of constrained windows in general. OK, now that that's all cleared up. Now, you say binding for motion? I assume that means the <Motion> event, for the cursor moving. I realize this is probably getting exhausting by now, but could you describe the problem you're encountering a little more?

FW. So I thought also. I've tried to bind larger window on smaller window with <Button1-Motion>-event, so that if larger window is moved, smaller window is moved too, but no result. How did you solve that problem?

FW: Aha. <Button1-Motion> won't do it, because to move or resize a window (in Windows, for example) you use the title bar or drag the edges of the window. The border and title bar are provided by the window manager, and clicking on them won't trigger any Tk events. As I mentioned earlier, I'd bind to <Configure> to respond when a window is resized or moved. However, you've got to check to make sure the window has actually moved and isn't configuring for other reasons, otherwise needlessly adjusting the geometry will itself trigger a <Configure>, and go into an infinite loop.


Window Panning In Tk?

2004/02/11 sheila

I want to make a small map of the entire region of a GUI, with a box around the area that is currently in the area the user is looking at. I want it to update whenever the user pans to another area. I want the user to be able to pan on the big section, or pan on the small section. I've seen UIs do this before, but I'm not sure which key words to search on. Where do I look to learn about this?

GPS: I think I know what you are saying. Ghostview has a widget like this, and I believe Xaw has a builtin for such a thing (Panner?). This could probably be done with two canvas widgets. I'll try to come up with some code to demonstrate today that uses code from Getting the Canvas View Area in Pixels.

GPS: See: Panner


How To Emulate A Three Button Mouse, With A Two Button Mouse (In Tk)

12/Aug/2003

Is there a method to emulate a third (middle) button by pressing both buttons together when using a two button mouse?

tje Aug 20 2003 - How about...

    bind Toplevel <ButtonPress-1> {set ::bp1 [clock clicks -milliseconds] ; catch emu2}
    bind Toplevel <ButtonPress-3> {set ::bp3 [clock clicks -milliseconds] ; catch emu2}
    bind Toplevel <ButtonRelease-1> {unset ::bp1}
    bind Toplevel <ButtonRelease-3> {unset ::bp3}
    proc emu2 {} {
        if {[expr abs($::bp1 - $::bp3)] <= 150} {event generate . <2>}
    }

Adjust the '150' to your liking for timing, and populate 'event generate' with stuff you need.

FW: Bear in mind you can often configure your window manager to globally emulate a 3-button mouse.


How Do I Redraw/Replace An Image - Without Temporarily Graying It Out?

(JULY 30, 2003)

How does someone make interactive graphics with Tk? I mean, smooth presentations.

Environment of our program is somewhat loaded (many background checks for events), and redrawing of screen leaves it in grey background color for noticeable amount of time. It would be good to at least preserve old picture before draw anything new. What tricks or what methods do you use to achieve smooth Tk graphics performance?

SZ

lv by interactive graphics what do you mean? Smooth animation? SZ Yes, smooth change of pictures composed of text and images. When we destroyed previous frame with picture and creating new one we get gray (standard background) regions on a screen for a moment. What technique to use to avoid that?

FW: Try reconfiguring the -file for the image, which (I believe) will redraw it without destroying anything.


Yellow Sticky Note Application

How To Drag A Toplevel Window With The Mouse

Nov 04, 2003 Newbie asks: I'm trying to create a "yellow stick note" app. I have created a little decoration-less window using wm overrideredirect, and now I need to generate window-moving events so that I can manually place the sticky note. I believe I need to use event generate, but how do I get drag coordinates into a little script, which would (I believe) call wm geometry? Thanks...

 Here's a solution:

 set ::moveable 0
 wm overrideredirect . 1
 bind . <ButtonPress> {set ::moveable 1}
 bind . <ButtonRelease> {set ::moveable 0}
 bind . <Motion> {if {!$::moveable} {break}; wm geometry %W +[expr %X-10]+[expr %Y-10]}

 JPT

Newbie responds: Sacrosanct bovine, Batman! You guys sure make it look easy! Just to make myself feel better, I modified your solution so that the frame wouldn't 'jump' to the cursor:

 set ::moveable 0
 set ::X 0
 set ::Y 0
 wm overrideredirect . 1
 bind . <ButtonPress> {set ::moveable 1; set ::X [expr %X-$::X]; set ::Y [expr %Y-$::Y]}
 bind . <ButtonRelease> {set ::moveable 0; set ::X [expr %X-$::X]; set ::Y [expr %Y-$::Y]}
 bind . <Motion> {if {!$::moveable} {break}; wm geometry %W +[expr %X-$::X]+[expr %Y-$::Y]}