Postioning Widget in Tkinter Python

Question:

I was recently introduced to tkinter, and I’m attempting to write a application for 2d plotter. I am trying to position my buttons using the .pack method and I have write the code and stuck when try to position the text display and the graph figure. Here’s the current code output for my application:
enter image description here

This is the intended view/positioning output for my application:
enter image description here

Why does it happen and how can I position it using .pack method?

This is the code (I have changed it so it easy to run it without image):

from tkinter import *
from tkinter import Tk, Frame, Menu
from tkinter.filedialog import *
from tkinter.scrolledtext import ScrolledText
from tkinter import ttk, filedialog
import tkinter.messagebox
import tkinter as tk

import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg #, NavigationToolbar2TkAgg
from matplotlib.figure import Figure

import time
import turtle
import os
import sys
import logging
import ruamel.yaml


class MenuBar(tk.Menu):
    def __init__(self, parent):
        tk.Menu.__init__(self, parent)
        
        fileMenu = tk.Menu(self, tearoff=False)
        self.add_cascade(label="File", underline=0, menu=fileMenu)
        fileMenu.add_command(label="Upload File", command=self.browseFile)
        fileMenu.add_command(label="Exit", underline=1, command=self.quit)

        settingMenu = tk.Menu(self, tearoff=False)
        self.add_cascade(label="Settings", underline=0, menu=settingMenu)
        settingMenu.add_command(label="Machine Variable") #,command=self.browseFile)
        
        aboutMenu = tk.Menu(self, tearoff=False)
        self.add_cascade(label="About", underline=0, menu=aboutMenu)
        #aboutMenu.add_command(label="Machine Variable")
    
    
    def browseFile(self):
        tmp = filedialog.askopenfilename(initialdir = "./", title = "select gcode file", filetypes = (("gcode files", "*.gcode"), ("gc files", "*.gc"), ("nc files", "*.nc"), ("all files", "*.*")))
        selectedfile = tmp
    
        gcodefile = open (selectedfile, 'r')
        gcodefileread = gcodefile.readlines()
        fileDisplayText.insert(END, gcodefileread)   
        gcodefile.close()
        
        gcode = extractGcode(selectedfile)
        self.diagramFrame.plot(gcode)
    
    def quit(self):
        sys.exit(0)


