Version 35 of Frame Background Image

Updated 2006-04-05 12:13:51

TIP#262 proposes that frames should have an option for setting a background image. This Page was started so some graphical examples of frames with backround images could be displayed along with a discussion of the proposed change.

ET The TIP#262 can be found here http://tip.tcl.tk/262.html

After this was published, it became apparent that nested frames might present a problem. I think that having a -transparent option for frames might enhance this. Below is a screenshot of 2 sets of nested frames with buttons, where the upper set is how they would look without images and without the ability to set a frame transparent. The bottom half shows how this could look with a background image and a frame (enclosing the 3 buttons) that has been set to be transparent. Since this is not yet implemented, the below image is merely my photoshop'd version of what it might look like.

Note that the image has been tiled. It was created in photoshop, from a pattern, and then repeated as needed to fill the frame. This would allow one to create small pattern files that could also be inlined as code without being thousands of lines of text. The tile option would let one resize the window and as many repititions of the pattern as needed would be rendered to fill the new frame size.

http://home.comcast.net/~etailor/images/frames2.gif

To implement this using the tip, (and an option -transparent not yet included in the tip) should be like so:

 Frame11 configure -backgroundimage $apattern -tile 1 
 Frame8  configure -transparent 1 -borderwidth 0

which would take an image, tile it (repeat it) as needed to fill the frame, and then make Frame8 transparent so the buttons appear to hover over the background.

Note: Frame11 and Frame8 are command aliases to frames. I use Visual Tcl for this which generates command aliases to each widget that can then be used to configure the widget.

Frame8 was created inside Frame11 to organize the layout of the 3 buttons using the pack manager. In order to be completely transparent, the border width would need to be 0. If not 0, then it would draw a frame, based on style, as before, but the interior of the frame would still be transparent. I haven't completely thought this out yet, however.


MG (Excuse the rambling, just woke up) If it's possible to add a -transparent option like that for frames, why not go a step further: add a transparent color which all widgets can accept as their -background color. I assume that if code is added so that frames could be transparent, it wouldn't take much to apply it to other widgets. (Of course, I could be totally wrong, so if anyone who actually knows could correct me...)

One thing I noticed in your images, btw: Frame5 (the non-transparent counterpart of Frame8) has a raised relief, with a fairly heavy border, but Frame8 doesn't. Would the borders still show up for transparent frames? (Since it's not difficult to turn the borders off when you don't want them, that would seem to make more sense, to me...) Oh, and another thought: although the TIP doesn't mention it, could/would these options be added to [toplevel] widgets as well as frames? That would probably be equally useful.


ET The discussion on the core list seems to be how one would make these frames transparent on the 3 major system, windows, linux/unix, macos. So far, windows seems do-able, macos with some changes to a different API. Haven't heard from the linux/unix guys yet. I was wondering myself if the transparent color that is part of gif images was actually implemented.

Frame5 did have the raised relief, but not for any particular reason - just an option click in visual-tcl where I often just try different settings to see their effect. I would think that a -borderwidth 0 on a transparent frame would make it completely transparent, while a positive value would still render the borders the same as if -transparent was not on - but I don't know exactly how they'd look if the interior was transparent. It might work out or the two options together might clash. But with border 0, I would think the style (raised, relief, etc.) would in effect be canceled.

I usually have at least one frame at the top of my heirarchy inside all my toplevels, so couldn't we get the effect applied to a toplevel simply by applying this to the outermost frame in a toplevel, rather than changing the toplevel code itself. In the example, Frame1 and Frame11 could be inside a frame just below the toplevel, which could have border 0.


Incidentaly, this -transparent option could also be more than a boolean; maybe a float, where 0. and 1. would be off/on but there could be semi-transparency with a value, say 0.5. I didn't suggest this yet as I really have no clue how difficult any of this would be to implement. But perhaps on a system that could not implement partial transparency, the floating value would simply be rounded to 0 or 1.

Also, -transparent would be a feature of frames, independent of the imaging capability. This would give a feeling of inheritance to inner frames that would then inherit their parent frames color. Then if one wanted to effect all the colors of a set of nested frames with the same color, one could just change the outermost frames color.

I would also think that all the other options, like expand, fill, etc. would work as expected. It seems logical that the rendering of styles would be in two parts, the interiors and the borders. There's also the internal and external padding that should be straightforward to implement also.

MG When I said as a color, I didn't really mean related to images, just as a simpler way to add transparency to all widgets. It would be good, for instance, to be able to give label widgets a transparent background, so that they took on the background color of the frame (or toplevel) they were packed in automatically.

I've also seen requests (and bits of code) on the Wiki for tiled background images in text and canvas widgets, so I wonder: is there any reason this TIP was limited to frame widgets? Is there something that makes it simple(r) to add these into frames than into (some/all) other kinds of widgets? Or would it theoretically be quite easy to have transparent or bg-imaged widgets of all types, once it's coded for frames?

ET I was thinking that if I could just make frames look jazy, I'd be able to better show off some Tcl/Tk gui programs I've been writing. One often needs to justify using Tcl/Tk. All I keep hearing is XML this, Java that, Python shmithon etc.

