views:

230

answers:

2

I am using Python 3.1 by the way.

I am trying to build a simple GUI using Tkinter - label, text entry field, button on the first row and editable text area with scrollbar to the right and on the bottom of it - on the second row. Please help me fix up the layout. What I have below does not quite work. If I have to use a grid, I will. I wish to keep the code very simple - I want to "sell" Python to some of my coworkers. So, I want to get a somewhat decent look and feel. Suggest better padding if you do not mind. Also, if my variable names, etc. seem weird, then please make a note.

At the same time I want to pretend that this is a throw-away script which I have not spent much time on. Since I am asking for your help, it ain't so, but they do not need to know ;). So, I do not want to introduce fancy code to create nice borders, etc. I just want something that is visually appealing, clean and simple. If I do not, then my presentation will not achieve its goal.

Thank you, my code is below:

class App:
    def __init__(self, parent):
        frame = Frame(parent)
        self.__setup_gui(frame) # Call Helper
        frame.pack(padx=15, pady=15)
        parent.title('To be changed')

    def __setup_gui(self, frame):

        # First Row
        self.cs_label = Label(frame, text='Change Set: ')
        self.cs_label.pack(side=LEFT, padx=10, pady=10)

        self.cs_val = Entry(frame, width=10)
        self.cs_val.pack(side=LEFT, padx=10, pady=10)

        self.get_button = Button(frame, text='Get', command=self.get_content)
        self.get_button.pack(side=LEFT, padx=10, pady=10)

        # Text area and scrollbar
        self.text_area = Text(frame, height=10, width=50, background='white')
        # Put a scroll bar in the frame
        scroll = Scrollbar(frame)
        self.text_area.configure(yscrollcommand=scroll.set)
        self.text_area.pack(side=TOP)
        scroll.pack(side=RIGHT,fill=Y)

        self.clipboard_var = IntVar()
        self.notepad_var = IntVar()

    def get_content(self):
        print(self.clipboard_var.get())
        print(self.notepad_var.get())

###################################################################################################

if __name__ == '__main__':
    root = Tk()
    app = App(root)
    root.mainloop()
+2  A: 

You definitely want the grid manager -- Pack only works for a vertical or horizontal stackup by itself. You can use multiple frames to work around it, but I find it's easier to expand a GUI if you just do it with Grid to start.

Here's what I've worked up real quick based what you said and the code. I reduced/removed the padding -- it looked huge for me -- and I set up two scrollbars, in a subframe to make the padding work out more easily. Note that to make the horizontal scrollbar useful your Text area needs to have wrap=NONE; otherwise you might as well use the easy 'ScrolledText' widget from tkinter.scrolledtext and skip the horizontal scroll bar.

I've now reframed things a bit to allow for resize, with a minimum size that shows the top buttons -- see the uses of minsize and row/columnconfigure.

BTW, it looks like your variables aren't being pulled from anywhere -- is that intentional?

from tkinter import *

class App:
    def __init__(self, parent):
        self.__setup_gui(parent) # Call Helper
        parent.title('To be changed')

    def __setup_gui(self, parent):

        # First Row
        self.rowframe = Frame(parent)
        self.rowframe.grid()
        self.cs_label = Label(self.rowframe, text='Change Set: ')
        self.cs_label.grid(row=0, column=0, padx=2, pady=2)

        self.cs_val = Entry(self.rowframe, width=10)
        self.cs_val.grid(row=0, column=1, padx=2, pady=2)

        self.get_button = Button(self.rowframe, text='Get', command=self.get_content)
        self.get_button.grid(row=0, column=2, padx=2, pady=2)
        parent.update_idletasks()
        parent.minsize(width=self.rowframe.winfo_width(), height=self.rowframe.winfo_height())

        # Text area and scrollbars
        self.textframe = Frame(parent)
        self.textframe.grid(row=1, columnspan=2, padx=2, pady=2, sticky=N+S+E+W)

        self.hscroll = Scrollbar(self.textframe, orient=HORIZONTAL)
        self.vscroll = Scrollbar(self.textframe)
        self.text_area = Text(self.textframe, height=10, width=50, wrap=NONE, background='white', yscrollcommand=self.vscroll.set, xscrollcommand=self.hscroll.set)
        self.text_area.grid(row=0, column=0, sticky=N+S+E+W)
        self.hscroll.config(command=self.text_area.xview)
        self.hscroll.grid(row=1, column=0, sticky=E+W)
        self.vscroll.config(command=self.text_area.yview)
        self.vscroll.grid(row=0, column=1, sticky=N+S)

        # Row 0 defaults to 0
        parent.rowconfigure(1, weight=1)
        parent.columnconfigure(1, weight=1)

        # Textarea setup
        self.textframe.rowconfigure(0, weight=1)
        self.textframe.columnconfigure(0, weight=1)


        self.clipboard_var = IntVar()
        self.notepad_var = IntVar()

    def get_content(self):
        print(self.clipboard_var.get())
        print(self.notepad_var.get())

###################################################################################################

if __name__ == '__main__':
    root = Tk()
    app = App(root)
    root.mainloop()

Now, all that said...you might get more visual appeal with PyGTK, PyQt, or wxPython, though tkinter coming "standard" is a nice feature.

Arthur Shipkowski
Very cool! Now, how can I get a scrollbar at the bottom as well?
Hamish Grubijan
I went through and changed the code for a horizontal scrollbar as well; I had to go back to using Text rather than ScrolledText for optimal visual appearance, and to make it useful I had to set wrap to NONE. You might find the information in http://www.effbot.org/zone/tkinter-scrollbar-patterns.htm useful for other scrollbar fiddling.
Arthur Shipkowski
Your solution has poor resize behavior. You should include calls to columnconfigure and rowconfigure, giving appropriate weight values to the row(s) and column(s) you want to grow and shrink.
Bryan Oakley
Bryan, you're quite correct. Part of it is that it isn't my interface design. If it was up to me, I'd have the top row's contents not resize at all, and make the text area size itself in direct proportion. Hamish, did you have specific resizing behavior in mind?
Arthur Shipkowski
Hm ... whatever makes it look good. As you make changes, please keep the old versions as well. As I am learning, I would like to pick the one I like best. Thanks.
Hamish Grubijan
I've made additional edits to add resizing. As for previous versions, you can get to them by clicking on the timestamp next to "edited" above.
Arthur Shipkowski
How cool !!!!!!!!!!!!
Hamish Grubijan