Need table that can insert other widgets and delete whole rows

半腔热情 提交于 2019-12-12 05:29:22

问题


Working on a part designer in Perl Tk. Each part has several properties, and each property has over a dozen attributes. Some attributes, like property name, property description, are just text entered in a field, others are chosen from a list of specific values, etc.

I have the program configured so that each property is a new row in a table. Each row has several columns corresponding to the configurable attributes of each property.

Here is my problem.

Using Tk::Table I was able to configure a table where I could insert radio buttons, check buttons, entry widgets, option menus, etc, into any given cell, so that configuring the different types of attributes could be done as easily as possible.

The problem with Tk:Table is that there is no option to delete an entire row, as far as I can tell. I need this option and don't want to write a whole algorithm for it if I can avoid it.

I then tried Tk:TableMatrix, which does have the option to delete an entire row like a spreadsheet does. However, as far as I can tell, I cannot insert widgets into the TableMatrix cells, thus each cell can only be typed in, which does not work for me.

My questions are:

  1. Is there a way to insert other widget types into the TableMatrix cells? If so, my problem is solved.

  2. If not, does anyone know how I can make a table in Perl Tk that can both take different widget types and insert them into cells, and that also has the option to delete entire rows easily?


回答1:


In case anyone in the future finds this post and is stuck in the same predicament, here is how I went about using Tk::Table and implementing a method to delete rows.

Rows to be deleted are selected with a checkbox. An algorithm goes through each checkbox and saves all information in the rows that are not checked. The table is then destroyed and rebuilt with the saved information.

This is just a dummy test program I made to test functionality before implementing it.

#!usr/bin/perl -w

use strict;
use Tk;
use Tk::Table;

my $mw = MainWindow->new;

my $table;
my $teststring = "test123";


my @options = ["A","B","C","D"];
my $choice = "C";
my $bool = 0;
my @rowstokeep;
my $storedrows;


my $tb = $mw->Text(
-background => "white",
-height     => 13.5,
-width      => 48.5
)->pack;

$table = $tb->Table(
-scrollbars     => "sw",
-fixedrows      => 1,
-takefocus      => 1,
-background     => "white",
-rows           => 6,
-columns        => 3
);




$tb->windowCreate('1.0 lineend', -window=>$table);
$tb->configure(-state=>'disabled');

my $printButton = $mw->Button(
-text       => "Print All",
-command    => \&printAll
)->pack;

my $newRowButton = $mw->Button(
-text       => "New Row",
-command    => [\&newRow,$table,$teststring,\@options,$choice,$bool]
)->pack;

my $deleteRowButton = $mw->Button(
-text       => "Delete Selected Rows",
-command    => [\&deleteRow]
)->pack;

my $rowsNumButton = $mw->Button(
-text       => "How Many Rows",
-command    => [\&printNumRows,$table]
)->pack;


my $closeButton = $mw->Button(
-text       => "Close Window",
-command    => sub {exit}
)->pack;



&makeHeaders;


&newRow($table,$teststring,\@options,$choice,$bool);




MainLoop;

sub getTableDim{
  my $tempheight = $table->height;
  my $tempwidth = $table->width;

  print "Table height is $tempheight\n";
  print "Table width is $tempwidth\n";
} #end sub getTableDim

sub makeHeaders{

  $table->put(0,0,"Entry");
  $table->put(0,1,"Option Menu");
  $table->put(0,2,"Check Button");
} #end sub makeHeaders

sub newEntry{
  my ($t,$r,$c,$text) = @_;
  my $e = $t->Entry(
    -textvariable   => \$text,
    -background     => "white"
);
  $t->put($r,$c,$e);
} #end sub newEntry

sub newOptionMenu{
  my ($t,$r,$c,$arr,$disp) = @_;
  my $om = $t->Optionmenu(
    -textvariable   => \$disp,
    -options        => @$arr,
    -background     => "white"
);
  $t->put($r,$c,$om);

} #end sub newOptionMenu

sub newCheckBox{
  my ($t,$r,$c,$v) = @_;
  my $cb = $t->Checkbutton(
    -variable       => \$v,
    -background     => "white"
);
  $t->put($r,$c,$cb);
} #end sub newCheckBox