class App(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        
        tk.Tk.wm_title(self, "Plotter Interface")
        menubar = MenuBar(self)
        self.config(menu=menubar)
        
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand = True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        
        topLeftFrame = tk.Frame(container, relief='solid', bd=1)
        topLeftFrame.pack(side=LEFT, anchor=NW, padx=0, pady=0) 
        bottomRightFrame = tk.Frame(container, relief='solid', bd=1)
        bottomRightFrame.pack(side=RIGHT, anchor=NE, padx=0, pady=0)
        
        #def update():
            #zero=0
            #one=zero+1
            #print(one)
        
        homebutton = tk.Button(topLeftFrame, height=50, width=50, command=None)
        homebutton.grid(row=0, column=0, padx=0, pady=0)
        

        playbutton = tk.Button(topLeftFrame, height=50, width=50, command=None)
        playbutton.grid(row=0, column=1, padx=0, pady=0)

        pausebutton = tk.Button(topLeftFrame, height=50, width=50, command=None)
        pausebutton.grid(row=0, column=2, padx=0, pady=0)
        
        stopbutton = tk.Button(topLeftFrame, height=50, width=50, command=None)
        stopbutton.grid(row=0, column=3, padx=0, pady=0)
        
        updownbutton = tk.Button(topLeftFrame, height=50, width=50, command=None)
        updownbutton.grid(row=0, column=4, padx=0, pady=0)
  
    
        nextbutton = tk.Button(bottomRightFrame, height=50, width=50, command=None)
        nextbutton.grid(row=0, column=1, padx=0, pady=0)
        
        prevbutton = tk.Button(bottomRightFrame, height=50, width=50, command=None)
        prevbutton.grid(row=0, column=0, padx=0, pady=0)
        
        self.diagramFrame = DiagramFrame(container)
        self.diagramFrame.pack(side=BOTTOM,fill='both',expand=True)
        
        
class DiagramFrame(tk.Frame):

    def __init__(self, parent):
        tk.Frame.__init__(self,parent)
        
        label = tk.Label(self, text="Drawing Plotter view", font=("Verdana", 12))
        label.pack(side=TOP, anchor=E, pady=0,padx=0)
        
        label2 = tk.Label(self, text="Gcode view", font=("Verdana", 12))
        label2.pack(side=TOP, anchor=W, pady=0,padx=0)
        
        self.f = Figure(figsize=(8,8), dpi=100)
        self.a = self.f.add_subplot(111)
        self.a.plot(0, 0, 'r')
        self.a.plot(0, 0, 'g')  
        self.a.axis("equal")    
        self.a.grid(color='grey', linestyle='-', linewidth=0.5)
        #self.a.legend(["XY", "UV"])  

        self.fileDisplayText = Text(self, width=27, height=13.6, font=(9))
        self.fileDisplayText.pack(side=LEFT, anchor=SW,padx=0, pady=0) 

        
        self.canvas = FigureCanvasTkAgg(self.f, self)
        self.canvas.draw()
        self.canvas.get_tk_widget().pack(side=RIGHT, fill=BOTH, expand=True)
Asked By: Haziq Hasbulah

||

Answers:

I think problem is because you put all in one container with LEFT, RIGHT and BOTTOM and you expect

+---------------------+
|    TOP(1),TOP(2)    |
+----------+----------+
| LEFT     |    RIGHT |
+----------+----------+
| BOTTOM(1),BOTTOM(2) |
+---------------------+   

but it works in different way

+------+------+-----------+-------+-------+    
|      |      |   TOP(1)  |       |       |
|      |      +-----------+       |       |
|      |      |   TOP(2)  |       |       |
| LEFT | LEFT +-----------+ RIGHT | RIGHT |
| (1)  | (2)  | BOTTOM(2) |  (2)  |  (1)  |
|      |      +-----------+       |       |
|      |      | BOTTOM(1) |       |       |
+------+------+-----------+-------+-------+  

You should use nested Frames

  • one frame only for buttons on left and right,
  • one frame only with graph and text on left and right.
  • and these frames should be inside another frame at top and bottom
  • and graph should be as another frame with label at top and with plot at bottom. (And the same with text)
+-FRAME or TK or TOPLEVEL-----------------------------------+
|                                                           |
|  +-FRAME.pack(TOP)-------------------------------------+  |
|  |                                                     |  |
|  |  Buttons.pack(LEFT)            Buttons.pack(RIGHT)  |  |
|  |                                                     |  |
|  +-----------------------------------------------------+  |
|                                                           |
|  +-FRAME.pack(BOTTOM)----------------------------------+  |
|  |                                                     |  |
|  |  +-FRAME.pack(LEFT)----+  +-FRAME.pack(RIGHT)----+  |  |
|  |  |                     |  |                      |  |  |
|  |  |  Label.pack(TOP)    |  |  Label.pack(TOP)     |  |  |
|  |  |                     |  |                      |  |  |
|  |  |  Text.pack(BOTTOM)  |  |  Graph.pack(BOTTOM)  |  |  |
|  |  |                     |  |                      |  |  |
|  |  +---------------------+  +----------------------+  |  |
|  |                                                     |  |
|  +-----------------------------------------------------+  |
|                                                           |
+-----------------------------------------------------------+

Something like this:

from tkinter import *
from tkinter import Tk, Frame, Menu
from tkinter.filedialog import *
from tkinter.scrolledtext import ScrolledText
from tkinter import ttk, filedialog
import tkinter.messagebox
import tkinter as tk

import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg #, NavigationToolbar2TkAgg
from matplotlib.figure import Figure

import time
import turtle
import os
import sys
import logging
#import ruamel.yaml

class MenuBar(tk.Menu):
    def __init__(self, parent):
        super().__init__(parent)
        
        fileMenu = tk.Menu(self, tearoff=False)
        self.add_cascade(label="File", underline=0, menu=fileMenu)
        fileMenu.add_command(label="Upload File", command=self.browseFile)
        fileMenu.add_command(label="Exit", underline=1, command=self.quit)

        settingMenu = tk.Menu(self, tearoff=False)
        self.add_cascade(label="Settings", underline=0, menu=settingMenu)
        settingMenu.add_command(label="Machine Variable") #,command=self.browseFile)
        
        aboutMenu = tk.Menu(self, tearoff=False)
        self.add_cascade(label="About", underline=0, menu=aboutMenu)
        #aboutMenu.add_command(label="Machine Variable")
    
    def browseFile(self):
        tmp = filedialog.askopenfilename(initialdir="./", title="select gcode file", filetypes=(("gcode files", "*.gcode"), ("gc files", "*.gc"), ("nc files", "*.nc"), ("all files", "*.*")))
        selectedfile = tmp
    
        gcodefile = open(selectedfile, 'r')
        gcodefileread = gcodefile.readlines()
        fileDisplayText.insert(END, gcodefileread)   
        gcodefile.close()
        
        gcode = extractGcode(selectedfile)
        self.diagramFrame.plot(gcode)
    
    def quit(self):
        sys.exit(0)


class App(tk.Tk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        tk.Tk.wm_title(self, "Plotter Interface")
        menubar = MenuBar(self)
        self.config(menu=menubar)
        
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand = True)
        
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        
        top_frame = tk.Frame(container)
        top_frame.pack(fill='x', expand=True)
        
        topLeftFrame = tk.Frame(top_frame, relief='solid', bd=1)
        topLeftFrame.pack(side=LEFT, anchor=NW, padx=0, pady=0)
        
        bottomRightFrame = tk.Frame(top_frame, relief='solid', bd=1)
        bottomRightFrame.pack(side=RIGHT, anchor=NE, padx=0, pady=0)
        
        #def update():
            #zero=0
            #one=zero+1
            #print(one)
        
        homebutton = tk.Button(topLeftFrame, command=None)
        homebutton.grid(row=0, column=0, padx=0, pady=0)

        playbutton = tk.Button(topLeftFrame, command=None)
        playbutton.grid(row=0, column=1, padx=0, pady=0)

        pausebutton = tk.Button(topLeftFrame, command=None)
        pausebutton.grid(row=0, column=2, padx=0, pady=0)
        
        stopbutton = tk.Button(topLeftFrame, command=None)
        stopbutton.grid(row=0, column=3, padx=0, pady=0)
        
        updownbutton = tk.Button(topLeftFrame, command=None)
        updownbutton.grid(row=0, column=4, padx=0, pady=0)
    
        nextbutton = tk.Button(bottomRightFrame, command=None)
        nextbutton.grid(row=0, column=1, padx=0, pady=0)
        
        prevbutton = tk.Button(bottomRightFrame, command=None)
        prevbutton.grid(row=0, column=0, padx=0, pady=0)
        
        bottom_frame = tk.Frame(container)
        bottom_frame.pack()
        
        self.diagramFrame = DiagramFrame(bottom_frame)
        self.diagramFrame.pack(side=BOTTOM,fill='both',expand=True)
        
        
class DiagramFrame(tk.Frame):

    def __init__(self, parent):
        super().__init__(parent)
        
        frame_right = tk.Frame(self)
        frame_right.pack(side=RIGHT, fill='both', expand=True)
        
        label1 = tk.Label(frame_right, text="Drawing Plotter view", anchor='w', padx=15, pady=5)
        label1.pack(side=TOP, fill='x', expand=True)
        
        self.f = Figure(figsize=(8,8), dpi=100)
        self.a = self.f.add_subplot(111)
        self.a.plot(0, 0, 'r')
        self.a.plot(0, 0, 'g')  
        self.a.axis("equal")    
        self.a.grid(color='grey', linestyle='-', linewidth=0.5)
        #self.a.legend(["XY", "UV"])  

        self.canvas = FigureCanvasTkAgg(self.f, frame_right)
        self.canvas.draw()
        self.canvas.get_tk_widget().pack(side=BOTTOM, fill='both', expand=True)

        # --------------------------
        
        frame_left = tk.Frame(self)
        frame_left.pack(side=LEFT, fill=BOTH, expand=True)
        
        label2 = tk.Label(frame_left, text="Gcode view", anchor='w', padx=15, pady=5)
        label2.pack(side=TOP, fill='x')

        self.fileDisplayText = Text(frame_left, width=27, font=(9))
        self.fileDisplayText.pack(side=BOTTOM, fill='both', expand=True) 
        
app = App()
app.mainloop()

enter image description here

Answered By: furas
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.