Python Forum
tkinter how to use whitespace with grid
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
tkinter how to use whitespace with grid
#1
Hi, I'm trying to write a gui application using tkinter and matplotlib. I am having trouble with the layout. I'm leaving all the buttons in one frame and the plot in another frame (ie optionsframe = tk.Frame(self), plotsframe = tk.Frame(self)) in a attempt to divide the window into 2 (unequal) parts. However I cannot get the matplotlib figure to scale I tried adding "plotsframe.grid_columnconfigure(0, weight=1 )plotsframe.grid_rowconfigure(0, weight=1)" but it doesn't work. can someone tell me how to use the whitespace? I'm leaving the code for the page in question below

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# Plot
import matplotlib
import matplotlib.pyplot as plt
from matplotlib import style
from numpy import arange
from math import *
matplotlib.use("TkAgg")
style.use('fivethirtyeight')
 
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
 
## gui
import tkinter as tk
from tkinter import ttk
 
LARGE_FONT = ("Verdana", 12)
NORM_FONT = ("Verdana", 10)
SMALL_FONT = ("Verdana", 18)
 
 
## texts
Nsup= "Not supported yet! \n error: 010"
 
def popupmsg(msg):
    popup = tk.Tk()
 
    popup.wm_title("!")
    label = ttk.Label(popup, text= msg, font= NORM_FONT)
    label.pack(side="top", fill="x", pady=10)
    b1 = ttk.Button(popup, text="ok", command = popup.destroy)
    b1.pack()
    popup.mainloop()
 
 
#Plot
Y = [[]]
X = [[]]
Lines = 3
Sel = 1
 
def calc(ite, height, width):
    trans = ite*-500
    for i in arange(0,10, 0.05):
        # handle more plots
        if (len(X) <= ite):
            Y.append([])
            X.append([])
        # Maths
        a = (pi*i*20* width) - (90) + trans
         
        if a >= -90 and a <= 270:
            y = sin(radians(a)) + (i*1.1*(ite/100) + 1) + (height)
        else:
            y = i*1.1*(ite/100) + (height)
         
 
        # save datapoints
        X[ite].append(i)
        Y[ite].append(y)
 
def draw():
    for i in range(0, Lines):
        calc(i, i, i+1)
 
 
         
# baseline
class GUI(tk.Tk):
 
    def __init__(self, *args, **kwargs):  ## start up
        tk.Tk.__init__(self, *args, **kwargs) ## init tkinter
        tk.Tk.iconbitmap(self, default="icon.ico")
        tk.Tk.wm_title(self, "prog. Name")
         
        ## container
        container = tk.Frame(self)              #Frame = window
                    #              fills in space,  if there is white space fill
        container.pack(side="top", fill="both", expand = True)
                                # min size, priority
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
 
 
        ## Menu bar
        menubar = tk.Menu(container)
        filemenu = tk.Menu(menubar, tearoff = 0)
        filemenu.add_command(label = "Save", command = lambda:popupmsg(Nsup))
        filemenu.add_separator()
        filemenu.add_command(label = "Exit", command = quit)
 
        newmenu = tk.Menu(menubar, tearoff = 1)
        newmenu.add_command(label = "Add line", command = lambda:popupmsg(Nsup))
        newmenu.add_command(label = "del line", command = lambda:popupmsg(Nsup))
 
        menubar.add_cascade(label="File", menu=filemenu) ## show it
        menubar.add_cascade(label="New", menu=newmenu)
        tk.Tk.config(self, menu=menubar)
         
        ## end Menu bar
        self.frames = {}
 
        for F in (StartPage, MainP):
            frame = F(container, self)
            self.frames[F] = frame
                                    # north, south, east, west
            frame.grid(row=0, column = 0, sticky="nsew")
 
        self.show_frame(StartPage)
 
    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()
 
 
class StartPage(tk.Frame):
 
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = ttk.Label(self, text= "Start page?", font= "LARGE_FONT") ## just defined the object
        label.grid(row=1, column = 1)
 
        button1 = ttk.Button(self, text="ok",
                            command=lambda: controller.show_frame(MainP) )
        button1.grid(row=2, column = 2)
 
 
 
         
