0

I'm creating a Tkinter application that has a frame within the GUI the changes depending on what the user is doing in the program. It seems to work as far as switching between which frame is being show. However, the spinbox widget changes its size every time you go back to the frame it is located in. I tried using a fixed width using width=5, but still encountered the same problem. I also tried using pack() instead of grid(). What is causing it to change shape and how do I stop it?

import tkinter as tk
from tkinter import ttk

class ODE_Solver_App(tk.Tk):

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)
        equation_settings = ttk.Frame(self)

        equation_settings.pack(side="top", fill="both", expand = True)

        equation_settings.grid_rowconfigure(0, weight=1)
        equation_settings.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for F in (ODE_Equation_Settings, System_Equation_Settings):

            frame = F(equation_settings, self)

            self.frames[F] = frame

            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(ODE_Equation_Settings)

        # Buttons in the main class for switching between frames.
        button1 = tk.Button(self, text="ODE Settings", command=lambda: self.show_frame(ODE_Equation_Settings))
        button1.pack()
        button2 = tk.Button(self, text="System Settings", command=lambda: self.show_frame(System_Equation_Settings))
        button2.pack()


    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()


class ODE_Equation_Settings(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)

        equation_profile = tk.Frame(self)  # I am going to have more frames in this class.
        equation_profile.pack()

        order_label = tk.Label(equation_profile, text="Order:")
        order_label.grid(row=0, column=0, sticky="w")
        order_select = tk.Spinbox(equation_profile, width=5, from_=1, to=100000)  # This is the spinbox that is changing in size.
        order_select.grid(row=0, column=1, sticky="e")


class System_Equation_Settings(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="This is Another Page!")
        label.pack(pady=10,padx=10)

        button1 = tk.Button(self, text="This does nothing yet...")
        button1.pack()


app = ODE_Solver_App()
app.mainloop()

I am using Python 3.4 on Yosemite

EDIT: I tried running the program on different computers. The results are as follows: Mac OS Mavericks - Same exact issue. Windows XP (virtual machine on mac) - Works just fine.

It seems as though the problem is related to the OS I'm using.

Camon
  • 1,003
  • 1
  • 10
  • 22
  • Somehow the widgets on my System doesn't change size after switching the frames. How does your Spinbox is changing? Is it getting bigger or smaller? – VRage Aug 11 '15 at 05:16
  • It's getting smaller. When I run it, it looks as if the width is changing to a smaller size. Eventually it disappears entirely. Also, the label "Order:" seems to get covered by something (The no longer visible widget perhaps?) and also disappears. – Camon Aug 11 '15 at 05:21
  • Seems to work with my system (windows 7 64bit, Python 2.7) – VRage Aug 11 '15 at 05:54
  • I just tried it on Windows XP, and it works. It doesn't work on any of my Macs though. Possible bug in tkinter on mac? – Camon Aug 11 '15 at 05:56

2 Answers2

2

I think this is a bug in the OSX version of Tkinter. It is known to be a bit buggy. I noticed that if I resize the window -- even if by just a single pixel -- the spinbox is restored. This seems to be a glitch in the rendering system.

I can get better results by removing all frames but the visible one (using grid_forget) and then re-gridding the one that should be visible, rather than raising and lowering frames. However, I'm still seeing an anomaly that only goes away after I jiggle my mouse. Though, calling update_idletasks() as the last step in show_frame seems to make that problem go away.

You can try the following code to see if it works better for you. It has the side effect of resizing the window each time you switch frames, though you can combat that by giving the main window a fixed size that is large enough to hold either of the frames.

def show_frame(self, cont):

    for frame in self.frames:
        self.frames[frame].grid_forget()
    frame = self.frames[cont]
    self.frames[cont].grid()
    frame.update_idletasks()
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • Thank you for the help! I also found another fix that involves changing the `relief=` or `borderwidth=` parameters. However, it makes the spinbox less appealing to look at. – Camon Aug 11 '15 at 17:10
0

I managed to find another way to work around the problem by changing some of the parameters. If you change the relife= or borderwidth= parameters, the spinbox behaves normally. The only downside to this approach is that the widget looks out of place in the GUI and is not very appealing to look at.

However, there is a second approach which involves making the spinbox a ttk widget. ttk does not have this widget, so you need to make it. This post here shows you how to do just that. This is a good fix especially if you are concerned about how your GUI looks.

*Note: This issue seems to be a bug in tkinter for the Mac. So far the code in the original post works fine on Windows.

Community
  • 1
  • 1
Camon
  • 1,003
  • 1
  • 10
  • 22