tkinter - 滚动条连接到文本小部件可见,但没有滑块

142 阅读3分钟

在构建一个需要显示大量文本的程序时,需要将滚动条附加到文本小部件。使用 Windows 7、python 3.3。以下是所使用代码的最小示例:

import datetime
import tkinter as tk
import tkinter.messagebox as tkm
import sqlite3 as lite


class EntriesDisplayArea(tk.Text):
    """
    Display area for the ViewAllEntriesInDatabaseWindow
    """
    def __init__(self,parent):
        tk.Text.__init__(self, parent,
                           borderwidth = 3,
                           height = 500,
                         width = 85,
                         wrap = tk.WORD)
        self.parent = parent



class EntriesDisplayFrame(tk.Frame):
    """
    Containing frame for the text DisplayArea
    """
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, relief = tk.SUNKEN,
                          width = 200,
                          borderwidth = 2)
        self.parent = parent
        self.grid(row = 0, column = 0)

        self.entriesDisplayArea = EntriesDisplayArea(self)
        self.entriesDisplayArea.grid(row = 1, column = 0, sticky = 'ns')
        self.scrollVertical = tk.Scrollbar(self, orient = tk.VERTICAL,
                                           command = self.entriesDisplayArea.yview)


        self.entriesDisplayArea.config(yscrollcommand = self.scrollVertical.set)
        for i in range(1000):
            self.entriesDisplayArea.insert(tk.END,'asdfasdfasdfasdfasdfasdfasdfasdfasdfasdf')
        self.scrollVertical.grid(row=1,column=1,sticky = 'ns')

class ViewAllEntriesInDatabaseWindow(tk.Toplevel):
    """
    Window in which the user can view all of the entries entered ever
    entered into the database.
    """
    def __init__(self, parent = None):
        tk.Toplevel.__init__(self,parent,
                             height = 400,
                             width = 400)
        self.grid()
        self.entriesDisplayFrame = EntriesDisplayFrame(self)

if __name__ == '__main__':
    t0 = ViewAllEntriesInDatabaseWindow(None)

运行上述代码后,滚动条可见,但没有滑块。

2. 解决方案

该问题有两个原因:

  1. 将文本小部件的高度设置为 500。该值表示字符而不是像素,因此将其设置为几千个像素的高度。
  2. 只插入一行文本,尽管文本长度为 40,000 个字符。

要解决这个问题,可以将高度设置为更合理的值,如 50,并在插入的数据中插入换行符,这样滚动条就会开始正常工作。

修改后的代码如下:

import datetime
import tkinter as tk
import tkinter.messagebox as tkm
import sqlite3 as lite


class EntriesDisplayArea(tk.Text):
    """
    Display area for the ViewAllEntriesInDatabaseWindow
    """
    def __init__(self,parent):
        tk.Text.__init__(self, parent,
                           borderwidth = 3,
                           height = 50,
                         width = 85,
                         wrap = tk.WORD)
        self.parent = parent



class EntriesDisplayFrame(tk.Frame):
    """
    Containing frame for the text DisplayArea
    """
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, relief = tk.SUNKEN,
                          width = 200,
                          borderwidth = 2)
        self.parent = parent
        self.grid(row = 0, column = 0)

        self.entriesDisplayArea = EntriesDisplayArea(self)
        self.entriesDisplayArea.grid(row = 1, column = 0, sticky = 'ns')
        self.scrollVertical = tk.Scrollbar(self, orient = tk.VERTICAL,
                                           command = self.entriesDisplayArea.yview)


        self.entriesDisplayArea.config(yscrollcommand = self.scrollVertical.set)
        for i in range(1000):
            self.entriesDisplayArea.insert(tk.END,'asdfasdfasdfasdfasdfasdfasdfasdfasdfasdf\n')
        self.scrollVertical.grid(row=1,column=1,sticky = 'ns')

class ViewAllEntriesInDatabaseWindow(tk.Toplevel):
    """
    Window in which the user can view all of the entries entered ever
    entered into the database.
    """
    def __init__(self, parent = None):
        tk.Toplevel.__init__(self,parent,
                             height = 400,
                             width = 400)
        self.grid()
        self.entriesDisplayFrame = EntriesDisplayFrame(self)

if __name__ == '__main__':
    t0 = ViewAllEntriesInDatabaseWindow(None)
