Thanks for taking time to look at this. I've been struggling with this for almost a week and its driving me crazy.
I have a horizontal Paned Window which is supposed to stretch from the bottom of my toolbar to the bottom of my window, but it's sticking only to the bottom of the root window. Eventually I want to have a Treeview widget in the left pane and thumbnails in the right pane.
Can anyone help me to get the Paned Window to stick NSEW? Do I need to put it inside another frame?
I'm using Python 2.7 on Windows 7. (This isn't my whole program, just a sample to demonstrate the problem.)
#!/usr/bin/env python
# coding=utf-8
from Tkinter import *
from ttk import *
class MainWindow:
def null(self):
pass
def __init__(self):
self.root = Tk()
self.root.geometry("700x300")
self.root.resizable(width=TRUE, height=TRUE)
self.root.rowconfigure(0, weight=1)
self.root.columnconfigure(0, weight=1)
self.menubar = Menu(self.root)
File_menu = Menu(self.menubar, tearoff=0)
self.menubar.add_cascade(label="Pandoras Box", menu=File_menu)
File_menu.add_command(label="Black Hole", command=self.null)
self.root.config(menu=self.menubar)
self.toolbar = Frame(self.root, relief=RAISED)
self.toolbar.grid(row=0, column=0, sticky='NEW')
self.toolbar.grid_columnconfigure(0, weight=1)
self.toolbar.rowconfigure(0, weight=1)
dummy = Button(self.toolbar, text="Tool Button")
dummy.grid(row=0, column=0, sticky='EW')
Find = Label(self.toolbar, text="Search")
Search = Entry(self.toolbar)
Find.grid(row=0, column=5, sticky='E', padx=6)
Search.grid(row=0, column=6, sticky='E', padx=8)
self.info_column = Frame(self.root, relief=RAISED, width=100)
self.info_column.grid(row=0, column=5, rowspan=3, sticky='NSW')
self.info_column.grid_rowconfigure(0, weight=1)
self.info_column.grid_columnconfigure(0, weight=1)
self.rootpane = PanedWindow(self.root, orient=HORIZONTAL)
self.rootpane.grid(row=1, column=0, sticky='NS')
self.rootpane.grid_rowconfigure(0, weight=1)
self.rootpane.grid_columnconfigure(0, weight=1)
self.leftpane = Frame(self.rootpane, relief=RAISED)
self.leftpane.grid(row=0, column=0, sticky='NSEW')
self.rightpane = Frame(self.rootpane, relief=RAISED)
self.rightpane.grid(row=0, column=0, sticky='NSEW')
''' THESE BUTTONS ARE SUPPOSED TO BE INSIDE PANED WINDOW STUCK TO THE TOP!'''
but_left = Button(self.leftpane, text="SHOULD BE IN LEFT PANE UNDER TOOLBAR FRAME")
but_left.grid(row=0, column=0, sticky='NEW')
but_right = Button(self.rightpane, text="SHOULD BE IN RIGHT PANE UNDER TOOLBAR FRAME")
but_right.grid(row=0, column=0, sticky='NEW')
self.rootpane.add(self.leftpane)
self.rootpane.add(self.rightpane)
self.SbarMesg = StringVar()
self.label = Label(self.root, textvariable=self.SbarMesg, font=('arial', 8, 'normal'))
self.SbarMesg.set('Status Bar:')
self.label.grid(row=3, column=0, columnspan=6, sticky='SEW')
self.label.grid_rowconfigure(0, weight=1)
self.label.grid_columnconfigure(0, weight=1)
self.root.mainloop()
a = MainWindow()
Short answer: the space you see between the buttons and the toolbar frame is because you allow the row containing the toolbar to resize, instead of the row containing the PanedWindow... To get what you want, replace:
self.root.rowconfigure(0, weight=1)
with
self.root.rowconfigure(1, weight=1)
Other comments:
Try to avoid wildcard imports. In this case, it makes it difficult to differentiate between tk and ttk widgets
To allow resizing of widgets aligned using grid(), .rowconfigure(..., weight=x) must be called on the widget's parent not the widget itself.
background colors are very useful to debug alignment issues in tkinter.
Code:
import Tkinter as tk
import ttk
class MainWindow:
def __init__(self):
self.root = tk.Tk()
self.root.geometry("700x300")
self.root.resizable(width=tk.TRUE, height=tk.TRUE)
self.root.rowconfigure(1, weight=1)
self.root.columnconfigure(0, weight=1)
self.toolbar = tk.Frame(self.root, relief=tk.RAISED, bg="yellow")
self.toolbar.grid(row=0, column=0, sticky='NEW')
self.toolbar.columnconfigure(0, weight=1)
dummy = ttk.Button(self.toolbar, text="Tool Button")
dummy.grid(row=0, column=0, sticky='EW')
Find = tk.Label(self.toolbar, text="Search")
Search = ttk.Entry(self.toolbar)
Find.grid(row=0, column=5, sticky='E', padx=6)
Search.grid(row=0, column=6, sticky='E', padx=8)
self.info_column = tk.Frame(self.root, relief=tk.RAISED, width=100, bg="orange")
self.info_column.grid(row=0, column=5, rowspan=2, sticky='NSW')
self.rootpane = tk.PanedWindow(self.root, orient=tk.HORIZONTAL, bg="blue")
self.rootpane.grid(row=1, column=0, sticky='NSEW')
self.leftpane = tk.Frame(self.rootpane, bg="pink")
self.rootpane.add(self.leftpane)
self.rightpane = tk.Frame(self.rootpane, bg="red")
self.rootpane.add(self.rightpane)
''' THESE BUTTONS ARE SUPPOSED TO BE INSIDE PANED WINDOW STUCK TO THE TOP!'''
but_left = ttk.Button(self.leftpane, text="SHOULD BE IN LEFT PANE UNDER TOOLBAR FRAME")
but_left.grid(row=0, column=0, sticky='NEW')
but_right = ttk.Button(self.rightpane, text="SHOULD BE IN RIGHT PANE UNDER TOOLBAR FRAME")
but_right.grid(row=0, column=0, sticky='NEW')
self.label = tk.Label(self.root, text="Status:", anchor="w")
self.label.grid(row=3, column=0, columnspan=6, sticky='SEW')
self.root.mainloop()
a = MainWindow()
Related
I am creating a GUI in python using Tkinter and classes and having trouble resizing specific rows in the grid packager.
The code I have attached works but I would like to control the row widths so that the top 2 frames are static in size and the bottom resizes with the window. I have tried many things whilst referencing different solutions but nothing works.
# !/usr/bin/python3
# Use Tkinter for python 2, tkinter for python 3
import tkinter as tk
# Main Window
class WinMain(tk.Frame):
def __init__(self, master):
# parameters that you want to send through the Frame class.
tk.Frame.__init__(self, master)
# reference to the master widget, which is the tk window
self.master = master
# with that, we want to then run init_window, which doesn't yet exist
self.init_window()
def init_window(self):
# changing the title of our master widget
self.master.title("GUI Tester")
# Create menu for window
self.createMenu()
# Create Gui for window
self.createGui()
# Update Gui every second after 1 second
self.after(1000, self.upDateGui)
def createMenu(self):
# Initialise drop-down menu
menu = tk.Menu(self.master)
self.master.config(menu=menu)
# Add drop-down menu for Options
options = tk.Menu(menu, tearoff=False)
menu.add_cascade(label="Options", menu=options)
options.add_command(label="Open...", command=self.menuOptionsOpen)
options.add_separator()
options.add_command(label="Close", command=self.menuOptionsClose)
# Add drop-down menu for Help
help = tk.Menu(menu, tearoff=False)
menu.add_cascade(label="Help", menu=help)
help.add_command(label="About...", command=self.menuHelpAbout)
def createGui(self):
# Define GUI using Grid to place widgets
# Size window to its minimum set to 2/3 of the screen resolution
top = self.winfo_toplevel()
screen_width = top.winfo_screenwidth()
screen_height = top.winfo_screenheight()
screen_resolution = str(int(screen_width * 2 / 3)) + 'x' + str(int(screen_height * 2 / 3))
top.geometry(screen_resolution)
top.minsize(int(screen_width * 1 / 3), int(screen_height * 1 / 3))
# ------------------------------------------------
# create all frames
# ------------------------------------------------
self.c = self.master
self.c.frameTop = tk.LabelFrame(self.c, text="Top", width=5, height=5, padx=5, pady=5)
self.c.frameMiddle = tk.LabelFrame(self.c, text="Middle", width=5, height=5, padx=5, pady=5)
self.c.frameBottom = tk.LabelFrame(self.c, text="Bottom", width=5, height=5, padx=5, pady=5)
self.c.frameRight = tk.Frame(self.c, borderwidth=5, relief=tk.GROOVE)
# ------------------------------------------------
# Create widgets for frameTop
# ------------------------------------------------
# Text Box
self.c.frameTop.textBox = tk.Text(self.c.frameTop, borderwidth=3, relief=tk.SUNKEN)
self.c.frameTop.textBox.config(font=("consolas", 12), undo=True, wrap='none')
# Text Box Scroll Bars
self.c.frameTop.textBoxYScroll = tk.Scrollbar(self.c.frameTop, orient=tk.VERTICAL,
command=self.c.frameTop.textBox.yview)
self.c.frameTop.textBox['yscrollcommand'] = self.c.frameTop.textBoxYScroll.set
self.c.frameTop.textBoxXScroll = tk.Scrollbar(self.c.frameTop, orient=tk.HORIZONTAL,
command=self.c.frameTop.textBox.xview)
self.c.frameTop.textBox['xscrollcommand'] = self.c.frameTop.textBoxXScroll.set
# ------------------------------------------------
# Create widgets for frameMiddle
# ------------------------------------------------
# Text Box
self.c.frameMiddle.textBox = tk.Text(self.c.frameMiddle, borderwidth=3, relief=tk.SUNKEN)
self.c.frameMiddle.textBox.config(font=("consolas", 12), undo=True, wrap='none')
# Text Box Scroll Bars
self.c.frameMiddle.textBoxYScroll = tk.Scrollbar(self.c.frameMiddle, orient=tk.VERTICAL,
command=self.c.frameMiddle.textBox.yview)
self.c.frameMiddle.textBox['yscrollcommand'] = self.c.frameMiddle.textBoxYScroll.set
self.c.frameMiddle.textBoxXScroll = tk.Scrollbar(self.c.frameMiddle, orient=tk.HORIZONTAL,
command=self.c.frameMiddle.textBox.xview)
self.c.frameMiddle.textBox['xscrollcommand'] = self.c.frameMiddle.textBoxXScroll.set
# ------------------------------------------------
# Create widgets for frameBottom
# ------------------------------------------------
# Text Box
self.c.frameBottom.textBox = tk.Text(self.c.frameBottom, borderwidth=3, relief=tk.SUNKEN)
self.c.frameBottom.textBox.config(font=("consolas", 12), undo=True, wrap='none')
# Text Box Scroll Bars
self.c.frameBottom.textBoxYScroll = tk.Scrollbar(self.c.frameBottom, orient=tk.VERTICAL,
command=self.c.frameBottom.textBox.yview)
self.c.frameBottom.textBox['yscrollcommand'] = self.c.frameBottom.textBoxYScroll.set
self.c.frameBottom.textBoxXScroll = tk.Scrollbar(self.c.frameBottom, orient=tk.HORIZONTAL,
command=self.c.frameBottom.textBox.xview)
self.c.frameBottom.textBox['xscrollcommand'] = self.c.frameBottom.textBoxXScroll.set
# ------------------------------------------------
# Create widgets for frameRight
# ------------------------------------------------
self.c.frameRight.btnStatus = tk.Button(self.c.frameRight, text='Status Window', command=self.launchWinStatus)
self.c.frameRight.btnSpare1 = tk.Button(self.c.frameRight, text='Send Middle', command=self.btnSpare1)
self.c.frameRight.btnSpare2 = tk.Button(self.c.frameRight, text='Spare 2', command=self.btnSpare2)
# ------------------------------------------------
# ------------------------------------------------
# Layout widgets in frameTop
# ------------------------------------------------
self.c.frameTop.grid_columnconfigure(0, weight=1)
self.c.frameTop.grid_columnconfigure(1, weight=0)
self.c.frameTop.grid_rowconfigure(0, weight=1)
self.c.frameTop.grid_rowconfigure(1, weight=0)
self.c.frameTop.textBox.grid(row=0, column=0, sticky="nsew")
self.c.frameTop.textBoxYScroll.grid(row=0, column=1, sticky="nsew")
self.c.frameTop.textBoxXScroll.grid(row=1, column=0, sticky="nsew")
# ------------------------------------------------
# Layout widgets in frameMiddle
# ------------------------------------------------
self.c.frameMiddle.grid_columnconfigure(0, weight=1)
self.c.frameMiddle.grid_columnconfigure(1, weight=0)
self.c.frameMiddle.grid_rowconfigure(0, weight=1)
self.c.frameMiddle.grid_rowconfigure(1, weight=0)
self.c.frameMiddle.textBox.grid(row=0, column=0, sticky="nsew")
self.c.frameMiddle.textBoxYScroll.grid(row=0, column=1, sticky="nsew")
self.c.frameMiddle.textBoxXScroll.grid(row=1, column=0, sticky="nsew")
# ------------------------------------------------
# Layout widgets in frameBottom
# ------------------------------------------------
self.c.frameBottom.grid_columnconfigure(0, weight=1)
self.c.frameBottom.grid_columnconfigure(1, weight=0)
self.c.frameBottom.grid_rowconfigure(0, weight=1)
self.c.frameBottom.grid_rowconfigure(1, weight=0)
self.c.frameBottom.textBox.grid(row=0, column=0, sticky="nsew")
self.c.frameBottom.textBoxYScroll.grid(row=0, column=1, sticky="nsew")
self.c.frameBottom.textBoxXScroll.grid(row=1, column=0, sticky="nsew")
# ------------------------------------------------
# Layout widgets in frameRight
# ------------------------------------------------
self.c.frameRight.grid_columnconfigure(0, weight=0)
self.c.frameRight.grid_rowconfigure(0, weight=0)
self.c.frameRight.btnStatus.grid(row=0, column=0, sticky="nsew")
self.c.frameRight.btnSpare1.grid(row=2, column=0, sticky="nsew")
self.c.frameRight.btnSpare2.grid(row=3, column=0, sticky="nsew")
# ------------------------------------------------
# Layout frames in top container
# ------------------------------------------------
numOfCols = 2
numOfRows = 6
self.c.grid_columnconfigure(0, weight=1, pad=3)
self.c.grid_columnconfigure(1, weight=0, pad=3)
self.c.grid_rowconfigure(0, weight=1, pad=3)
self.c.grid_rowconfigure(1, weight=1, pad=3)
self.c.grid_rowconfigure(2, weight=1, pad=3)
self.c.grid_rowconfigure(3, weight=1, pad=3)
self.c.grid_rowconfigure(4, weight=1, pad=3)
self.c.grid_rowconfigure(5, weight=1, pad=3)
frameTopRowCol = [0, 0]
frameTopSpan = [2, 1]
frameMiddleRowCol = [frameTopRowCol[0] + frameTopSpan[0],
frameTopRowCol[1]]
frameMiddleSpanRC = [2, 1]
frameBottomRowCol = [frameMiddleRowCol[0] + frameMiddleSpanRC[0],
frameMiddleRowCol[1]]
frameBottomSpanRC = [2, 1]
frameRightRowCol = [frameTopRowCol[0],
frameTopRowCol[1] + frameTopSpan[1]]
frameRightSpanRC = [numOfRows, 1]
self.c.frameTop.grid(row=frameTopRowCol[0], column=frameTopRowCol[1],
rowspan=frameTopSpan[0], columnspan=frameTopSpan[1], sticky="nsew")
self.c.frameMiddle.grid(row=frameMiddleRowCol[0], column=frameMiddleRowCol[1],
rowspan=frameMiddleSpanRC[0], columnspan=frameMiddleSpanRC[1], sticky="nsew")
self.c.frameBottom.grid(row=frameBottomRowCol[0], column=frameBottomRowCol[1],
rowspan=frameBottomSpanRC[0], columnspan=frameBottomSpanRC[1], sticky="nsew")
self.c.frameRight.grid(row=frameRightRowCol[0], column=frameRightRowCol[1],
rowspan=frameRightSpanRC[0], columnspan=frameRightSpanRC[1], sticky="nsew")
# ------------------------------------------------
# Layout top container in window
# ------------------------------------------------
self.grid_columnconfigure(0, weight=1, pad=3)
self.grid_rowconfigure(1, weight=1, pad=3)
# ------------------------------------------------
# Layout window
# ------------------------------------------------
top.grid_columnconfigure(0, weight=1, pad=3)
top.grid_rowconfigure(1, weight=1, pad=3)
def menuOptionsOpen(self):
print("menuOptionsOpen")
def menuOptionsClose(self):
print("menuOptionsClose")
def menuHelpAbout(self):
print("menuHelpAbout")
def launchWinStatus(self):
print ("launchWinStatus")
def btnSpare1(self):
print("btnSpare1")
def btnSpare2(self):
print("btnSpare2")
def upDateGui(self):
print("upDateGui")
# Perform update every x milliseconds
self.after(1000, self.upDateGui)
# Main
def main():
root = tk.Tk()
app = WinMain(root)
root.mainloop()
# Launch Main
if __name__ == '__main__':
main()
I have a section at line 174 where I can change rowconfigure weights and this has peculiar effects that I can't explain. It should be able to fix the height of some rows while other rows are allowed to grow/shrink with the window down to a minimum size.
There are a few things:
There is a lot of code not relevant to the problem.
You have constructed a confusing widget hierarchy. The class WinMain()
is instantiated with root as master. While WinMain() inherits Frame(),
you never put any widgets inside self. Then you create the name top = self.winfo_toplevel() which is the running Tk() instance = root = master = self.master = self.c.
Your use of notation is confusing;
self.c.frameTop.textBox = tk.Text(self.c.frameTop, ...
Why save reference to the Text widget in the textBox attribute of frameTop?
Finally you configure grid in self (Frame which does not contain anything)
and root.
I think much of your problems are because you have confused the names of things. I'm providing an example below with only the necessary code to get the correct behaviour. My use of bg colors is to ease identification of the different widgets.
import tkinter as tk
# Main Window
class WinMain(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.master = master
self.master.config(bg='tan')
master.geometry('600x400+800+50')
self.pack(padx=10, pady=10, expand=True, fill='both')
self.columnconfigure(0, weight=1)
self.rowconfigure(2, weight=1) # Expand cols 0 & 2 with resize
# Top
frameTop = tk.LabelFrame(self, text="Top", bg='peru')
frameTop.grid(row=0, column=0, sticky='nsew')
frameTop.columnconfigure(0, weight=1) # Expand frame with resize
frameTop.rowconfigure(0, weight=1)
Top_Box = tk.Text(frameTop, borderwidth=3, relief=tk.SUNKEN, width=20, height=2)
Top_Box.grid(row=0, column=0, sticky="nsew", padx=10, pady=10)
# Middle
frameMiddle = tk.LabelFrame(self, text="Middle", padx=5, pady=5, bg='tomato')
frameMiddle.grid(row=1, column=0, sticky='nsew')
frameMiddle.columnconfigure(0, weight=1) # Expand frame with resize
frameMiddle.rowconfigure(0, weight=1)
Middle_Box = tk.Text(frameMiddle, borderwidth=3, relief=tk.SUNKEN, width=20, height=2)
Middle_Box.grid(row=0, column=0, sticky="nsew", padx=10, pady=10)
# Bottom
frameBottom = tk.LabelFrame(self, text="Bottom", padx=5, pady=5, bg='khaki')
frameBottom.grid(row=2, column=0, sticky='nsew')
frameBottom.columnconfigure(0, weight=1) # Expand frame with resize
frameBottom.rowconfigure(0, weight=1)
Bottom_Box = tk.Text(frameBottom, borderwidth=3, relief=tk.SUNKEN, width=20, height=2)
Bottom_Box.grid(row=0, column=0, sticky="nsew", padx=10, pady=10)
# Right
frameRight = tk.Frame(self, borderwidth=5, relief=tk.GROOVE, bg='thistle')
frameRight.grid(row=0, column=1, rowspan=3, sticky='nsew')
btnStatus = tk.Button(frameRight, text='Status Window',)
btnSpare1 = tk.Button(frameRight, text='Send Middle')
btnSpare2 = tk.Button(frameRight, text='Spare 2')
btnStatus.grid(row=0, column=0, sticky="ew")
btnSpare1.grid(row=1, column=0, sticky="ew")
btnSpare2.grid(row=2, column=0, sticky="ew")
if __name__ == '__main__':
root = tk.Tk()
app = WinMain(root)
root.mainloop()
I am new to the Tkinter module. I only have experience with PyQt5. I am playing with a couple widgets in my Frame. They are three buttons, and I am trying to expand their size relative to the size of the window. To do this I am using w.columnconfigure(n, weight=1). This should spread the 3 buttons I have across the window Frame. This is the code I am running. I have tried with the w.columnconfigure before placing the widgets in the grid, and, as seen in the posted code, after the widgets are placed in the grid. I noticed no difference or functionality. Is there a convention? Anyway, appreciate any guidance!
def create_widgets(self):
""" Create three buttons that do nothing. """
self.bttn1 = Button(self, text="I do nothing")
self.bttn2 = Button(self)
self.bttn2.configure(text="Me too!")
self.bttn3 = Button(self)
self.bttn3["text"] = "Same here!"
self.bttnCt = Button(self)
self.bttnCt["text"] = "Total Clicks: 0"
self.bttnCt["command"] = self.update_count
self.bttn1.grid(row=0, column=0, sticky=W+E)
self.bttn2.grid(row=0, column=1, sticky=W+E)
self.bttn3.grid(row=0, column=2, sticky=W+E)
self.bttnCt.grid(row=1, column=1, sticky=W+E)
bttn_list = [self.bttn1, self.bttn2, self.bttn3, self.bttnCt]
for k, i in enumerate(bttn_list):
i.columnconfigure(k, weight=1)
#self.bttn1.columnconfigure(0, weight=1)
#self.bttn2.columnconfigure(1, weight=3)
#self.bttn3.columnconfigure(2, weight=1)
#self.bttnCt.columnconfigure(3, weight=1)
columnconfigure() or rowconfigure() functions are applied to the window or frame, of which the widget is a part of. Here you are applying it on the button itself. Apply it on on its parent basically.
Here is a small example.
import tkinter as tk
app = tk.Tk()
bttn1 = tk.Button(app, text="I do nothing")
bttn2 = tk.Button(app, text='Me too!')
bttn3 = tk.Button(app, text='Same here!')
bttnCt = tk.Button(app, text='Total Clicks: 0')
bttn1.grid(row=0, column=0, sticky="ew")
bttn2.grid(row=0, column=1, sticky="ew")
bttn3.grid(row=0, column=2, sticky="ew")
bttnCt.grid(row=1, column=1, sticky="ew")
bttn_list = [bttn1, bttn2, bttn3, bttnCt]
for i in range(len(bttn_list)):
app.columnconfigure(i, weight=1) ## Not the button, but the parent
app.mainloop()
Using tkinter, I wanted to make an interface containing a few buttons on the left, which would be fairly static and align with the widgets on the right fairly nicely.
On the right, I wanted an Entry widget above a Text widget, both of which would resize accordingly (the Entry widget only on the X axis).
This code accomplishes most of that, except the Text widget does not resize and the Entry widget only resizes to align with the Text widget. Upon trying to column/rowconfigure the root, the top frame resizes awkwardly.
Here's a picture of the tkinter interface from this code:
from tkinter import *
def main():
root = Tk()
root.geometry("300x400")
framet = Frame(root)
frameb = Frame(root)
framet.grid(row=0, column=0, sticky='ew')
frameb.grid(row=1, column=0, sticky='news')
button1 = Button(framet, text='one', width=8)
button1.grid(row=0, column=0)
button2 = Button(frameb, text='two', width=8)
button2.grid(row=1, column=0, sticky='n')
entry1 = Entry(framet)
entry1.grid(row=0, column=1, sticky='ew')
text1 = Text(frameb, highlightbackground='black', highlightthickness=1)
text1.grid(row=1, column=1, sticky='news')
framet.columnconfigure(1, weight=1)
if __name__ == '__main__':
main()
As you can see, the Entry and Text widgets do not resize. How could I accomplish this whilst still having the Buttons remain static, and not moving anything (only resizing)?
Would this work for you? I changed the lines with # comments, I think, I can't really remember what I did I just tryed to get it working, one problem which I'm not happy with though is the entry widget is not the same height as the button, I guess you could manually set its height but..
from tkinter import *
def main():
root = Tk()
root.grid_columnconfigure(1,weight=1) # the text and entry frames column
root.grid_rowconfigure(0,weight=1) # all frames row
buttonframe = Frame(root)
buttonframe.grid(row=0, column=0, sticky="nswe")
entry_text_frame = Frame(root)
entry_text_frame.grid(row=0, column=1, sticky="nswe")
entry_text_frame.grid_columnconfigure(0,weight=1) # the entry and text widgets column
entry_text_frame.grid_rowconfigure(1,weight=1) # the text widgets row
button1 = Button(buttonframe, text='one', width=8)
button1.grid(row=0, column=0, sticky='nswe')
button2 = Button(buttonframe, text='two', width=8)
button2.grid(row=1, column=0, sticky='nswe')
entry1 = Entry(entry_text_frame)
entry1.grid(row=0, column=0, sticky='nswe')
text1 = Text(entry_text_frame, highlightbackground='black', highlightthickness=1)
text1.grid(row=1, column=0, sticky='news')
root.geometry("300x400")
if __name__ == '__main__':
main()
I need help on this. I'm just started to learn Tkinter and I have some difficulties to do this:
Image: Main window with a new window
Basically, what I want is to do is to create a frame in the main window (root or master) that pop-out initially. This frame will contain labels and buttons; besides, it will be above other labels and buttons. Similar to the image I posted. I tried to achieve this by creating a new window but the new window comes with title, minimize, maximize and close button which it is something I do not want. I want to achieve I similar result like the image I posted. Thank you in advance.
If you do not need a floating window, you can just create a frame and use place to place it in the center of the window.
Here's a basic example:
import tkinter as tk
class Popout(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent, background="black", padx=10, pady=10)
title = tk.Label(self, text="How to play", font=("Helvetica", 16), anchor="w",
background="black", foreground="white")
instructions = tk.Label(self, text="The goal of Klondike is to blah blah blah...",
background="black", foreground="white", anchor="w")
cb = tk.Checkbutton(self, text="Do not show again", highlightthickness=0,
background="black", foreground="white")
oneof = tk.Label(self, text="1 of 6", background="black", foreground="white")
close_btn = tk.Button(self, text="Close", background="black", foreground="white")
next_btn = tk.Button(self, text="Next", background="black", foreground="white")
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(1, weight=1)
title.grid(row=0, column=0, columnspan=2, sticky="ew")
oneof.grid(row=0, column=2, sticky="ne")
instructions.grid(row=1, column=0, columnspan=3, sticky="nsew", pady=10)
cb.grid(row=2, column=0, sticky="w")
close_btn.grid(row=3, column=1, sticky="ew", padx=10)
next_btn.grid(row=3, column=2, sticky="ew")
root = tk.Tk()
root.geometry("600x400")
p = Popout(root)
p.place(relx=.5, rely=.5, anchor="center")
root.mainloop()
I tried to find out why, but maybe don't know the right questions. I have a project where I'm trying to create a dashboard for my car. The problem is that when I try to make a canvas object from another class appear my GUI starts but does not show anything. If I start the GUI without asking for the canvas to appear the GUI works and shows the screen. I'm new to Python. My version is 3.5
My Main program:
from tkinter import*
from helperThingys import Helpers
root = Tk()
root.geometry("800x480")
bgLeft = Frame(root, bg="black", width=200, height=480)
bgLeft.pack_configure(fill=BOTH, expand=1, side=LEFT)
bgMiddle = Frame(root, bg="black", width=400, height=480)
bgMiddle.pack_configure(fill=BOTH, expand=1, side=LEFT)
bgRight = Frame(root, bg="black", width=200, height=480)
bgRight.pack_configure(fill=BOTH, expand=1, side=LEFT)
# These are really gif images read to labels to be able to grid them
# now just plain text labels for convenience.
label_4hi = Label(bgLeft, text="ok", bg="green")
label_4lo = Label(bgLeft, text="ok", bg="green")
label_lock = Label(bgLeft, text="ok", bg="green")
label_batt = Label(bgMiddle, text="ok", bg="red")
label_fuelF = Label(bgLeft, text="ok", bg="orange")
label_glow = Label(bgLeft, text="ok", bg="yellow")
label_hb = Label(bgMiddle, text="ok", bg="blue")
label_indL = Label(bgMiddle, text="ok", bg="green")
label_indR = Label(bgMiddle, text="ok", bg="green")
label_lowFuel = Label(bgLeft, text="ok", bg="red")
label_lowOil = Label(bgLeft, text="ok", bg="red")
label_park = Label(bgMiddle, text="ok", bg="red")
label_pwrS = Label(bgLeft, text="ok", bg="red")
label_rFog = Label(bgLeft, text="ok", bg="orange")
label_temp = Label(bgLeft, text="ok", bg="red")
label_gauge = Label(bgMiddle, text="ok", bg="red")
# Middle frame
bgMiddle.rowconfigure(0, minsize=46, weight=1)
bgMiddle.rowconfigure(1, minsize=217, weight=5)
bgMiddle.rowconfigure(2, minsize=217, weight=5)
bgMiddle.columnconfigure(0, minsize=80)
bgMiddle.columnconfigure(1, minsize=80)
bgMiddle.columnconfigure(2, minsize=80)
bgMiddle.columnconfigure(3, minsize=80)
bgMiddle.columnconfigure(4, minsize=80)
label_indL.grid(row=0, column=0, sticky=E+N+W)
label_hb.grid(row=0, column=1, sticky=E+N+S+W)
label_park.grid(row=0, column=2, sticky=E+N+S+W)
label_batt.grid(row=0, column=3, sticky=E+N+S+W)
label_indR.grid(row=0, column=4, sticky=E+N+S+W)
# Left frame
bgLeft.rowconfigure(0, minsize=46, weight=1)
bgLeft.rowconfigure(1, minsize=46, weight=1)
bgLeft.rowconfigure(2, minsize=46, weight=1)
bgLeft.rowconfigure(3, minsize=46, weight=1)
bgLeft.rowconfigure(4, minsize=46, weight=1)
bgLeft.columnconfigure(0, minsize=100)
bgLeft.columnconfigure(1, minsize=100)
label_4hi.grid(row=0, column=0, sticky=E+N+S+W)
label_4lo.grid(row=0, column=1, sticky=E+N+S+W)
label_lock.grid(row=1, column=0, sticky=E+N+S+W)
label_pwrS.grid(row=1, column=1, sticky=E+N+S+W)
label_rFog.grid(row=2, column=0, sticky=E+N+S+W)
label_lowFuel.grid(row=2, column=1, sticky=E+N+S+W)
label_lowOil.grid(row=3, column=0, sticky=E+N+S+W)
label_temp.grid(row=3, column=1, sticky=E+N+S+W)
label_fuelF.grid(row=4, column=0, sticky=E+N+S+W)
label_glow.grid(row=4, column=1, sticky=E+N+S+W)
# Middle frame
speedo = helpers.Gauge()
speedo.makeGauge(bgMiddle, 150, "speed")
speedo.grid(row=1, columnspan=5, sticky=E+N+S+W)
#label_gauge.grid(row=1, columnspan=5, sticky=E+N+S+W)
# Right Frame
#oilPres = Gauge(bgRight, 150, "oilPres")
root.mainloop()
And here is the 'helpers.py' from helperThingys package.
from tkinter import Canvas
class Gauge(Canvas):
def __init__(self):
Canvas.__init__(self)
pass
def makeGauge(self, window, value, gaugeType):
if gaugeType == "speed":
baseCanvas = Canvas(window, bg="black", width=400, height=217,
highlightthickness=0)
baseCanvas.create_arc([10, 5, 390, 395], start=0, extent=180,
fill="white")
return baseCanvas
I'm using the canvases as the background for the gauges. The strange thing was that this 'helpers.py' worked and created the canvases to my GUI when it was not a class but a module:
def makeGauge(self, window, value, gaugeType):
if gaugeType == "speed":
baseCanvas = Canvas(window, bg="black", width=400, height=217,
highlightthickness=0)
baseCanvas.create_arc([10, 5, 390, 395], start=0, extent=180,
fill="white")
return baseCanvas
... and so on (the module was then in the same package as the GUI). That's why I know that the canvases work with the GUI. What am I doing wrong when using them in a class?
Thank you for your answers.
Your problem is that Gauge both is a subclass of Canvas and creates one or more other canvases (that are, oddly, a child of some other window).
When you call makeGauge, this creates the second canvas, and returns it. However, you don't save a reference and you never call pack, place or grid on this second canvas so it never shows up.
I don't know what you're intending to do with the two canvases, but I'm guessing you really only want one. I suggest making the class like this, where you pass all arguments in at the time you create the canvas, so that you can create the gauge in a single step:
class Gauge(Canvas):
def __init__(self, parent, value, gaugeType):
Canvas.__init__(self, parent)
self.makeGauge(value, gaugeType)
def makeGauge(self, value, gaugeType):
if gaugeType == "speed":
self.configure(bg="black", width=400, height=217,
highlightthickness=0)
self.create_arc([10, 5, 390, 395], start=0, extent=180,
fill="white")
elif gaugeType == "rpm":
...
speedo = Gauge(bgMiddle, 150, "speed")
speedo.grid(...)
If you want to keep both canvases, or you decide to make Gauge inherit from something else, you need to save the reference that is returned by makeGauge, and then add it to the display:
gauge = speedo.makeGauge(bgMiddle, 150, "speed")
gauge.grid(row=1, columnspan=5, sticky=E+N+S+W)