需要可以插入其他小部件并删除整行的表

时间:2014-11-25 20:47:54

标签: perl tk

在Perl Tk工作的零件设计师。每个部分都有几个属性,每个属性都有十几个属性。某些属性(如属性名称,属性描述)只是在字段中输入的文本,其他属性是从特定值列表中选择的等等。

我已配置程序,以便每个属性都是表中的新行。每行有几列对应于每个属性的可配置属性。

这是我的问题。

使用Tk :: Table我能够配置一个表格,我可以将单选按钮,复选按钮,条目小部件,选项菜单等插入到任何给定的单元格中,以便配置不同类型的属性可以作为尽可能容易。

Tk:Table的问题是,据我所知,没有删除整行的选项。我需要这个选项,如果可以避免,我不想为它编写完整的算法。

然后我尝试了Tk:TableMatrix,它可以选择像电子表格那样删除整行。但是,据我所知,我不能将小部件插入TableMatrix单元格,因此每个单元格只能输入,这对我不起作用。

我的问题是:

  1. 有没有办法将其他窗口小部件类型插入TableMatrix单元格?如果是这样,我的问题就解决了。

  2. 如果没有,有没有人知道如何在Perl Tk中创建一个表,它可以采用不同的小部件类型并将它们插入到单元格中,还可以选择轻松删除整行?

2 个答案:

答案 0 :(得分:2)

如果将来有人发现这篇文章并陷入同样的​​困境,那么我就是如何使用Tk :: Table并实现删除行的方法。

使用复选框选择要删除的行。算法遍历每个复选框并将所有信息保存在未检查的行中。然后使用保存的信息销毁并重建该表。

这只是我在实现之前测试功能的虚拟测试程序。

#!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

答案 1 :(得分:0)

我总是将HLists用于表格(尽管只有文字)。 $hlist->add添加行$hlist->delete以删除它们。奖励,行可以有(但不要求)点击它们的回调。

我不确定将小部件添加到单元格中。 Tk示例程序widget(如果您已经获得Tk则应该安装)具有显示HList单元格中的按钮的代码,因此它似乎是可能的。请参阅&#34; Tix Widgets =&gt; #7具有单个单元格样式的多列列表框&#34;。

在示例代码中,他们使用itemCreate调用-itemtype=>'window',然后设置-widget=>$widget_code我在-widget上看不到很多文档,但它在示例中有效。我已经从示例代码中稍微清理了一下:

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