6

I'm trying to create a simple word processor for starters to learn Python a bit better.

I'm using the Tkinter Text widget for the main editing program, the only problem is the height and width are defined by characters.

This creates a problem when I change fonts, for not all fonts are the same width.

Every time the font is changed, the Text widget re-sizes, although technically it is the same width and height. This looks ridiculous when trying to type up something, I'm trying to make the word processor as nice as possible.

Is there a way to define the width and height in pixels?

the .grid_propagate(False) is not useful for the size is technically not changing, only the character width.

I'm trying to stay away from wxPython for now, since everything I've done up to this point has been in Tkinter.

I have done endless hours of extensive googling but have found no solutions.

nbro
  • 15,395
  • 32
  • 113
  • 196
reallycoolnerd
  • 105
  • 2
  • 7

3 Answers3

12

You are wrong when you say you can't use grid_propagate(False), because you can. grid_propagate is related to the actual size, not the size attribute. Also, if you simply give your application a fixed size using wm_geometry, font changes won't affect the size of the window.

Here's an example using grid_propagate, which sets the container to a fixed size in pixels:

import Tkinter as tk
import tkFont

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self._textFont = tkFont.Font(name="TextFont")
        self._textFont.configure(**tkFont.nametofont("TkDefaultFont").configure())

        toolbar = tk.Frame(self, borderwidth=0)
        container = tk.Frame(self, borderwidth=1, relief="sunken", 
                             width=600, height=600)
        container.grid_propagate(False)
        toolbar.pack(side="top", fill="x")
        container.pack(side="bottom", fill="both", expand=True)

        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        text = tk.Text(container, font="TextFont")
        text.grid(row=0, column=0, sticky="nsew")

        zoomin = tk.Button(toolbar, text="+", command=self.zoom_in)
        zoomout = tk.Button(toolbar, text="-", command=self.zoom_out)
        zoomin.pack(side="left")
        zoomout.pack(side="left")

        text.insert("end", '''Press te + and - buttons to increase or decrease the font size''')

    def zoom_in(self):
        font = tkFont.nametofont("TextFont")
        size = font.actual()["size"]+2
        font.configure(size=size)

    def zoom_out(self):
        font = tkFont.nametofont("TextFont")
        size = font.actual()["size"]-2
        font.configure(size=max(size, 8))

if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • I was referring to the grid_propagate not working with the Text widget. Technically it works but it still expands because its width is in Characters, and so it stays the same length in characters, but not all the character sizes are the same. The text widget does not fill my entire window, i wanted there to be space to add Buttons later on. The problem is the actual 'Text' Widget keeps re-sizing to meet the needs of each and every different font. It looks silly when typing something and changing the font and seeing the text widget expanding and contracting. – reallycoolnerd Mar 24 '12 at 00:24
  • @reallycoolnerd: I'm sorry, but you're incorrect about `grid_propagate`. It has nothing to do with the size attribute, it has everything to do with the actual size of the widget. If you can show code where you try to use `grid_propagate` and it doesn't work, we can fix it. It sounds like you don't understand how `grid_propagate` works. You do realize that you have to call it on the parent? It has no effect calling `grid_propagate` on the text widget itself. – Bryan Oakley Mar 24 '12 at 01:00
  • @reallycoolnerd: is there something about my example that is confusing to you? The example clearly shows how I am able to set the size of the text widget in pixels by setting the size of its container and turning geometry propagation off. Perhaps if you can explain why you don't understand the example then I can figure out how to improve it. – Bryan Oakley Mar 24 '12 at 01:06
  • I looked at the example, and the example works fine if the text widget is set to fill the window. However I changed the code so that the widget did not fill the window, and the very same thing happened where the textbox re-sized to the contours of the text. I called the grid_propagate to the parent of my text widget. Although i have tried once before without success, is it possible to Put the widget inside a frame or canvas and use the grid_propagate without the text widget re-sizing? – reallycoolnerd Mar 24 '12 at 04:48
  • I will try to upload my code tomorrow, my computer is being stubborn and I am very tired. Sorry for this delay. – reallycoolnerd Mar 24 '12 at 04:59
  • 1
    @reallycoolnerd: just because the text widget fills the frame doesn't mean you can't use other widgets. Think of the frame and the text widget as a single widget. You can put that combination in yet another frame so that you can add additional widgets. My example illustrates that -- there are buttons and a toolbar in addition to the text/frame combination. – Bryan Oakley Mar 24 '12 at 13:14
  • hmm, I think I understand what you are saying. So I should be able to add frames on either side of the frame in the middle and use buttons. As soon as i can i shall try that out. Also, I see that you used the .pack method and the .grid method. Can you use both as long as you use one type within the same parent? Such as having a textbox in a frame that uses pack and a button in a different frame using grid? The other times I used both in the same parent frame, it refused to load it. Thank you for putting up with my questions. – reallycoolnerd Mar 24 '12 at 13:19
  • @reallycoolnerd: yes, you can add frames on either side of the middle frame. And yes, you can use `pack` and `grid` in the same application. I use both in probably every GUI I've ever written. The only rule is that you can't use them both on the same master. – Bryan Oakley Mar 24 '12 at 13:22
  • Thank you very much, I was able to get it Working! You have taught me very much that I will be able to apply in the future. Again, Thank you very much, – reallycoolnerd Mar 24 '12 at 17:05
  • 1
    @reallycoolnerd: if you like this answer, vote it up. If it solves your problem, accept it by clicking on the checkmark next to the answer. Doing so lets others know they don't need to try and give you a different answer. For more information see http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work – Bryan Oakley Mar 24 '12 at 21:13
  • @BryanOakley I am having difficulty with a [similar problem](http://stackoverflow.com/questions/37915393/how-to-stop-window-readjusting-its-size-based-on-the-text-size-inside-it), I have tried your suggestion, but I am still having problems, what am I missing? – 3kstc Jun 20 '16 at 06:08
0

..tested this: this works on the frame size, but not on the (scrolled)text-widgets size. my setup is a bit more complicated, with a masterframe for 2 sites, mainframes for each site and frames with various content, i.a. a scrolledtext widget.

adding grid_propagate, *_row- and *_columnconfigure warded the masterframe from resizing, even with adding grid options to main- and contentframes, what results in warding the mainframe to resize.. when changing the font, the widgetsize also changes - and, in the last example, the scrolledtext-widget disappears behind the frame on its right side (containing other widgets)..

  • workaround is -of course- adjusting height (/lines) and width (/letters per line) 'til everything fits. (..sorry: forgot to mention..) –  Jun 12 '19 at 11:22
0

Use the pack geometry manager to pack the widgets.

I was creating a notepad and wanted the font sample area to display the font size. So I created a label frame and added a label in it - i.e. AabYyZz - to display the font sample. 

When I increased the font size the size of the label frame also increased, so I've tried the .pack_propagate method and it worked.

jupiterbjy
  • 2,882
  • 1
  • 10
  • 28