【问题标题】:Is there a way to clone a tkinter widget?有没有办法克隆 tkinter 小部件?
【发布时间】:2017-09-30 18:48:15
【问题描述】:

我正在尝试创建小部件网格。这个小部件网格以标签开始,告诉我它们的坐标。然后,我有一个将替换它们的按钮的起点和终点列表。 假设我有一个从 (0, 0) 到 (0, 2) 的按钮,我从该位置删除标签并在那里放置一个具有正确行跨度的按钮。 如果一个按钮将替换另一个按钮(不仅仅是标签),我创建一个框架,然后我想克隆按钮作为更改父级的一种方式(我已经阅读过 tkinter 不可能)并添加框架的新按钮也是如此。然后框架将用并排而不是重叠的按钮替换网格上的小部件(标签和旧按钮)。

所以这个example image 显示了一个标签网格,然后是第一个按钮的放置位置,然后是第二个按钮的位置,以及两个按钮并排放置的结果框架。

对我来说最大的问题是必须删除第一个按钮并将其重新放置在网格上,因为无法更改小部件的父级。尽管我也欢迎在网格上并排放置按钮的更好想法。

【问题讨论】:

  • 您无法更改小部件的父级,但您可以更改另一个小部件位于哪个小部件内部。这会解决你的问题吗?真的不清楚你的问题到底是什么。
  • @Bryan Oakley 如何更改另一个小部件位于哪个小部件中?现在我正在循环浏览整个窗口的 F​​rame.grid_slaves() (我在一个名为 info 的变量中对此进行描述)并利用它提供的信息来重新创建按钮。当我找到正确的 info["row"] 和 info["column"] 时,我正在使用此信息创建一个新按钮,但这只是有关此按钮如何放置在网格上的信息。不是像文本那样的按钮信息。
  • “如何更改另一个小部件位于哪个小部件中?” - 几何管理器都接受in_ 参数来指定放置小部件的位置。直接来自文档的规则:“每个从属的主控必须是从属的父级(默认)或从属的父级的后代。”
  • 因此,如果我创建一个与我要克隆的 Button 具有相同父级的 Frame,我可以将按钮的 in_ 参数更改为包含在新 Frame 中,因为它的父级是也是 Button 的父级?
  • 试试看。

标签: python-3.x tkinter


【解决方案1】:

没有直接克隆小部件的方法,但 tkinter 提供了一种方法来确定小部件的父级、小部件的类以及小部件的所有配置值。此信息足以创建副本。

看起来像这样:

def clone(widget):
    parent = widget.nametowidget(widget.winfo_parent())
    cls = widget.__class__

    clone = cls(parent)
    for key in widget.configure():
        clone.configure({key: widget.cget(key)})
    return clone

【讨论】:

    【解决方案2】:

    要扩展answer by Bryan Oakley,这里有一个函数可以让你完全克隆一个小部件,包括它的所有孩子:

    def clone_widget(widget, master=None):
        """
        Create a cloned version o a widget
    
        Parameters
        ----------
        widget : tkinter widget
            tkinter widget that shall be cloned.
        master : tkinter widget, optional
            Master widget onto which cloned widget shall be placed. If None, same master of input widget will be used. The
            default is None.
    
        Returns
        -------
        cloned : tkinter widget
            Clone of input widget onto master widget.
    
        """
        # Get main info
        parent = master if master else widget.master
        cls = widget.__class__
    
        # Clone the widget configuration
        cfg = {key: widget.cget(key) for key in widget.configure()}
        cloned = cls(parent, **cfg)
    
        # Clone the widget's children
        for child in widget.winfo_children():
            child_cloned = clone_widget(child, master=cloned)
            if child.grid_info():
                grid_info = {k: v for k, v in child.grid_info().items() if k not in {'in'}}
                child_cloned.grid(**grid_info)
            elif child.place_info():
                place_info = {k: v for k, v in child.place_info().items() if k not in {'in'}}
                child_cloned.place(**place_info)
            else:
                pack_info = {k: v for k, v in child.pack_info().items() if k not in {'in'}}
                child_cloned.pack(**pack_info)
    
        return cloned
    

    例子:

    root = tk.Tk()
    
    frame = tk.Frame(root, bg='blue', width=200, height=100)
    frame.grid(row=0, column=0, pady=(0, 5))
    
    lbl = tk.Label(frame, text='test text', bg='green')
    lbl.place(x=10, y=15)
    
    cloned_frame = clone_widget(frame)
    cloned_frame.grid(row=1, column=0, pady=(5, 0))
    
    root.mainloop()
    

    给予:

    【讨论】:

      猜你喜欢
      • 2011-04-20
      • 1970-01-01
      • 2022-10-13
      • 1970-01-01
      • 1970-01-01
      • 2021-03-18
      • 1970-01-01
      • 2014-05-17
      • 1970-01-01
      相关资源
      最近更新 更多