Thread Tk: Toplevel funktioniert nicht bei 2tem Aufruf (9 answers)
Opened by Juergen at 2011-03-02 08:51

Kalle
 2011-03-30 16:36
#147133 #147133
User since
2007-03-18
48 Artikel
BenutzerIn
[default_avatar]
Hallo Jürgen,

hier ein paar Beispiele:

kleines Beispiel für Toplevel Windows.
Da ich hier sowohl für das Main Window als auch für die Toplevel Windows die gleichen Widgets benutze, hab ich sie einfach mal in eine sub ausgelagert.
Mit dem Button kann "Create Toplevel Window" Button kann man nun vom Main Window als auch von bereits erzeigten Toplevel Windows aus neue Toplevels erstellen.
Dabei hängen alle erzeugten Toplevel Windows hängen am Main Window und sind voneinander unabhängig.

So ungefähr:
Code: (dl )
1
2
3
4
5
          |- Toplevel
|- Toplevel
MainWindow|
|- Toplevel
|- Toplevel


Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/usr/local/bin/perl

use strict;
use warnings;
use Tk;


#main window
my $mw = MainWindow->new(-title=>'Main Window');

create_widgets($mw);

MainLoop();



sub create_toplevel_window {
  # create toplevel window
  my $top=$mw->Toplevel(-title=>"Toplevel Window");
  # create toplevel frames
  create_widgets($top);
}

sub create_widgets {
  my $thiswindow = shift;
  my $frame_top = $thiswindow->Frame-> pack(-side=>'top',-fill => 'both', -anchor,'nw');
  my $frame_bottom = $thiswindow->Frame-> pack(-side=>'top',-fill => 'both', -anchor,'nw');
  my $edit_button = $thiswindow->Button(-text => "Create Toplevel Window",-state => 'normal',-width => 30,-activebackground=>'gray', -command => sub{create_toplevel_window()})->pack (-in => $frame_top,-side=>'top',-padx => 3,-pady => 5);
  my $mw_close_button = $thiswindow->Button(-text => 'Close',-background=>'gray',-width=>60,-command => sub{$thiswindow->destroy})->pack(-in=>$frame_bottom,-side => 'top',-expand => '0',-fill => 'x');
}



Im folgenden Beispiel hänge ich die Toplevel Windows an das Window, das den Aufruf ausführt.
Erzeuge ich damit mehrere Toplevels und schliesse ein übergeordnetes Window, dann werden alle daran hängenden und darunterliegenden Windows geschlossen.
So ungefähr:
Code: (dl )
1
2
3
4
5
6
7
8
                     |-Toplevel
|- Toplevel|
| |-Toplevel|-Toplevel
| |-Toplevel
|
MainWindow|
|- Toplevel|-Toplevel
|- Toplevel


Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/usr/local/bin/perl

use strict;
use warnings;
use Tk;

#main window
my $mw = MainWindow->new(-title=>'Main Window');

create_widgets($mw);

MainLoop();


sub create_toplevel_window {
  my $thiswindow = shift;
  # create toplevel window
  my $top=$thiswindow->Toplevel(-title=>"Toplevel Window");
  # create toplevel frames
  create_widgets($top);
}

sub create_widgets {
  my $thiswindow = shift;
  my $frame_top = $thiswindow->Frame-> pack(-side=>'top',-fill => 'both', -anchor,'nw');
  my $frame_bottom = $thiswindow->Frame-> pack(-side=>'top',-fill => 'both', -anchor,'nw');
  my $edit_button = $thiswindow->Button(-text => "Create Toplevel Window",-state => 'normal',-width => 30,-activebackground=>'gray', -command => sub{create_toplevel_window($thiswindow)})->pack (-in => $frame_top,-side=>'top',-padx => 3,-pady => 5);
  my $mw_close_button = $thiswindow->Button(-text => 'Close',-background=>'gray',-width=>60,-command => sub{$thiswindow->destroy})->pack(-in=>$frame_bottom,-side => 'top',-expand => '0',-fill => 'x');
}


Das dritte Beispiel dürfte deinem Anliegen nahe kommen. Aus dem Main Window wird ein Toplevel gestartet. Im Toplevel werden daten geladen und in einer MListbox angezeigt.
Ein Add Button sorgt dafür, daß neue Daten hinzugefügt werden können.
Der Refresh Button ist nicht wirklich bedeutsam, da die MListbox nach dem Hinzufügen durch die sub fill_tasklist refreshed wird. aber der Refresh Button bewirkt auch eine Dumper Ausgabe in der Shell.

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/local/bin/perl

use strict;
use warnings;

use Tk;
use Tk::MListbox;
use Tk::DialogBox;
use Tk::LabEntry;
use Data::Dumper;

#main window
my $mw = MainWindow->new(-title=>'Main Window');

my $frame_top = $mw->Frame-> pack(-side=>'top',-fill => 'both', -anchor,'nw');
my $frame_bottom = $mw->Frame-> pack(-side=>'top',-fill => 'both', -anchor,'nw');
my $edit_button = $mw->Button(-text => "Edit Tasks",-state => 'normal',-width => 30,-activebackground=>'gray', -command => sub{edit_tasks()})->pack (-in => $frame_top,-side=>'top',-padx => 3,-pady => 5);
my $mw_close_button = $mw->Button(-text => 'Close',-background=>'gray',-width=>60,-command => sub{$mw->destroy})->pack(-in=>$frame_bottom,-side => 'top',-expand => '0',-fill => 'x');


