【问题标题】:How to have multiple text widgets with scrollbars in a frame on tkinter如何在 tkinter 的框架中拥有多个带有滚动条的文本小部件
【发布时间】:2015-06-17 16:56:24
【问题描述】:

我希望我的文本小部件在每个文本小部件中都具有scrollbar 功能。我创建了一个canvas,并在其中嵌入了一个使用create_windowframe。然后我将 2 个文本小部件放入此框架中。我希望每个文本小部件都有一个滚动条,但是当我添加滚动条时,其中一个适合整个框架,而第二个适合一半框架。我将如何解决这个问题?

import tkinter as tk
import os
import tkinter.filedialog
import tkinter.messagebox

class Main(tk.Tk):

def __init__(self, *args, **kwargs):
    '''This initialisation runs the whole program'''
    #textBoxList = []

    tk.Tk.__init__(self, *args, **kwargs)
    self.title('Untitled')
    self.geometry('500x500')
    self.canvas = tk.Canvas(self)
    self.scroll = tk.Scrollbar(self, orient='vertical', command=self.canvas.yview)
    self.canvas.configure(yscrollcommand=self.scroll.set)
    self.frame = tk.Frame(self.canvas) # frame does not get pack() as it needs to be embedded into canvas throught canvas.
    self.scroll.pack(side='right', fill='y')
    self.canvas.pack(fill='both', expand='yes')
    self.canvas.create_window((0,0), window=self.frame, anchor='nw')
    self.frame.bind('<Configure>', self.canvas.configure(scrollregion=self.canvas.bbox('all')))

    # 1st Text Widget
    self.journal = tk.Text(self.frame)
    self.vsb = tk.Scrollbar(self.frame)
    self.vsb.config(command=self.journal.yview)
    self.journal.config(yscrollcommand=self.vsb.set)
    self.vsb.pack(side='right', fill='y')
    self.journal.pack()

    #2nd Text Widget
    self.good = tk.Text(self.frame)
    self.vsb2 = tk.Scrollbar(self.frame)
    self.vsb2.config(command=self.good.yview)
    self.good.config(yscrollcommand=self.vsb2.set)
    self.vsb2.pack(side='right', fill='y')
    self.good.pack()

root = Main()
root.mainloop()

【问题讨论】:

  • 如果没有MCVE,这很难回答。
  • 抱歉,我将代码编辑为 MCVE

标签: python python-3.x tkinter


【解决方案1】:

两个问题(除了粘贴代码时可能刚刚发生的混乱缩进):

  1. frame 绑定到函数的返回值而不是函数本身。您可以使用 lambda 函数解决此问题。
  2. 您正在尝试使用pack() 创建一个复杂的布局。请改用grid()

 

import tkinter as tk
import os
import tkinter.filedialog
import tkinter.messagebox

class Main(tk.Tk):

    def __init__(self, *args, **kwargs):
        '''This initialisation runs the whole program'''
        #textBoxList = []

        tk.Tk.__init__(self, *args, **kwargs)
        self.title('Untitled')
        self.geometry('500x500')
        self.canvas = tk.Canvas(self)
        self.scroll = tk.Scrollbar(self, orient='vertical', command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=self.scroll.set)
        self.frame = tk.Frame(self.canvas) # frame does not get pack() as it needs to be embedded into canvas throught canvas.
        self.scroll.pack(side='right', fill='y')
        self.canvas.pack(fill='both', expand='yes')
        self.canvas.create_window((0,0), window=self.frame, anchor='nw')
        self.frame.bind('<Configure>', lambda x: self.canvas.configure(scrollregion=self.canvas.bbox('all'))) # lambda function

        # 1st Text Widget
        self.journal = tk.Text(self.frame)
        self.vsb = tk.Scrollbar(self.frame)
        self.vsb.config(command=self.journal.yview)
        self.journal.config(yscrollcommand=self.vsb.set)
        self.journal.grid(row=0, column=0) # grid instead
        self.vsb.grid(row=0, column=1, sticky='ns') # grid instead

        #2nd Text Widget
        self.good = tk.Text(self.frame)
        self.vsb2 = tk.Scrollbar(self.frame)
        self.vsb2.config(command=self.good.yview)
        self.good.config(yscrollcommand=self.vsb2.set)
        self.good.grid(row=1, column=0) # grid instead
        self.vsb2.grid(row=1, column=1, sticky='ns') # grid instead

root = Main()
root.mainloop()

【讨论】:

  • 谢谢,您能否扩展问题 1,因为我不太明白:a) 框架如何绑定到返回值 b) 提供 lambda 如何使其绑定到函数
  • 有关更多信息,请参阅this question。基本上,像multiply(2,3) 这样的东西不是函数,它只是数字6lambda 关键字定义了一个函数,基本上用作包装器。
【解决方案2】:

我不确定为什么会发生这种情况,但您可以通过为每个文本/滚动条对创建一个框架来解决它。

    first_text_frame = tk.Frame(self.frame)
    first_text_frame.pack()
    # 1st Text Widget
    self.journal = tk.Text(first_text_frame)
    self.vsb = tk.Scrollbar(first_text_frame)
    self.vsb.config(command=self.journal.yview)
    self.journal.config(yscrollcommand=self.vsb.set)
    self.vsb.pack(side='right', fill='y')
    self.journal.pack()

    second_text_frame = tk.Frame(self.frame)
    second_text_frame.pack()
    #2nd Text Widget
    self.good = tk.Text(second_text_frame)
    self.vsb2 = tk.Scrollbar(second_text_frame)
    self.vsb2.config(command=self.good.yview)
    self.good.config(yscrollcommand=self.vsb2.set)
    self.vsb2.pack(side='right', fill='y')
    self.good.pack()

【讨论】:

    【解决方案3】:

    如果您想拥有两个文本小部件,一个在另一个之上,每个在右侧都有一个滚动条,pack 是几何管理器的错误选择。你应该切换到grid,或者使用一些内部框架来调整。

    您的另一个选择是创建一个自定义类,该类是一个包含一个文本小部件和一个滚动条的框架。然后,创建这个类的两个实例,并将一个放在另一个之上。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多