I thought if I could just have better looking backgrounds, that could really spice up my gui scripts. The frame idea came to me when I was struggling to jazz up a "master control panel" I had written, and wanted to have a chrome background behind some widgets in a frame. In my business, it's often how cool the thing looks that sells the project. Functionality comes second when you have only a few seconds to impress some high placed political types.

I looked around, found the wiki entry on tiled backgrounds but it all seemed relatively difficult to implement involving a lot of code with canvases.

So, I asked myself, what's the smallest Tcl/Tk change that would get me what I was after, and background images in frames seemed to fit the bill. Since other widgets had background images (like button) I figured this must not be too difficult to implement. Later, the -transparent idea seemed to add almost as much as the imaging itself, but I haven't yet figured out how to change a published TIP.

It could be the way I program. Since I can add frames with no effort using visual-tcl, I tend to use them around almost every widget, just in case I want to later add something next to it without messing up other widget placement. I find the place and grid managers to be problematic and difficult to work with and so by using many frames and the pack manager I can always get what I want. I'm just a sort of frame type of guy :)

DKF: If frames support background images, so should toplevels. After all, those two widgets are virtually the same thing.

ET It's been brought to my attention that a canvas can do pretty much everything a frame can, and it supports a background image. So, if this is the case, I might suggest a withdrawl of this tip and instead create a tip that proposes that a canvas background image could be transparent as I've discussed above. I also did the tiling with the code example (by Aric Bills) from tiled image to tile a jpg file I created from a photoshop pattern. Then I made an inline -data string from the file. The tiling reduced an inline image -data set from over 2000 lines of text to about 200. Quite exceptable for inlining.

On the other hand, doing this within frames might still be a preferable way to go for beginners who might be put off by the complexity of canvases. I guess it would be up to the implementers to decide which was best.

There's also a package called Paved Widgets that support most of this request. I've asked the poster who mentioned this if it supported transparent images (he replyed as how it did not), as I'd still need to do framing with a paved::canvas and would need the transparency.


This is beginning to converge down to a few ideas.

  • use canvas instead of frame to get a background image
  • use the tiling repeat feature of image copy
  • write a new tip suggesting transparency option for a canvas and/or a frame (and text widget, surely)
  • implement the first 2 in Tcl code, but the hard one is the transparency

Without the transparency, placement would be difficult as nested frames or canvases would obscure the background image.

I had considered suggesting a hack on frame whereby using the -backgroundimage on a frame command would just invoke canvas behind the scenes. This could get confusing, or it could be a way to implement this as a frame so the novice programmer wouldn't have to think about all the canvas features to get a background image into a frame. But maybe it'd just be better to go with a few library proc's instead.