class MainP(tk.Frame):
 
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
     
        f = Figure()
        a = f.add_subplot(111)
         
        draw()
        for i in range(len(X)):
            if i is not (Sel):
                a.plot(X[i],Y[i], color="black", linewidth = 0.6)
            if i is Sel:
                a.plot(X[i],Y[i], color="blue", linewidth = 1)
        ## set frame
        optionsframe = tk.Frame(self)
        optionsframe.grid(row = 0, column = 0)
        ## withing options frame
        button1 = ttk.Button(optionsframe, text="+")
        button1.grid(row=1, column = 0)
        button2 = ttk.Button(optionsframe, text="-")
        button2.grid(row=1, column = 1)
 
        button1 = ttk.Button(optionsframe, text="<")
        button1.grid(row=2, column = 0)
        button2 = ttk.Button(optionsframe, text=">")
        button2.grid(row=2, column = 1)
 
        scaleframe = tk.Frame(optionsframe)
        scaleframe.grid(row = 3, column = 0)
         
        slabel1 = ttk.Label(scaleframe, text = "    Amp", font = "NORM_FONT")
        slabel1.grid(row = 3, column = 0)
        slabel2 = ttk.Label(scaleframe, text = "    Frq", font = "SMALL_FONT")
        slabel2.grid(row = 3, column = 1)
        slabel3 = ttk.Label(scaleframe, text = "    Inc", font = "NORM_FONT")
        slabel3.grid(row = 3, column = 2)
         
        scale1 = tk.Scale(scaleframe, from_=100, to=0.1)
        scale1.grid(row=4, column = 0)
        scale2 = tk.Scale(scaleframe, from_=100, to=0)
        scale2.grid(row=4, column = 1)
        scale3 = tk.Scale(scaleframe, from_=100, to=0)
        scale3.grid(row=4, column = 2)
        ## end
         
        #show the plot
        plotsframe = tk.Frame(self)
        plotsframe.grid(row = 0, column = 1)
        plotsframe.grid_columnconfigure(0, weight=1)
        plotsframe.grid_rowconfigure(0, weight=1)
 
         
        canvas = FigureCanvasTkAgg(f,plotsframe)
        canvas.show()
        canvas.get_tk_widget().grid(row=0, column=0, rowspan = 2, pady=20, padx=10, sticky='nsew')
 
 
 
        """
        #show the plot
        canvas = FigureCanvasTkAgg(f,self)
        canvas.show()
        canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand = True)
 
        # for matplotlib toolbar
        toolbar = NavigationToolbar2TkAgg(canvas, self)
        toolbar.update()
        canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand = True)
        """
         
 
app = GUI()
app.geometry("1280x720")
app.mainloop()
Reply
#2
first you don't show enough code to run what is controller?
where's you initial setup of parent?

If you're not too far into your project to change GUI packages, I'd look into wxpython
In tkinter is notoriously difficult to get your geometry correct.
In wxpython it's a snap see example here:
Reply
#3
sorry, I've uploaded the whole code, I'll take a look at wxpython.
Reply
#4
Sorry, forgot the link: https://python-forum.io/Thread-Perfectly...n-template
Reply
#5
thanks, I'm trying to switch over to wxpython. I'm having a few problems though, I am not being able to fit a matplotlib figure to a panel (it works when its the whole screen) can you help me out? also is there a way to get the size of the frame without having to set it in the int? here is the code that I've done so far

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import wx
 
##mpl in wx
import wx.lib.agw.aui as aui
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx
from matplotlib.figure import Figure
 
class Main(wx.Frame):
    def __init__(self, *args, **kwargs):
        dispX = wx.DisplaySize()[0]
        dispY = wx.DisplaySize()[1]
        super(Main, self).__init__(*args, **kwargs, size= (dispX, dispY))
 
        #frame starts in center of
        ##self.Move((dispX/4, dispY/4))
        self.Show()
 
        self.basicGUI()
 
    def basicGUI(self, *args, **kwargs):
        dispX = wx.DisplaySize()[0]
        dispY = wx.DisplaySize()[1]
        lowestpos = dispY
        #menu bar
        menuBar = wx.MenuBar()
        ##panel
        panelLW = dispX*.2
        panelLH = lowestpos
        panelL = wx.Panel(self, id=wx.ID_ANY, size=(panelLW,lowestpos) )
 
        panelRW = dispX*.2 - panelLW
        panelRH = lowestpos
        panelR = wx.Panel(self)
         
        # menu options
        fileButton = wx.Menu()
        editButton = wx.Menu()
        helpButton = wx.Menu()
         
        # File options
        exitItem = fileButton.Append(wx.ID_EXIT, "E&xit", "Close Program")
        menuBar.Append(fileButton, '&File')
        # Edit options
        menuBar.Append(editButton, '&Edit')
        # Help options
        menuBar.Append(helpButton, '&Help')
         
        #call it
        self.SetMenuBar(menuBar)
        #what to do when click
        self.Bind(wx.EVT_MENU, self.Quit, exitItem)
        self.SetTitle("prog")
        self.Show(True)
 
         
        wx.TextCtrl(panelL, pos=(10,10), size=(panelLW-20 ,lowestpos-80))
 
        #matplotlib
        self._mgr = aui.AuiManager(self)
        self.figure = Figure()
        self.axes = self.figure.add_subplot(111)
        self.canvas = FigureCanvas(panelR, -1, self.figure)
        #self.sizer = wx.BoxSizer(wx.VERTICAL)
        #self.sizer.Add(panelR, 1, wx.LEFT | wx.TOP | wx.GROW)
        #self.SetSizer(panelR.sizer)
        panelL.Fit()
        #end
         
        self._mgr.Update()
        self.Show()
         
    def Quit(self, e):
        self.Close()
    def Conf(self, e):
        pass
         
