4

I have a set of radiobuttons (say, with choices 1 and 2) and need to show some widget based off of the user's choice. For example, if they chose 1, I would show them a labelframe with several radiobuttons; whereas, if they chose 2, I would show them a labelframe with some buttons. In either case, the resulting content would be shown in the same area on the window.

What is a good way to switch between multiple widget displays like this?

This answer has me thinking that I should use a panedwindow and frames, but I don't quite see how I would switch between different content.

Community
  • 1
  • 1
Pat
  • 16,515
  • 15
  • 95
  • 114

2 Answers2

3

When using a panedwindow, you should be able to switch between content panes by deleting a frame and adding a new one to replace it. See this manual page for a description of the forget and add/insert commands for ttk::panedwindow.

Sample code:

package require Ttk

# Create a panedwindow
ttk::frame .f
ttk::panedwindow .f.pane -orient vertical

# Create three panes
ttk::frame .f.pane.one -height 50 -width 50
ttk::label .f.pane.one.l -text "Number one"
pack .f.pane.one.l

ttk::frame .f.pane.two -height 50 -width 50
ttk::label .f.pane.two.l -text "Number two"
pack .f.pane.two.l

ttk::frame .f.pane.three -height 50 -width 50
ttk::label .f.pane.three.l -text "Number three"
pack .f.pane.three.l

# Add frames one and two to the panedwindow
.f.pane add .f.pane.one
.f.pane add .f.pane.two

pack .f.pane -expand 1 -fill both
pack .f -expand 1 -fill both

# Replace pane one with pane three
.f.pane insert 1 .f.pane.three
.f.pane forget 2 

You can adapt this code for your own needs. Simply create all the views that you might need, and then swap them in and out as needed.

bta
  • 43,959
  • 6
  • 69
  • 99
  • The easiest way to hook the selection of the pane to the radiobuttons is to use a write `trace` on the radiobuttons' shared state variable. – Donal Fellows Sep 04 '10 at 07:00
  • @Donal I have tried to go the `trace` route, but my code prevented the radiobutton from changing and gave me an error. Here is the code (`demoChoice` is the radiobutton variable): `set inEvent 0 trace variable demoChoice w { global demoChoice inEvent if ($inEvent) { return } set inEvent 1 .main.demoDetails.lbl configure -text $demoChoice set inEvent 0 }` – Pat Sep 07 '10 at 14:09
  • @Pat: Use a procedure for the trace callback. – Donal Fellows Sep 07 '10 at 15:13
  • You'll want to make the procedure takes `args` as its parameter list; trace callbacks get extra arguments appended. – Donal Fellows Sep 07 '10 at 15:18
  • I didn't really need multiple windows with a pane, but roughly the same technique worked with a single pane. I just used `.f.pane forget 0; .f.pane add .f.pane.X` – Pat Sep 07 '10 at 18:21
  • @Donal Thanks, that makes more sense. – Pat Sep 07 '10 at 18:22
1

A really simple way is to use one frame for each set of data. Use grid to place them all in the same row and column. Then all you need to do is raise the frame and it's children to the top of the stacking order.

Another technique starts out the same but instead of using raise, do grid remove on whichever frame is currently being shown, and then grid on the one to be shown. With grid remove, grid remembers all of the settings so that you don't have to specify all of the options again the next time you want it to appear.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685