Steffen: Perl/TK, Menüstruktuer mit Buttons

Hallo liebe Forumsgemeinde,

bin Perl/TK Neuling und steh schon am Anfang vor nem kleinen Problem.

Beim Folgenden Script
will ich links nen paar Buttons haben und Links dann das Fenster wo man Arbeitet (je nachdem welches Menü durch den Button gewählt wurde)

jedoch erstellt der beim wechseln der Menüs durch die Buttons alles mehrfach...

Sicherlich muss ich das irgendwie schliessen...
klar mit destroy  aber is das die korrekte lösung?
müsste sich das nicht überlagern???

am besten ihr schaut euch das kurze Script mal an und startet es dann wisst ihr was ich meine

DANKE & Gruß
Steffen

#! /usr/bin/perl -w

use strict;
use Tk;
use Tk::NoteBook;
use Win32::GUI;

my ($DOS) = Win32::GUI::GetPerlWindow();
Win32::GUI::Hide($DOS);

my $main = MainWindow->new;

my $frame_left=$main->Frame()->pack(-side => 'left');
my $frame_right=$main->Frame()->pack(-side => 'right');

my $schalter1 = $frame_left->Button("-text" => "Mitarbeiter","-height" => 2,"-width" => 10,"-command" => [&Show_Mitarbeiter] )
     ->pack();
my $schalter2 = $frame_left->Button("-text" => "Dienste","-height" => 2,"-width" => 10,"-command" => [&Show_Dienste] )
     ->pack();
my $schalter3 = $frame_left->Button("-text" => "Ende","-height" => 2,"-width" => 10,"-command" => sub { print "Zurück in der Konsole\n"; exit 0; } )
     ->pack();

MainLoop;
Win32::GUI::Show($DOS);

##############################################################

Subroutinen

sub Show_Mitarbeiter {
#$frame_right->destroy;
my $radio1=$frame_right->Radiobutton(-text => "Optionsfeld 1" )
                                     ->pack();
my $radio2=$frame_right->Radiobutton(-text => "Optionsfeld 2")
                                     ->pack();

}

Dienste anzeigen

sub Show_Dienste {
my $nb = $frame_right->NoteBook()->pack();
my $page1 = $nb->add('PageID-1', -label => 'Dienste');
my $page2 = $nb->add('PageID-2', -label => 'neuer Dienst');
 }

  1. Halihallo Steffen

    jedoch erstellt der beim wechseln der Menüs durch die Buttons alles mehrfach...
    Sicherlich muss ich das irgendwie schliessen...
    klar mit destroy  aber is das die korrekte lösung?

    Ich würde sagen: destroy :-)
    Aaaaber: Du möchtest vielleicht nicht wirklich schliessen...

    müsste sich das nicht überlagern???

    Wieso? - Wenn du das Widget löschst, was soll sich dann noch
    überlagern?

    ---

    Grundsätzlich:
    Wenn du links mehrere Buttons hast, die "staatisch" sind und rechts
    dynamischen Inhalt (der z.B. durch drücken der linken Buttons
    geändert wird), dann schmeiss den gesamten rechten Inhalt in ein
    Frame-Widget (wie du es hast). Es ist dann einfach den Inhalt
    auszutauschen, da alle Kinder implizit gelöscht/unsichtbar werden.
    Das nur prinzipiell und so hast du es ja auch richtig gemacht.

    Möglichkeit 1:  In jede Subroutine folgendes einbauen:

    $frame_right->destroy() if ($frame_right);
     $frame_right = $main->Frame()->pack(-side => 'right');
     ... frame neu aufbauen ...

    Damit sollte es funktionieren.

    Es ist, sagen wir mal, keine schöne Lösung... Der Window-Manager
    muss den Frame bei jedem Buttonclick neu erstellen, was natürlich
    Zeit kostet und visuell über "flackern" wahrgenommen wird. Besser ist
    es für jeden Button bereits ein Frame mit Content zu erstellen und
    diesen dann anzuzeigen, wenn der entsprechende Button gedrückt wurde.
    Falls nachher ein anderer Button gedrückt wird, soll der Frame wieder
    versteckt werden und der für den Button geeigneten Frame angezeigt
    werden (Möglichkeit II).

    Dein Beispiel angepasst an Möglichkeit II:

    Die Frames für ButtonI und ButtonII werden bereits vor MainLoop
    erstellt. Da sie jedoch durch keinen Geometry Manager (pack,...)
    gejagt werden, sind sie vorerst unsichtbar. Falls ein Button gedrückt wird (somit eine deiner Subroutinen aufgerufen wird), wird
    einfach der _entsprechende_ Frame mit pack sichtbar und der
    andere (falls aktiv) mit packForget unsichtbar gemacht.
    So einfach und so effizient :-)

    #!/usr/bin/perl

    use strict;
    use warnings;
    use Tk;
    use Tk::NoteBook;

    my $main = MainWindow->new();

    my $frame_left=$main->Frame()->pack(-side => 'left');
    my $frame_right=$main->Frame()->pack(-side => 'right');

    Frameinhalt für Button 1: Mitarbeiter

    my $fr1 = $frame_right->Frame();
    $fr1->Radiobutton(-text => "Optionsfeld 1" )->pack();
    $fr1->Radiobutton(-text => "Optionsfeld 2" )->pack();

    Frameinhalt für Button 2: Dienste

    my $fr2 = $frame_right->Frame();
    my $nb = $fr2->NoteBook();
    $nb->pack();
    $nb->add('PageID-1', -label => 'Dienste');
    $nb->add('PageID-2', -label => 'neuer Dienst');

    Linker Frame

    my $schalter1 = $frame_left->Button("-text" => "Mitarbeiter","-height" => 2,"-width" => 10,"-command" => [&Show_Mitarbeiter] )
         ->pack();
    my $schalter2 = $frame_left->Button("-text" => "Dienste","-height" => 2,"-width" => 10,"-command" => [&Show_Dienste] )
         ->pack();
    my $schalter3 = $frame_left->Button("-text" => "Ende","-height" => 2,"-width" => 10,"-command" => sub { print "Zurück in der Konsole\n"; exit 0; } )
         ->pack();

    MainLoop;

    ##############################################################

    Subroutinen

    ##############################################################

    Mitarbeiter anzeigen

    sub Show_Mitarbeiter {
        $fr1->pack( -side => 'top' );
        $fr2->packForget();
    }

    Dienste anzeigen

    sub Show_Dienste {
        $fr2->pack( -side => 'top' );
        $fr1->packForget();
    }

    Viele Grüsse

    Philipp