def main():
    app = wx.App()
    Main(None)
    app.MainLoop()
 
main()
Reply
#6
This more than fills my screen.
What exactly is your goal, number of panes, and what goes where.
Reply
#7
I'd like to have 2 panels, similar to the example that you gave me, the left panel(now it's with a textbox) with a few buttons and sliders to manipulate the graph on the right panel. I'd like the plot to fill the right panel but it isn't showing.
Reply
#8
Ok, I'll play with it. You may not see results until tomorrow.
Reply
#9
OK,
This is almost there. For some reason the numpy plot is not plotting, but I'll leave that for you to fix.
Should just be a typo somewhere.
You'll also have to add back your buttons and binding, but the canvas is where you want it ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import wx
import wx.aui as aui
import wx.lib.agw.aui as aui
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
from numpy import arange, sin, pi
 
 
class Nutrition(wx.Frame):
    def __init__(self, parent, id=wx.ID_ANY, title="Matplotlib Example", pos=wx.DefaultPosition,
                 size=(1200, 675), style=wx.DEFAULT_FRAME_STYLE, name='TryMethods'):
        # ideal size: width = height x 1.77864583 or height = width / 1.77864583
        self.main_width = size[0]
        self.main_height = size[1]
        app = wx.App()
        wx.Frame.__init__(self, parent, id, title, pos, size, style)
        app.SetTopWindow(self)
        # self.pnl = pnl = MainPanel(self)
        self._mgr = aui.AuiManager(self)
 
        left_panel_width = self.main_width * .3  # This is 30% of main width
        left_panel_height = self.main_height * .75  # This is 75% of main height
        left_panel_sz = left_panel_width, left_panel_height  # combined for widget size
 
        right_panel_width = self.main_width - left_panel_width  # which is 70% of main width
        right_panel_height = left_panel_height  # Keep same height as left panel
        right_panel_sz = right_panel_width, right_panel_height
 
 
        self.left_panel = wx.Panel(self, id=wx.ID_ANY, size=left_panel_sz)
        self.right_panel = wx.Panel(self, id=wx.ID_ANY, size=right_panel_sz)
 
 
        hsizer = wx.BoxSizer(wx.HORIZONTAL)
 
        self.figure = Figure()
        self.axes = self.figure.add_subplot(111)
        self.canvas = FigureCanvas(self.right_panel, -1, self.figure)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.EXPAND)
        hsizer.SetSizeHints(self.right_panel)
        self.right_panel.SetSizer(self.sizer)
 
        self._mgr.AddPane(self.left_panel, aui.AuiPaneInfo().Left())
        self._mgr.AddPane(self.right_panel, aui.AuiPaneInfo().Center())
 
        self._mgr.Update()
        self.Show()
 
        app.MainLoop()
 
    def draw(self):
        t = arange(0.0, 3.0, 0.01)
        s = sin(2 * pi * t)
        self.axes.plot(t, s)
 
def main():
    tm = Nutrition(None)
    tm.draw()
 
if __name__ == '__main__':
    main()
Click to enlarge:
   
Reply
#10
wow thanks man. ya it should plot nothing so far I'm only working on the gui later I'll actually get something in the graph that way thing wont get overcrowded. when I finish the code I'll add it here incase if someone wants to use it as a reference.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Centering and adding a push button to a grid window, TKinter Edward_ 15 15,291 May-25-2023, 07:37 PM
Last Post: deanhystad
  [Tkinter] Draw a grid of Tkinter Canvas Rectangles MrTim 5 11,727 May-09-2021, 01:48 PM
Last Post: joe_momma
  Tkinter grid columnspan being ignored mntfr 6 9,308 Feb-01-2019, 06:01 PM
Last Post: mntfr
  Widget placement issues with tkinter grid thread 1 mgtheboss 2 5,497 Jan-09-2018, 03:59 PM
Last Post: SmokerX

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020