-1

I'm surely misunderstanding something with pack and grid... I'm making the GUI for a python application that get debug messages in multiple terminal-like consoles. Making a Tkinter GUI is new to

First of all why do I need to pack buttonframe to have it shown? Shouldn't grid be equivalent to pack?

The GUI is made of a series of buttons on top in the buttonframe and a series of vertical consoles below showing up in columns. Instead what I get is all the consoles stacked vertically.

The consoles are frames with text inside which is written by other threads in the application.

If I don't grid the consoles[idx] it doesn't change (so I assume it doesn't work). If I don't pack the consoles[idx] the GUI starts flickering.

Please note that if I instead call create_Hterms, which instead stacks vertically a bunch of horizontal consoles.

How do I correctly put my consoles as vertical columns?

import Tkinter as tikei

NCONSOLES = 4
HORZ_CONSOLE_W = 10
HORZ_CONSOLE_H = 12

# FakeConsole: one of the consoles that are spawned by MainWindow.
class FakeConsole(tikei.Frame): # from Kevin in http://stackoverflow.com/questions/19479504/how-can-i-open-two-consoles-from-a-single-script
    def __init__(self, root, cust_width, cust_height, *args, **kargs):
        tikei.Frame.__init__(self, root, *args, **kargs)
        self.grid(row=0)

        #white text on black background
        self.text = tikei.Text(root, bg="black", fg="white", width=cust_width, height=cust_height)
        self.text.grid(row=0)
        self.text.insert(tikei.END, 'ASD')
        self.text.see(tikei.END)

    def clearConsole(self):
        self.text.delete(1.0,tikei.END)



class MainWindow(tikei.Frame):
    counter = 0
    consoles = []
    consoleFormat = ''
    e_Vvar = ''
    e_Hvar = ''
    var1 = ''
    ctrlCmdRecipient = ''

    def __init__(self, *args, **kwargs):
        tikei.Frame.__init__(self, *args, **kwargs)
        self.consoleFormat = 'H'
        self.cF = tikei.StringVar()

        self.grid(row=0)

        self.buttonframe = tikei.Frame(self)
        self.buttonframe.grid(row=0)
        tikei.Button(self.buttonframe, text = "Clear Consoles", command=self.clearConsoles).grid(row=0, column=0)
        tikei.Button(self.buttonframe, text = "start").grid(row=0, column=1)
        tikei.Button(self.buttonframe, text = "stop").grid(row=0, column=2)

        self.consoleFrame = tikei.Frame(self)

        self.create_Hterms()

        self.consoleFrame.grid(row=1)

        # create a status bar
        self.statusTxt = tikei.StringVar()
        self.statusTxt.set('-')
        self.statusLab = tikei.Label(self.buttonframe, text="Status: ", anchor=tikei.W, height=1).grid(row=1, column=0, sticky=tikei.W)
        self.statusBar = tikei.Label(self.buttonframe, textvariable=self.statusTxt, anchor=tikei.W, height=1).grid(row=1, column=1, columnspan=4, sticky=tikei.W)


    def clearConsoles(self):
        for i in range(NCONSOLES):
            self.consoles[i].clearConsole()

    def create_Hterms(self):
        ctr = NCONSOLES
        idx = 0

        cons_w = HORZ_CONSOLE_W
        cons_h = HORZ_CONSOLE_H

        while ctr > 0:
            self.consoles.append(FakeConsole(self.consoleFrame, cons_w, cons_h)) # 
            self.consoles[idx].grid(row=idx+1, column=0)
            ctr -= 1
            idx += 1
        return idx+1



root = tikei.Tk()
mainTk = MainWindow(root)
root.wm_title("TOOLS")
mainTk.grid(row=0)
root.mainloop()
  • I'm having some trouble running your code. The indentation isn't right, `self` on line 3 is undefined, there's no colon after `def create_Vterms()` and it's missing its `self` parameter, `self.clearConsoles` doesn't exist, `NCONSOLES` and `VERT_CONSOLE_W` and `VERT_CONSOLE_H` are not defined, and `threading` is used but not imported. Please [provide code](http://sscce.org/) that can be copy and pasted and run, which exhibits your problem. – Kevin Jun 20 '14 at 17:56
  • Don't use `pack()` and `grid()` on the same element ! `pack()` and `grid()` are mutually exclusive. – furas Jun 20 '14 at 18:24
  • You have a considerable number of syntactic flaws. This can't possibly be your actual code. Can you please give us code that runs? – Bryan Oakley Jun 20 '14 at 21:38
  • Ok, I'm sorry about the badly formatted code, I edited a working example also cleaning any reference to pack(). Yet I obtain the same result. – KeinReverb Leonardo Gabrielli Jun 23 '14 at 13:51

1 Answers1

0

First of all why do I need to pack buttonframe to have it shown? Shouldn't grid be equivalent to pack?

No, generally speaking you do not need to pack buttonframe to have it shown. Use pack or grid, but not both on the same widget. In this specific case, however, the use of pack masks bugs deeper in your code, and makes it seem like calling pack is required.

The problem is that you use pack for self.consoleFrame, and both self.consoleFrame and self.buttonFrame have the same parent. Because they share the same parent you must use either pack or grid for both.

The GUI is made of a series of buttons on top in the buttonframe and a series of vertical consoles below showing up in columns. Instead what I get is all the consoles stacked vertically.

This is because you use grid, and then you use pack. You can only use one or the other, and the last one you use "wins". Thus, you're using pack, and you're not giving it any options, so it's defaulting to packing things top to bottom.

While it's perfectly safe to use both grid and pack in the same application, it's pointless to use both on the same widget, and it's an error to use different ones for widgets that share the same parent.

The solution to the problem is to be consistent with your use of grid and pack. If you intend to use grid, make sure you use it consistently for all widgets that share the same parent.

The same holds true for pack -- use it consistently. Also, I recommend to always explicitly add the side, fill and expand arguments to pack so that it is clear what your intention is.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • I appreciate your insight. You mention arguments to consistently use pack, however are there guidelines for grid? I have the feeling that using grid(row=idx, column=0) in the while construct does not stack the consoles in rows, although I specify a new row index at each iteration. Maybe grid should be supplied with some additional option? – KeinReverb Leonardo Gabrielli Jun 23 '14 at 15:01
  • @KeinReverbLeonardoGabrielli: yes, it's generally a good idea to always specify an explicit row and column, as well as the `sticky` attribute. Ambiguity is the enemy. – Bryan Oakley Jun 23 '14 at 16:42