I'm working on a Tk project that includes the ability to edit a set of filters, much like email filters. I've come up with a scheme that uses two HList widgets to manage this.
The user interaction works nicely, but I've discovered that I've got some memory issues. Every time I select a new rule for editing, I gobble up about 110 K of ram.
Before I go into much more detail, my questions are:
Here's a gross little ASCII picture of the interface:
+--------------------------------+ | [ ] A Rule X | | [X] A Different Rule X | | + | +--------------------------------+ Name _____________________ Run if [ANY =] conditions: +--------------------------------+ |[FIELD1 =] [ > =] __________ X | |[FIELD2 =] [ < =] __________ X | |[FIELD3 =] [ is =] [ value =] X | +--------------------------------+ Legend: [FOO =] is meant to represent an Optionmenu The X and + are buttons for adding or deleting items _____ are Entry widgets The borders denote my HList widgets.
How it works
When a user selects a rule in the top HList, it is displayed in the bottom HList. The I copy the rule into my "working copy" aka my object's rule attribute. The Rule and Clause objects are basic Class::Struct based objects. Then I clean out the bottom HList by explicitly destroying the widgets in each item, and delete each entry. Then I create new entries and items and populate them with new widgets. A lot of widgets are created and destroyed in this process, but the only other option I can see is creating a pool of widgets and parceling them out or creating new ones as needed--a task I'd rather not manage.
sub EditRule { my $self = shift; my $rule = shift || 'NO_COPY'; if ( $rule ne 'NO_COPY') { $rule->copy($self->original_rule); $rule->copy($self->rule); } # This is my HList widget my $clause_list = $self->clause_list; # Here we remove all items from the HList. foreach my $path ( $clause_list->info('children') ) { print "Deleting $path\n"; foreach (0..3) { next unless $clause_list->item('exists', $path, $_); my $w = $clause_list->item('cget', $path, $_, '-widget'); # This is testing code where I try explicitly clearing out + bits the widgets I use. # It could be refined by writing an arg list to an array a +nd passing it to a generic $w->configure call. if ( ref $w eq 'Tk::Button' ) { print "\tCleaning button\n"; $w->configure( '-command'=> undef, -textvariable => undef ); } elsif ( ref $w eq 'Tk::Optionmenu' ) { print "\tCleaning Optionmenu\n"; $w->options($NULL_OPTS); $w->configure( '-command'=> undef, -textvariable => undef, ); } elsif ( ref $w eq 'Tk::Entry' ) { print "\tCleaning Entry\n"; $w->configure( -textvariable => undef, ); } $w->DESTROY; } $clause_list->delete('entry', $path); } # This gets a list of conditions or clauses for the rule # Clause is another Class::Struct based object. my $clauses = $self->rule->clauses; # Here I make a new HList item to house the NEW CLAUSE button. # methods called _W_blah_blah return a widget. $clause_list->add('new_clause'); $clause_list->itemCreate('new_clause',0, -itemtype => 'window', -widget => $self->_W_new_clause(), ); # Here I add a new entry for each clause in the rule. foreach my $i ( 0..$#{$clauses} ) { $self->DisplayClause($i); } $self->join_op->configure( -state => 'normal', ); } # END EditRule ----------------------------------------- sub DisplayClause { my $self = shift; my $i = shift; # Clause index my $clause_list = $self->clause_list; # Get my HList widget my $clause = $self->rule->clauses->[$i]; # Get the clause to displ +ay. # I know that no item exists at HList path $i. $clause_list->add($i, -before=>'new_clause'); # Create the Tix display items. # _W_foobar returns a widget. # different field values have different operator and value widgets +. $clause_list->itemCreate($i, 0, -itemtype => 'window', -widget => $self->_W_select_field($clause, $i), ); $clause_list->itemCreate($i, 1, -itemtype => 'window', -widget => $self->_W_select_op($clause), ); $clause_list->itemCreate($i, 2, -itemtype => 'window', -widget => $self->_W_select_value($clause), ); $clause_list->itemCreate($i,3, -itemtype => 'window', -widget => $self->_W_delete_clause($i), ); }
Any ideas? Comments? Rebukes for my foolishness?
TGI says moo
In reply to Tk, HLists and memory leakage by TGI
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |