【问题标题】:Select multiple TCL/TK text widgets at once一次选择多个 TCL/TK 文本小部件
【发布时间】:2017-03-09 07:48:37
【问题描述】:

我正在尝试使用 TCL/TK 创建一个表并在不使用 Tktable 小部件的情况下构建它。

我正在使用画布使用以下提供的方法从头开始构建表格:

simple Tktable

我有一大堆自定义设置,(到目前为止)我觉得如果我在画布中构建表格会更容易,因此我使用这种方法而不是 Tktable。

我的表格将充满只读文本小部件、可编辑文本小部件和一些下拉菜单。

这是我的问题:

1) 如何允许用户同时选择多个文本小部件并检索选择?例如,用户选择了整行/列等。

请看下面的简化代码:

package require Tk

proc makeWindow {} {
    set toplevelWindow .gui
    destroy $toplevelWindow

    ## Make the toplevel window
    toplevel $toplevelWindow
    wm title $toplevelWindow "Test case 1"
    wm minsize $toplevelWindow 200 200
    set pathName $toplevelWindow.testMultiSelection

    ## Create the canvas where I build the table
    destroy $pathName
    frame $pathName

    set col 0
    for {set i 0} {$i < 4} {incr i} {
        set w "$pathName\_$i"
        destroy $w
        text $w -width 9 -height 1 -state normal
        $w insert end $i
        $w configure -state disabled
        grid $w -row $i -column $col -sticky ew
    }
    grid config $toplevelWindow.testMultiSelection -column 0 -row 0 -sticky w
}

makeWindow

在上面的示例中,我希望选择一些数字(基本上类似于 ctrl+select)并以某种方式将选择存储在某处并检索它们以供以后使用。

如果上面的压缩测试用例不清楚,请告诉我。

编辑 1

忘了补充一点,我知道如何使用selection get 命令检索单个文本小部件选择。

【问题讨论】:

    标签: tcl tk


    【解决方案1】:

    默认情况下,一次只能选择一个小部件。如果您在每个小部件的小部件级别关闭选择的导出(配置-exportselection 0),那么您可以接管它的管理。但是,某些平台也不会显示选择,除非小部件具有焦点(由于平台 GUI 规则),因此您可能还需要管理文本标签以应用选择的外观。 (sel 标签是选择;它是专门管理的,但您可以很容易地复制它的外观。)

    请记住,您可以在画布和文本小部件中嵌入小部件(如果子小部件的名称使其成为容器的子级)。 window 子命令和/或项目类型是您在该路线上寻找的内容。

    另一件大事是管理剪贴板。你会想要明确地接管它。通常的命令是clipboard,尽管也可以使用selection 命令(它可以访问剪贴板/选择机制的较低级别部分;剪贴板是CLIPBOARD 选择)。

    了解这一点,您正在做的事情很复杂,并且可能需要相当多的时间和精力。问问自己,您的项目在这种复杂程度下是否真的合理。

    【讨论】:

    • 感谢您的解释。我想我在开始这个项目时被误导了。我现在正在探索其他大型小部件,可用于开发类似仪表板的“Excel”(到目前为止是 Tktable 和 tablelist)。提到的小部件在满足我的需求方面要好得多。
    【解决方案2】:

    这个想法的要点是使用文本标签来标记选定的文本,这样您不仅可以获得选定文本的外观,还可以将该文本标记为“选定”。然后,您的复制操作仅遍历所有文本小部件并获取内容(如果它拥有“已选择”标签)。您可以在获取内容时取消选择选定的文本,方法是删除标签,或者像我在下面所做的那样,按钮命令用自己的撤消命令替换自身。

    因此流程是单击列按钮,该列中的所有文本小部件都将其内容标记为已选中(所选文本是白色背景和黑色前景,因此看起来已选中)单击弹出菜单或访问的菜单按钮所有选定的项目并对内容执行操作,然后单击列按钮取消选择列。所有选定的文本小部件都删除了选定的标签,并恢复了文本的默认外观。

    假设您单击列的顶部(我假设它是一个按钮)并且您知道该列中的文本小部件,您可以使用标签标记每个文本小部件中的文本以指示它已被选中。然后要复制,您可以遍历所有文本小部件并在每个标记的文本小部件中提取内容。取消选择遍历所有文本小部件并取消标记内容。在下面的代码中,我假设我有以下功能: getAllTextWindowPaths - 给我画布中所有 textwidgets 的列表,getAllTextPathsInColumn colnumber - 给我列 $colnumber 中画布中所有 textwidgets 的列表。

    # configure tags for all your text windows 
    
    foreach t [ getAllTextWindowPaths ] { 
      $t tag configure selected -background white -foreground black 
    } 
    # configure the column select button 
    button .canvas.button.column1 -text {1} -command [ list clickColumn                        .canvas.button.column1 1 ]
    
    proc selectText { textpath { select 1 }  } { 
      if { $select == 1 } { 
         $textpath tag add 1.0 end selected
      } else { 
         $textpath tag remove 1.0 end selected
      } 
    }
    
    proc clickColumn { colpath colnum } {
      # now call this click handler for for your column of textwidgets
      # you can make same for a row 
    
      foreach t [getTextPathsInColumn $colnum ] {
         selectText $t 1
      }
      $colpath configure -command [list unclickColumn $colpath $colnum ]
    }
    proc unclickColumn { colpath colnum } {
      # now call this click handler for for your column of textwidgets
      # you can make same for a row 
    
      foreach t [getTextPathsInColumn $colnum ] {
         selectText $t 1
      }
      $colpath configure -command [list clickColumn $colpath $colnum ]
    } 
    
    proc getSelectedContents { } { 
         # im adding to a list all the seleted contents but you can arrange
         # it anyway you want
         set retval {} 
         foreach t [getAllTextWindowPaths ] { 
             if { "selected" in [$t tag names 1.0 ] } { 
                lappend retval [ $t get 1.0 end ] 
             }
         }
        # optional call selectText $t 0  here foreach selected widget
        # to clear selection or handle the column click handler again
        return $retval  
    }
    

    【讨论】:

    • 这是解决问题的好方法。我在两个文本小部件上进行了尝试,它似乎确实有效。无论如何,我仍然认为这对于我的仪表板/表格之类的应用程序来说是一件相当复杂的事情。到目前为止,megawidget tablelist 似乎很好地处理了我的要求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-04
    • 2012-03-10
    相关资源
    最近更新 更多