button, label etc over an background image using tkinter. few days before I just stared learning python so I am sorry if this question look silly.. my code is below.. but at this moment label is showing below image not over image..please correct me.
import tkinter
haren = tkinter.Tk()
width, height = haren.winfo_screenwidth(), haren.winfo_screenheight()
bg = tkinter.PhotoImage(file="img/bg.png")
panel1 = tkinter.Label(haren, image=bg)
panel1.pack(side='top', fill='both', expand='yes')
haren.wm_title("Hi Sana")
haren.grid()
yeah=tkinter.Label(haren, text="Developed by Full Mad Haren Sarma")
yeah.pack()
haren.wm_geometry("%dx%d+0+0" % (width, height))
haren.mainloop()
In your current code, if you want both the image and the text to be visible, the window must be big enough for both. If the background image is exactly as large as your screen size, the text will be hidden. You can reveal the text by increasing the window size (I recommend testing with a smaller image), noting that it collapses under the image when you shrink the window.
Try changing your geometry manager to grid instead of pack.
panel1.pack(side='top', fill='both', expand='yes')
changes to:
panel1.grid(row=0, column=0)
and
yeah.pack()
changes to:
yeah.grid(row=0, column=0, sticky='s')
Note how both widgets are added to the same row and column, so the most recently-grid()ed widget will appear on top of previous ones. The sticky option indicates where in its grid square the widget will rest (the south end in this case).
Related
I am attempting to create fixed-size canvas widget with scroll bars. The canvas in question could be quite large, and will almost definitely be much larger than the frame containing it. I would like to keep the canvas at its fixed size, but be able to resize the window containing it. The issue I am having is I don't know how to bind the scroll bars to the edge of the window.
I have tried both .pack and .grid. The obvious issue with .grid is that it will simply place the scroll bars next to the canvas. Unfortunately, the canvas must have a fixed size that will always be larger than the window. Whenever I .pack, the canvas appears to resize with the window, even when I explicitly disable expand and set fill to None.
I have made set the background to black for the purpose of clearly seeing the canvas area.
import tkinter as tk
from tkinter import *
class DialogueCreation(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.xbar = tk.Scrollbar(parent, orient=HORIZONTAL)
self.xbar.pack(side=BOTTOM, fill=X)
self.ybar = tk.Scrollbar(parent)
self.ybar.pack(side=RIGHT, fill=Y)
self.item_canvas = tk.Canvas(parent, width=5000, height=5000, xscrollcommand=self.xbar.set, yscrollcommand=self.ybar.set)
self.item_canvas.pack(side=LEFT, expand=FALSE, fill=None)
self.item_canvas.configure(background='black')
if __name__ == '__main__':
root = tk.Tk()
DialogueCreation(root)
root.title("Editor")
root.mainloop()
The canvas is a massive 5000x5000, so I should definitely be able to scroll when the window is small. I want the scrollbars to remain flush with the edges of the window, without resizing my canvas. The scrollbars remain dormant no matter how large or small the window is. I'm assuming the canvas is resizing with the window, which is definitely not the desired result.
Eventually this canvas will have several images displayed on it, and the location of those images must not change on the canvas. I do not believe the issue is with how I bound the scrollbars (I checked several other posts on this website to make sure), but it would not be uncharacteristic if I missed something obvious like that.
When you say you want to create a fixed size canvas, I'm assuming that you mean you want the drawable area to be a fixed size, rather than have a fixed size for the viewable portion of the canvas.
To do that, you need to set the scrollregion attribute to the drawable area. You use the width and height attributes to set the size of the visible portion of the canvas.
Also, hooking up scrollbars is a two way street: you've got to configure the canvas to update the scrollbars, and configure the scrollbars to scroll the canvas.
Note: you made DialogCreation a Frame, yet you put all of the widgets directly in the parent. That's very unusual, and not the best way to do it. I recommend inheriting from Frame like you do, but then all of the widgets should go in self rather than parent.
When you do it this way, you need to make sure you call pack on the instance of DialogCreation, eg:
dr = DialogueCreation(root)
dr.pack(fill="both", expand=True)
Using pack
With pack, you should set the expand option to True if you want the visible portion to grow or shrink when the user resizes the window.
My personal experience is that code is easier to understand and easier to maintain if you separate widget creation from widget layout. The following code shows how I would rewrite your code using pack. Notice the additional lines for configuring xbar and ybar, as well as setting the scrollregion.
class DialogueCreation(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.xbar = tk.Scrollbar(self, orient=HORIZONTAL)
self.ybar = tk.Scrollbar(self)
self.item_canvas = tk.Canvas(self, width=400, height=400,
xscrollcommand=self.xbar.set,
yscrollcommand=self.ybar.set)
self.xbar.configure(command=self.item_canvas.xview)
self.ybar.configure(command=self.item_canvas.yview)
self.item_canvas.configure(scrollregion=(0,0,4999,4999))
self.item_canvas.configure(background='black')
self.xbar.pack(side=BOTTOM, fill=X)
self.ybar.pack(side=RIGHT, fill=Y)
self.item_canvas.pack(side=LEFT, expand=TRUE, fill=BOTH)
Using grid
The obvious issue with .grid is that it will simply place the scroll bars next to the canvas.
I don't see that as obvious at all. grid has no such restriction. You can put the scrollbar anywhere you want.
The important thing to remember with grid is that rows and columns do not automatically grow or shrink when the window as a whole changes size. You have to explicitly tell tkinter which rows and columns to grow and shrink.
To achieve the same effect as with using pack, you need to configure row zero, column zero to be given all extra space. You do that by giving them a weight that is greater than zero.
To use grid instead of pack, replace the last three lines of the above example with the following six lines:
self.item_canvas.grid(row=0, column=0, sticky="nsew")
self.xbar.grid(row=1, column=0, sticky="ew")
self.ybar.grid(row=0, column=1, sticky="ns")
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
When I put a widget inside the frame, the color of the frame vanishes. If it was 'black' before, then after putting a widget(label) inside the frame, the color again becomes white.
Here's my code:
from tkinter import *
root = Tk()
root.geometry("700x600")
f = Frame(root, height = 400, width = 400, bg = 'black')
f.pack()
id = Label(f, text = "Email:", fg = 'blue', font = ('Kristen ITC', 18))
id.pack()
Your Frame is resizing itself to the Label. You need to set...:
...
f.pack_propagate(False)
f.pack()
...
In order for the Frame to maintain its own dimension without affected by the its children widgets.
By default, widgets shrink or expand to fit their contents. When you add the button, the frame shrinks down to fit.
It appears you want the frame to take up just a part of the root window. Instead of explicitly giving the frame a width and height, it's usually better to let tkinter do that for you. Fill the frame with whatever widgets you want, and let tkinter decide how big the frame should be. Then, use appropriate options for grid or pack to arrange them logically. When tkinter is allowed to make widgets the right size, you'll end up with a much more responsive UI.
For example, if you set the fill and expand options when you call pack on the frame, it will not shrink to fit. If you later need to add more widgets, you won't have to modify other parts of your code to make them fit.
f.pack(fill="both", expad=True)
You can also turn off this "shrink to fit" feature by calling f.pack_propagate(False), but that is rarely the right solution because it forces you to calculate sizes, and your calculations may be wrong if you run the program on a system with different fonts or different resolutions.
I have a transparent tkinter message widget and a label, one containing text the other an image, the image is only drawn in the parts where the text label is behind it. 1
I'm using python tkinter on windows 7 to draw the labels on the desktop on a transparent window, so what you're seeing in the background is my regular windows desktop, which might have something to do with it
Here are snippets of code, but there is alot more that's not relevant I think
x = Tk()
label = tkinter.Message(x, textvariable=text, font=('Terminal','10'), fg='white', bg='green', width=800, anchor='n')
label.master.overrideredirect(True)
label.master.geometry('+30+30')
label.master.lift()
label.master.wm_attributes('-transparentcolor', 'green')
label.pack()
Then this is inside a function which is called to display the plot
new_plot = Label(x, image=plot_image, fg='white', bg='green', anchor='n', width=640, height=480)
new_plot.image = plot_image
new_plot.master.wm_attributes('-transparentcolor', 'green')
new_plot.place(x = 20, y = 30, width=640, height=480)
new_plot.update()
Then at the end
x.mainloop()
I hope this is all that's relevant to the problem
I suspect it has to do with the fact that a tkinter window by default is 1x1 pixel in size. When you use place, tkinter will not expand the window to fit its contents.
The reason it works with the messagebox is because you are adding the messagebox to the root window with pack which will cause the window to grow.
The simple solution is to use new_plot.pack(...) instead of new_plot.place(...).
I am using Tkinter's Canvas to create simple graphics for my GUI. I notice that I want to place my shapes and text right at the corners of my canvas, but they are ending up partially hidden. For text, I see there is an anchor option which the documentation suggests being set to NW if, for example, I want to place the text in the top left corner, but even then I see just a little bit of the beginning of the text being cut off. Here is my code:
import Tkinter as tk
root = tk.Tk()
root.geometry("300x300")
c = tk.Canvas(root, bg="green", width=300, height=300)
c.pack(fill="both", side="right", expand=True)
c.create_text(0,0,text="Hello world!", anchor="nw")
root.mainloop()
I know I can adjust the coordinates of where the text starts and by trial and error figure out which one gives the best looking result, but I was wondering if there was a smarter way to do it.
I notice a similar thing when I try to create shapes, such as a circle:
import Tkinter as tk
root = tk.Tk()
root.geometry("300x300")
c = tk.Canvas(root, bg="green", width=300, height=300)
c.pack(fill="both", side="right",expand=True)
c.create_oval(0,0,300,300, fill="gray")
root.mainloop()
For the circle, the parts of the circle closest to the edges are being cut off. If I stretch and drag the window to be larger, I can see the far right and bottom parts of the circle, so they are being draw. I also don't see an option similar to anchor for the circle.
I am noticing the tiniest amount of white space around my canvas, between the canvas and the window. I set the pack options to fill out against all sides and to expand if extra space was available. I wondering if this is the problem.
Unfortunately, the canvas border and highlight ring are inside the widget and thus use some of the drawable area and can potentially hide parts of other objects.
The simplest solution is to set the highlightthickness and borderwidth attributes to zero:
c.configure(highlightthickness=0, borderwidth=0)
If you need a border and/or highlight ring, put the canvas inside a frame.
When I try to detect that a window is resized with tkinter, it works most of the time. However, there is one exception; that is, when resizing it for the first time vertically and making the window larger, nothing is picked up. I see the initial size when the window appears, but nothing after that if I try to immediately make the window larger vertically. However, if I try to make it vertically "taller," after resizing it another way (ie making it smaller or resizing horizontally), then it works fine.
Here's the gist of the code I'm using:
from Tkinter import *
main = Tk()
def resize(event):
print("The new dimensions are:",event.width,"x",event.height)
window.focus_set()
canvas = Canvas(main, width=850, height=400)
window = Frame(main, width=800, height=10)
window.focus_set()
canvas.bind("<Configure>", resize)
canvas.pack()
canvas.update()
window.pack()
main.mainloop()
Am I doing something wrong?
If it matters, I'm using Python 2.7.3 on 64 bit Ubuntu 12.10
EDIT: It seems as though the dimensions are either incorrect (horizontal enlargement) or not showing up at all (vertical enlargement) when the window size is above 852x402. Is this a problem with my window manager (ie, Unity)?
Change canvas = Canvas(main, width=850, height=400) by canvas = Canvas(main, width=850, height=400, bg="red") and see what happens.
Since the canvas is inside the root window, when you make the window vertically larger, you are not changing the canvas size or position. It maintains its maximum height of 400, and the handler is not called. However, in the case of the horizontal enlargement, its position is exactly the middle because of the call to pack(): That's why it moves, and the bound function is called.
The rest of the results when you make the window smaller both horizontally and vertically are as expected.
It's because the canvas is not being resized. You're setting the binding on the canvas, but you haven't configured the canvas to grow and shrink along with the containing window.
Try setting the background of the canvas and frame widgets to something distinctive and you'll see what I mean.
To fix the problem try setting the expand and fill attributes when packing your widgets.