The following example program demonstrates a resizeable window with a few canvases. One outer canvas and two inner canvases. Of the two inner ones, one has 2 labels and the other 2 buttons. The one with buttons has a slate texture for the background. This works because the buttons are not in a frame (or canvas) of their own nested inside the canvas.

    # procedure from Aric Bills wiki example
    proc {initBackground} {canvas sourceImage} {
        package require Img 
        set tiledImage [image create photo]
        $canvas create image 0 0  -anchor nw  -image $tiledImage  -tags {backgroundBitmap}
        $canvas lower backgroundBitmap
        if {0} {
            proc {tile} {canvas sourceImage tiledImage} {
                $tiledImage copy $sourceImage  -to 0 0 [winfo width $canvas] [winfo height $canvas]
            }
            bind $canvas <Configure> [list tile $canvas $sourceImage $tiledImage]
            bind $canvas <Destroy> [list image delete $sourceImage $tiledImage]
            tile $canvas $sourceImage $tiledImage
        } else {  
            # avoid needing a tile proc  
            bind $canvas <Configure> "$tiledImage copy $sourceImage  -to 0 0 \[winfo width $canvas\] \[winfo height $canvas\]"
            bind $canvas <Destroy> [list image delete $sourceImage $tiledImage]
            $tiledImage copy $sourceImage  -to 0 0 [winfo width $canvas] [winfo height $canvas]   
        }
     }


    proc {main} {argc argv} {
            global  vTcl
            package require Img
            #wm withdraw .
            wm geometry . 400x400+30+30
            initBackground .can61.can66 [myback]
            #console show
    }
    proc {myback} {} {

    set backg [image create photo -data {
    R0lGODlhKgApAMQAAISMlaistKOrs32BiYuPn36Cj5igrJGZpZ6mspGWpZ2l
    rZefp5CZoZygqISIlaKmroOHkImNlpaaoqOns52hrZebp4qTm4+UnIqOm5CV
    oQAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAqACkAAAX/oHJZU+ZE
    U2RhlwMpVXVRcdWcmHVK2TRZl1+FQYFEMhAKJnJh3B4K3uQCyVQojcUIA3Fc
    MAGKwvHILCIUJwOJyTAuCpqEQsmYM0dLfFHJXAR2DQoTFFMrfWA9ZREsNHE/
    FA8ECxhcGBMPLAVXGRYZbQqWDBEQThWZKykGMRcHDQZ+AFQYMBgUFhYMU2UE
    FwAQFg8PDpcTMn4XEisNExBzEr85jRQSmBgPPnZcxBYRFRYSDRYAuDlTxmOc
    SH4WdALfYAwQPgoMXl52nZ9+NJ0qDyPeKKgyyga1ChGEPRAgINKFDAUiDMAj
    oUyRICMyTHxYQYIDE18wVBDwMEeADNg6/9bBMKCLGwoCAH5kYCuCiwpaUgDI
    gTJmsAzVYDxYZWSBJyanfmCYQ4cAjwEksJy6oGKCBBk8LATgIQeCjAcDZBHp
    kaGBAJENIEDA0CACA2USDlTSJQ2lu2rDwLX4tJRC1QcMYiir1CAZ2yUl/fSI
    QrZBAVsWgOWw0AADnywSlk5g8RCATQg7gQCxFcDysAhHtrhAnSOIEmMSVNjZ
    6wkISm0XCi/Y7KtKMt/gGjSooMDKw08zrAxh0alQDAwAOMnOYGCBHRWViMOs
    89D6BQR8cK1FUjEGA3AxxSUjsjkCgE8N5khqo6TbxxldWFRpqAUopgleEODA
    FSOcUlVgB/0wzP8FTfjBiC8r0ICdZc0AgEBuC5AzxxJWIfIAH/7gksEYOhyH
    iQP2WIGNHw100sZHChzRUCELYGGdFxBQBZRa4zVAwwUyvKGRYD3k+FQBFACp
    wEklfAHBAN985IADOy0wxwUPlEZHA54tyEMGZzEBwwIBfHPDJycEAMwIOZ7S
    B13t+PWAGJuVQsECzrS1wG5BcKYVKfiAxsI3USwQHxIOUNJAliegGUoFxkQg
    QQAPWEAJKWutMF4fD+kigQKZcPaDFxMI4A1bi7axgh11QqcWakC81dF/JniW
    FKx2rJaZJ2RK8NZkZQA1oAUyTHBAeHyitIYRB8wJ5BrUvFTaJ11Ug8f/J5Tx
    AOkU7CCZiRgZRDKQBQj4g8ecwUQWBE1tRAADHemGe4RZngRLwyEyPGQBAXZI
    QIA5WABRQDAPHBCpBAX4mkMEqxAYxaDYEgNNCpGFUwgGJ6DzzWPVUMNFRxm4
    QkelDhw1XibzrFVuqd0A8ZU4FATgi2VXHBBOcZWh1kILlVITa24dqVrNbhXA
    goYdD+BkMwKEYFMbLcCIkZwdhRSHWlnDPSABgzVuFJgECCCAkx8DtLGWFy2K
    oONVnQDggCAxw2RFOACcs44NE8QBQJIDYJf0FzuVitJUmTATgDEBLODFSBWQ
    kwTeOeLhwqTtLNUn3ieRoEwFJ+GJsaRb12lddALueeHRANGSsFYEZJZQxgzg
    BC3JCgizUkkAxTFnSXaeSGblEmmUSTMpgzzARDsMMhAGBUa3wSZojCwBwVkd
    vbGEG4WVUIcnUcxAoAEi1PaDIbPl6AM1JQDlhja60FFFPkfUMYUlyfhFQNYr
    wBEAETHygUEIADs=
    }
    ]
        return $backg
    }

       set base ""
       canvas $base.can61 \
            -borderwidth 2 -closeenough 1.0 -height 264 -relief ridge -width 378 
        canvas $base.can61.can62 \
            -borderwidth 2 -closeenough 1.0 -height 264 -highlightthickness 9 \
            -relief ridge -width 378 
        label $base.can61.can62.lab64 \
            -text label1 
        label $base.can61.can62.lab65 \
            -text label2 
        canvas $base.can61.can66 \
            -closeenough 1.0 -height 264 -relief groove -width 378 
        button $base.can61.can66.but67 \
            -background #009900 -borderwidth 6 -foreground #ffff00 -pady 0 \
            -text button1 
        button $base.can61.can66.but75 \
            -background #ff0000 -borderwidth 6 -foreground #ffffff -pady 0 \
            -text exit -command exit
        ###################
        # SETTING GEOMETRY
        ###################
        pack $base.can61 \
            -in . -anchor center -expand 1 -fill both -side top 
        pack $base.can61.can62 \
            -in $base.can61 -anchor center -expand 1 -fill both -side top 
        pack $base.can61.can62.lab64 \
            -in $base.can61.can62 -anchor center -expand 1 -fill none -side top 
        pack $base.can61.can62.lab65 \
            -in $base.can61.can62 -anchor center -expand 1 -fill none -side top 
        pack $base.can61.can66 \
            -in $base.can61 -anchor center -expand 1 -fill both -side top 
        pack $base.can61.can66.but67 \
            -in $base.can61.can66 -anchor center -expand 1 -fill none -side top 
        pack $base.can61.can66.but75 \
            -in $base.can61.can66 -anchor center -expand 1 -fill none -side top 


    main $argc $argv