在构建一个需要显示大量文本的程序时,需要将滚动条附加到文本小部件。使用 Windows 7、python 3.3。以下是所使用代码的最小示例:

```python
import datetime
import tkinter as tk
import tkinter.messagebox as tkm
import sqlite3 as lite


class EntriesDisplayArea(tk.Text):
    """
    Display area for the ViewAllEntriesInDatabaseWindow
    """
    def __init__(self,parent):
        tk.Text.__init__(self, parent,
                           borderwidth = 3,
                           height = 500,
                         width = 85,
                         wrap = tk.WORD)
        self.parent = parent



class EntriesDisplayFrame(tk.Frame):
    """
    Containing frame for the text DisplayArea
    """
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, relief = tk.SUNKEN,
                          width = 200,
                          borderwidth = 2)
        self.parent = parent
        self.grid(row = 0, column = 0)

        self.entriesDisplayArea = EntriesDisplayArea(self)
        self.entriesDisplayArea.grid(row = 1, column = 0, sticky = 'ns')
        self.scrollVertical = tk.Scrollbar(self, orient = tk.VERTICAL,
                                           command = self.entriesDisplayArea.yview)


        self.entriesDisplayArea.config(yscrollcommand = self.scrollVertical.set)
        for i in range(1000):
            self.entriesDisplayArea.insert(tk.END,'asdfasdfasdfasdfasdfasdfasdfasdfasdfasdf')
        self.scrollVertical.grid(row=1,column=1,sticky = 'ns')

class ViewAllEntriesInDatabaseWindow(tk.Toplevel):
    """
    Window in which the user can view all of the entries entered ever
    entered into the database.
    """
    def __init__(self, parent = None):
        tk.Toplevel.__init__(self,parent,
                             height = 400,
                             width = 400)
        self.grid()
        self.entriesDisplayFrame = EntriesDisplayFrame(self)

if __name__ == '__main__':
    t0 = ViewAllEntriesInDatabaseWindow(None)
```


运行上述代码后,滚动条可见,但没有滑块。


## 2. 解决方案

该问题有两个原因:

1. 将文本小部件的高度设置为 500。该值表示字符而不是像素,因此将其设置为几千个像素的高度。
2. 只插入一行文本,尽管文本长度为 40,000 个字符。

要解决这个问题,可以将高度设置为更合理的值,如 50,并在插入的数据中插入换行符,这样滚动条就会开始正常工作。

修改后的代码如下:

```python
import datetime
import tkinter as tk
import tkinter.messagebox as tkm
import sqlite3 as lite


class EntriesDisplayArea(tk.Text):
    """
    Display area for the ViewAllEntriesInDatabaseWindow
    """
    def __init__(self,parent):
        tk.Text.__init__(self, parent,
                           borderwidth = 3,
                           height = 50,
                         width = 85,
                         wrap = tk.WORD)
        self.parent = parent



class EntriesDisplayFrame(tk.Frame):
    """
    Containing frame for the text DisplayArea
    """
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, relief = tk.SUNKEN,
                          width = 200,
                          borderwidth = 2)
        self.parent = parent
        self.grid(row = 0, column = 0)

        self.entriesDisplayArea = EntriesDisplayArea(self)
        self.entriesDisplayArea.grid(row = 1, column = 0, sticky = 'ns')
        self.scrollVertical = tk.Scrollbar(self, orient = tk.VERTICAL,
                                           command = self.entriesDisplayArea.yview)


        self.entriesDisplayArea.config(yscrollcommand = self.scrollVertical.set)
        for i in range(1000):
            self.entriesDisplayArea.insert(tk.END,'asdfasdfasdfasdfasdfasdfasdfasdfasdfasdf\n')
        self.scrollVertical.grid(row=1,column=1,sticky = 'ns')

class ViewAllEntriesInDatabaseWindow(tk.Toplevel):
    """
    Window in which the user can view all of the entries entered ever
    entered into the database.
    """
    def __init__(self, parent = None):
        tk.Toplevel.__init__(self,parent,
                             height = 400,
                             width = 400)
        self.grid()
        self.entriesDisplayFrame = EntriesDisplayFrame(self)

if __name__ == '__main__':
    t0 = ViewAllEntriesInDatabaseWindow(None)
```
````