sub printAll{

my $numRows = $table->totalRows;

for (my $i=1;$i<$numRows;$i++){
  my $out1 = $table->get($i,0)->cget(-textvariable);
  my $out2 = $table->get($i,1)->cget(-textvariable);
  my $out3 = $table->get($i,2)->cget(-variable);

  print "\n\nEntry in row $i is $$out1\n";
  print "Optionmenu in row $i is $$out2\n";
  print "Checkbox in row $i is $$out3\n";
} #end for
} #end sub printAll


sub newRow{

  my ($t,$entrystr,$optionarr,$optionchoice,$checkboxval) = @_;

  my $numRows = $t->totalRows;

  &newEntry($t,$numRows,0,$entrystr);
  &newOptionMenu($t,$numRows,1,$optionarr,$optionchoice);
  &newCheckBox($t,$numRows,2,$checkboxval);

} # end sub newRow


sub printNumRows{
  my ($t) = @_;
  my $numrows = $t->totalRows;
  print "There are now $numrows total rows\n";
} #end sub printNumRows

sub deleteRow{

  @rowstokeep = ();
  @$storedrows = ();

  my $numRows = $table->totalRows;


  for (my $i = 1;$i<$numRows;$i++){
    my $bool = $table->get($i,2)->cget(-variable);
      if (!($$bool)){

    push (@rowstokeep,$i); #push row number into array if checkbox not checked
      } #end if $$bool
  } #end for


  my $size = @rowstokeep;


  if ($size > 0){
  for (my $i = 0;$i<$size;$i++){

    my $entry = $table->get($rowstokeep[$i],0)->cget(-textvariable);
    $storedrows->[$i]->{'Entry'} = $$entry;

    my $option = $table->get($rowstokeep[$i],1)->cget(-textvariable);
    $storedrows->[$i]->{'Option'} = $$option;

    my $cbstatus = $table->get($rowstokeep[$i],2)->cget(-variable);
    $storedrows->[$i]->{'Check'} = $$cbstatus;
  } #end for
  } #end if



  $table->clear;
  $table->destroy; 
  #table needs to be destroyed due to strange bug found with table->clear

  $table = $tb->Table(
  -scrollbars       => "sw",
  -fixedrows        => 1,
  -takefocus        => 1,
  -background       => "white",
  -rows         => 6,
  -columns      => 3
  );



  $tb->windowCreate('1.0 lineend', -window=>$table);
  $tb->configure(-state=>'disabled');

  $newRowButton->configure(
  -command=>[\&newRow,$table,$teststring,\@options,$choice,$bool]);
    #whenever table is destroyed and recreated, all buttons that call it are still pointing 
    #to table's old hash value and need to be reconfigured 
  $rowsNumButton->configure(
  -command=>[\&printNumRows,$table]);


  &makeHeaders;

  my $newsize = @$storedrows;

  if ($newsize>0){
    for (my $i = 0; $i<$newsize;$i++){
      &newRow($table,$storedrows->[$i]->{'Entry'},\@options,
      $storedrows->[$i]->{'Option'},$storedrows->[$i]->{'Check'});
    } #end for
  } #end if
} #end sub deleteRow



回答2:


I've always used HLists for tables (although only with text). $hlist->add to add rows, $hlist->delete to remove them. Bonus, the rows can have (but don't require) a callback on clicking them.

I'm not sure about adding widgets into the cells. The Tk example program widget (which should be installed if you've got Tk) has code that shows a button in a HList cell, so it seems possible. See "Tix Widgets => #7 Multicolumn listbox with individual cell styles".

In the sample code, they call itemCreate with -itemtype=>'window' and then set -widget=>$widget_code I haven't seen much documentation on -widget but it works in the example. I've cleaned this up somewhat from the example code:

$h->itemCreate
          ($e, $col,
           -itemtype => 'window',
           -style => $style,
           -widget => $widget_code
           );


来源:https://stackoverflow.com/questions/27136398/need-table-that-can-insert-other-widgets-and-delete-whole-rows

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!