Saturday, 3 February 2018

Scrolling 2 text widgets together

I am using the pack() Geometry Manager to place all of the widgets. I opted for the pack() Manager because it is ideal for placing widgets side by side or drop down position. Fortunately, in a text editor, I have all the widgets Placed next to each other or in descending order. It is therefore advantageous to the pack() Manager. We can do the same with the grid() manager also.

Save Save

# Craig Hammond 2018

import tkinter as tk
from tkinter import *


from tkinter import ttk
import re

class SampleTextApp(Frame):
    def __init__(self, master, **kwargs):# this **kwargs is needed for the scroll bar
        ttk.Frame.__init__(self, master)
        self.file_name = None
        self.grid()
        self.create_widgets()

    def create_widgets(self):

        # font varialble to use with all widgets
        my_font = ('', 18)
        
        # add a text box for the line numbers
        self.line_number_text = Text(self, font=my_font, width=4, padx=3, takefocus=0, border=0, background='yellow', state='disabled', wrap='none')
        self.line_number_text.pack(side='left', fill='y')
        
        # add the main text box widget here
        self.main_text = Text(self, font=my_font, wrap='none')
        self.main_text.bind('<KeyPress>', self.on_text_changed)
        self.main_text.pack(expand='yes', fill='both')
        
        # add a scroll bar for the main text widget
        self.scroll_bar = Scrollbar(self.main_text)
        self.scroll_bar.pack(side='right', fill='y')

        # call the scroll bar functions
        self.scroll_bar['command'] = self.on_scrollbar
        self.line_number_text['yscrollcommand'] = self.on_textscroll
        self.main_text['yscrollcommand'] = self.on_textscroll
# this will update the line numbers any time you
        # press a key on the keyboard
        self.main_text.bind('<Any-KeyPress>', self.on_text_changed)
        self.main_text.focus_set()
   
    def on_scrollbar(self, *args):
        self.line_number_text.yview(*args)
        self.main_text.yview(*args)
        
    def on_textscroll(self, *args):
        # Moves scrollbar and scrolls text widgets when the mouse wheel
        # is moved on the text widget
        self.scroll_bar.set(*args)
        self.on_scrollbar('moveto', args[0])
        
    def on_text_changed(self, event=None):
        self.update_line_numbers()
    
    def get_line_numbers(self):
        output = ''
        row, col = self.main_text.index("end").split('.')
        for i in range(1, int(row)):
            output += str(i) + '\n'
        return output

    def update_line_numbers(self, event=None):
        line_numbers = self.get_line_numbers()
        # disables the text widget so the widget does not scroll
        self.main_text.config(state='disabled')
        self.line_number_text.config(state='normal') 
        self.line_number_text.delete('1.0', 'end')
        self.line_number_text.insert('1.0', line_numbers)
        self.line_number_text.config(state='disabled')
        # returns the text widget back to normal
        self.main_text.config(state='normal')

root = Tk()
PROGRAM_NAME = ' My Text Editor '
root.title(PROGRAM_NAME)
root.geometry("600x300")
app = SampleTextApp(root)
app.pack(fill='both', expand='yes')
app.mainloop()

No comments:

Post a Comment