6

Question

  1. How can I change the justification of specific lines in the ScrolledText widget in Tkinter?
  2. What was the reason for my original errors?

Background

I am currently working on a Tkinter Text box application, and am looking for ways to change the justification of a line. Ultimately, I want to be able to change specific lines from LEFT ALIGN to RIGHT ALIGN to etc. For now, I simply need to find out how to change the justification of the entire text box, though further help will be greatly appreciated. I have been using Effbot.org to help me in my quest. Here is my code for the ScrolledText widget:

Code

def mainTextFUN(self):
    self.maintextFrame = Frame (root, width = 50, height = 1,
                           )

    self.maintextFrame.grid(row = 1, column = 1, sticky = N, columnspan = 1,
                            rowspan = 1)

    self.write = ScrolledText(self.maintextFrame,
                              justify(CENTER),
                              width = 100, height = 35, relief = SUNKEN,
                              undo = True, wrap = WORD,
                              font = ("Times New Roman",12),
                              )
    self.write.pack()

When I run this, I get an error.

Traceback (most recent call last):
  File "D:\Python Programs\Text Editor\MyTextv5.py", line 132, in <module>
    app = Application(root)
  File "D:\Python Programs\Text Editor\MyTextv5.py", line 16, in __init__
    self.mainTextFUN()
File "D:\Python Programs\Text Editor\MyTextv5.py", line 57, in mainTextFUN
justify(CENTER),
NameError: global name 'justify' is not defined
>>> 

If I change the justify argument to after the font argument, I get a different error in the form of a messagebox.

There's an error in your program:
*** non-keyword arg after keyword arg (MyTextv5.py, line 61)

EDIT

I changed the code based on a suggestion by abarnert. I added justify = CENTER, after self.maintextFrame. Despite this, I simply got another error.

Traceback (most recent call last):
  File "D:\Python Programs\Text Editor\MyTextv5.py", line 132, in <module>
    app = Application(root)
  File "D:\Python Programs\Text Editor\MyTextv5.py", line 16, in __init__
    self.mainTextFUN()
  File "D:\Python Programs\Text Editor\MyTextv5.py", line 60, in mainTextFUN
    font = ("Times New Roman",12),
  File "C:\Python27\lib\lib-tk\ScrolledText.py", line 26, in __init__
    Text.__init__(self, self.frame, **kw)
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 2827, in __init__
    Widget.__init__(self, master, 'text', cnf, kw)
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1974, in __init__
    (widgetName, self._w) + extra + self._options(cnf))
TclError: unknown option "-justify"
xxmbabanexx
  • 8,256
  • 16
  • 40
  • 60

4 Answers4

14

You're using an option named justify, but no such option exists for the text widget. Are you reading some documentation somewhere that says justify is a valid option? If so, you need to stop reading that documentation.

There is, however, a justify option for text tags. You can configure a tag to have a justification, then apply that tag to one or more lines. I've never used a ScrolledText widget so I don't know if it has the same methods as a plain text widget, but with a plain text widget you would do something like this:

t = tk.Text(...)
t.tag_configure("center", justify='center')
t.tag_add("center", 1.0, "end")

In the above example, we are creating and configuring a tag named "center". Tags can have any name that you want. For the "center" tag we're giving it a justification of "center", and then applying that tag to all the text in the widget.

You can tag individual lines by adjusting the arguments to the tag_add method. You can also give a list of tags when inserting text using the insert method.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • What do you mean by `tags`? Are you saying that that allows me to format the document with greater precision, or something else? In any case, please elaborate further! – xxmbabanexx Feb 23 '13 at 08:18
  • @xxmbabanexx: tags let you associate fonts, colors, margins, justification, baseline offsets, word wrapping and more on a character-by-character and line-by line basis. Search for "Tags" here: http://effbot.org/tkinterbook/text.htm – Bryan Oakley Feb 23 '13 at 12:36
5

It is easy to understand why trying to set justify=CENTER for a Text widget fails: there is no such option for the widget.

What you want is to create a tag with the parameter justify. Then you can insert some text using that tag (or you can insert any text and later apply the tag to a certain region):

import Tkinter

root = Tkinter.Tk()
text_widget = Tkinter.Text()
text_widget.pack(fill='both', expand=True)

text_widget.tag_configure('tag-center', justify='center')
text_widget.insert('end', 'text ' * 10, 'tag-center')

root.mainloop()
mmgp
  • 18,901
  • 3
  • 53
  • 80
  • 1
    What do you mean by `tags`? Are you saying that that allows me to format the document with greater precision, eg.(in SO ** ** allows me to make something **bold**) or something else? In any case, please elaborate further! – xxmbabanexx Feb 23 '13 at 08:19
2

The problem is your Python syntax, not anything related to tkinter:

self.write = ScrolledText(self.maintextFrame,
                          justify(CENTER),
                          width = 100, height = 35, relief = SUNKEN,

That's not how you pass a keyword argument justify with value CENTER; you're passing a positional argument, with value justify(CENTER). So, Python tries to calculate justify(CENTER) by looking for a function named justify, doesn't find one, and raises a NameError.

Moving it doesn't help, it just means you get a SyntaxError before you can even get to the NameError, because you've got a positional argument justify(CENTER) after the keyword argument font, and that's not allowed.

The right way to do it is the same way you're passing all the other keyword arguments in the very next line:

self.write = ScrolledText(self.maintextFrame,
                          justify = CENTER,
                          width = 100, height = 35, relief = SUNKEN,

By the way changing the justification to CENTER isn't going to change anything from left-aligned to right-aligned; it's going to change it from left-aligned to centered. Are you sure you didn't want RIGHT?


Once you've fixed the syntax problems, you've got a new problem, which is related to tkinter. The ScrolledText class just passes through its keyword params to the Text class, and the Text widget doesn't have a justify parameter.

If you read the docs, justify is used as a tag associated with a range of text, not with the widget. So, you have to use tag_config with the justify property to create a named tag config, then you can apply it to ranges of text inside the widget, as the examples show. So:

self.write.tag_config('justified', justify=RIGHT)
self.write.insert(INSERT, 'Ancients of Mu-Mu', 'justified')

And of course this directly answers your other question:

How can I change the justification of specific lines in the ScrolledText widget in Tkinter?

Either insert them with the right tag in the first place, or select them and apply the tag after the fact.

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • 1
    I added `justify = CENTER` to my code, but simply got another error. I am running python 2.7.3, if that matters. – xxmbabanexx Feb 22 '13 at 01:08
1

What maybe confusing people is that the documentation at http://effbot.org/tkinterbook/text.htm, referred to above, does in fact list justify as an option for the Text widget and maybe there was at one time, (seems like an option a text widget should have) but the documentation at http://www.tcl.tk/man/tcl8.4/TkCmd/text.htm does not list a justify option, only the -justify tag. Note that a Label widget can handle multi-line text and does have a -justify option.

sulai
  • 5,204
  • 2
  • 29
  • 44
Wiley
  • 1,156
  • 7
  • 4
  • No, that documentation doesn't list justify as an option for the widget. It _does_ list it as an option for tags, however. Search for the word "justify" and the only place it appears is on the section related to tags. The page very clearly states "The following options are used with tag_config to specify the visual style for text using a certain tag." – Bryan Oakley Apr 22 '13 at 13:58