如何在tkinter的框架中使用带滚动条的多个文本小部件

时间:2015-06-17 16:56:24

标签: python python-3.x tkinter

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

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()

3 个答案:

答案 0 :(得分:1)

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

    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()

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

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

  1. frame绑定到函数的返回值而不是函数本身。您可以使用lambda函数解决此问题。
  2. 您正在尝试使用pack()创建复杂的布局。请改为grid()
  3. 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()