MainLoop();


sub edit_tasks {
  # load your data
  my $tasks=load_data();

  # create toplevel window
  my $top=$mw->Toplevel(-title=>"Toplevel Window");

  # create toplevel frames
  my $frame_top = $top->Frame-> pack(-side=>'top',-fill => 'both', -anchor,'nw');
  my $frame_bottom = $top->Frame-> pack(-side=>'top',-fill => 'both', -anchor,'nw');
  my $tasklist = $top->Scrolled('MListbox',
                        -scrollbars => 'ose',-separatorcolor => 'darkgrey',-height=>15,-width=>300)->pack(-in=>$frame_top,-expand=>1,-fill=>'both');
  $tasklist->columnInsert('end',-text=>'Task',-width=>15);
  $tasklist->columnInsert('end',-text=>'Date',-width=>15);
  $tasklist->columnInsert('end',-text=>'Time',-width=>15);

  #buttons
  my $add_button = $top->Button(-text => "Add Task",-state => 'normal',-width => 30,-activebackground=>'gray', -command => sub{add_task($top,\$tasks); fill_tasklist($tasklist,\$tasks);})->pack (-in => $frame_top,-side=>'top',-padx => 3,-pady => 5);
  my $refresh_button = $top->Button(-text => "Refresh",-state => 'normal',-width => 30,-activebackground=>'gray', -command => sub{fill_tasklist($tasklist,\$tasks);})->pack (-in => $frame_top,-side=>'top',-padx => 3,-pady => 5);
  my $mw_close_button = $top->Button(-text => 'Close',-background=>'gray',-width=>60,-command => sub{$top->destroy})->pack(-in=>$frame_bottom,-side => 'top',-expand => '0',-fill => 'x');

  fill_tasklist($tasklist,\$tasks);
}

sub add_task {
  my $parent=shift;
  my $tasksref=shift;
  my $tasks=$$tasksref;
  my $ewidth=40;

  my $thistaskname;
  my $thisdate;
  my $thisstart;
  my $thisstop;

  my $add_dialog = $parent->DialogBox( -title   => "Add task",-buttons => [ "Save", "Cancel" ] );

  my $task_entry=$add_dialog->LabEntry(-label => "Task          ", -bg=>'white',
         -labelFont => 'monospaced8',
         -labelPack => [-side => "left", -anchor => "w"],
         -width => 30,
         -textvariable => \$thistaskname)->pack(-side => "top", -anchor => "nw", -fill=>'x');

  my $date_entry1=$add_dialog->LabEntry(-label => "Date          ",  -bg=>'white',
         -labelFont => 'monospaced8',
         -labelPack => [-side => "left", -anchor => "w"],
         -width => $ewidth,
         -textvariable => \$thisdate)->pack(-side => "top", -anchor => "nw", -fill=>'x');

  my $time_start_entry=$add_dialog->LabEntry(-label => "Time Start ",  -bg=>'white',
         -labelFont => 'monospaced8',
         -labelPack => [-side => "left", -anchor => "w"],
         -width => $ewidth,
         -textvariable => \$thisstart)->pack(-side => "top", -anchor => "nw", -fill=>'x');

  my $time_stop_entry=$add_dialog->LabEntry(-label => "Time Stop ",  -bg=>'white',
         -labelFont => 'monospaced8',
         -labelPack => [-side => "left", -anchor => "w"],
         -width => $ewidth,
         -textvariable => \$thisstop)->pack(-side => "top", -anchor => "nw", -fill=>'x');

  $task_entry->focus; #set focus depending on type of command (add,edit) and erros (alias,user or password invalid)
  my $clicked_button = $add_dialog->Show;

  if ($clicked_button eq 'Save') {
    my $thistime="$thisstart\-$thisstop";
    push(@{$tasks->{$thistaskname}->{$thisdate}},$thistime);
  }
}


sub fill_tasklist {
  my $tasklistwidget=shift;
  my $tasksref=shift;
  my $tasks=$$tasksref;

  $tasklistwidget->delete(0,'end');
  foreach my $thistaskname (sort keys %{$tasks}) {
    foreach my $thisdate (sort keys %{$tasks->{$thistaskname}}) {
      foreach my $thistime (@{$tasks->{$thistaskname}->{$thisdate}}) {
        my @row;
        push(@row,$thistaskname);
        push(@row,$thisdate);
        push(@row,$thistime);
        $tasklistwidget->insert('end', [@row]);
        $tasklistwidget->see('end');
        $tasklistwidget->update;
      }
    }
  }
  print Dumper($tasks);
}



sub load_data {
  my $tasks;
  my $pos= tell(DATA);
  while  (<DATA>) {
    chomp $_;
    my @line=split(/,/,$_);
    my $thistaskname=$line[0];
    my $thisdate=$line[1];
    my $thisstart=$line[2];
    my $thisstop=$line[3];
    my $thistime="$thisstart\-$thisstop";
    push(@{$tasks->{$thistaskname}->{$thisdate}},$thistime);
  }
  seek DATA, $pos, 0;
  return $tasks;
}

__DATA__
Task1,20110329,08:00,12:00
Task2,20110329,13:00,18:00
Task3,20110330,09:00,17:00


Gruß

Kalle

View full thread Tk: Toplevel funktioniert nicht bei 2tem Aufruf