Anchor's value looked reversed in tkinter, python3.7 - python

When I used anchor in place() mythod in tkinter, the button's position seems reverse to what I set.
from tkinter import *
win = Tk()
frame = Frame(win, relief=RAISED, borderwidth=1, width=400, height=300)
frame.pack(fill=BOTH, ipadx=5, ipady=5, expand=1)
button1 = Button(frame, text="Button 1")
button1.place(x=200, y=150, anchor=NW, width=200, height=150)
win.mainloop()
As u can see, I set the button anchor(I mean x=200, y=150) at the center of the frame, and the anchor's value is NW. The button should be placed in top left corner of the frame, but it turned out at bottom right corner of it, it's totally reversed.
I am so confused, and I try my best to look out in google, but it seems like no one has the same question as me, if anyone could help me out please?

The anchor specifies the part of the button that is to appear at the given coordinates. Setting the anchor to NW means that the northwest corner of the button is to appear at the given coordinates.
You've set the coordinates at 200,150, so the upper-left corner of the widget will be placed at that position, and that's exactly what is happening.

Related

Button to teleport you a specific part of a scrollable region, tkinter

This is the tkinter code I have used to create a scrollable region. I was wondering if there was a way I could add in a button which when you pressed it teleports you to a specific section of the scrollable region. Is it even possible?
self.canvas1 = Canvas(master, width=1200, height=700, scrollregion=(0,0,800,3000))
self.horizontalscroll = Scrollbar(master, orient=HORIZONTAL)
self.horizontalscroll.pack(side=BOTTOM, fill=X)
self.horizontalscroll.config(command=self.canvas1.xview)
self.verticalscroll = Scrollbar(master, orient=VERTICAL)
self.verticalscroll.pack(side=RIGHT, fill=Y)
self.verticalscroll.config(command=self.canvas1.yview)
self.canvas1.config(xscrollcommand=self.horizontalscroll.set, yscrollcommand=self.verticalscroll.set, bg="#4c5059")
self.canvas1.pack(fill=BOTH, expand=True)
self.frame1 = Frame(master)
self.frame1.configure(bg="#4c5059")
self.MainWindow = self.canvas1.create_window(10, 10, window=self.frame1, anchor='nw')
Yes, you can call the xview_moveto and yview_moveto methods to scroll anywhere you want. These take a value representing a percentage. Top/left is zero, bottom/right is 1.0, the middle is .5, etc.
For example, to show the bottom-right corner you could do this:
self.canvas1.xview_moveto(1.0)
self.canvas1.yview_moveto(1.0)

Canvas on a frame not being displayed

I have a Canvas inside a Frame in tkinter. The frame has a background color and the canvas too. But seemingly the frame background overrides the canvas color.
How can I increase the transparency of the frame background such that the canvas is visible?
import Tkinter
import tkMessageBox
from Tkinter import *
top = Tkinter.Tk()
frame = Frame(top, width=1000, height=1000, background="bisque")
frame.pack()
bottomframe = Frame(top, width=1000, height=1000, background="red")
bottomframe.pack( side = BOTTOM )
def creatLayers(no_of_layers, max_nodes_in_each_layer, frame1=bottomframe):
print 'here2'
listLayerRect=[]
listDelimiterRect=[]
#The canvas is created here.
mainCanvas=Tkinter.Canvas(frame1, bg="white", height=1000, width=1000)
frame1.pack(side=LEFT)
for i in range (0,no_of_layers):
print 'here3'
x=15*i
#rectangles that are being drawn on the canvas.
mainCanvas.create_polygon(x,0,x+10,0,x+10,1000,x,1000, outline='gray', fill='gray', width=2)
# listLayerRect.append(Tkinter.Canvas(frame1, bg="blue", height=1000, width=30))
# listDelimiterRect.append(Tkinter.Canvas(frame1, bg="yellow", height=1000, width=30))
L1 = Label(frame, text="Layers")
E1 = Entry(frame, bd =8)
L2 = Label(frame, text="Layers2")
def helloCallBack(E=E1,):
# tkMessageBox.showinfo( "Hello Python", "Hello World")
k=int(E.get())
print 'here'
print k
creatLayers(k,k)
B = Tkinter.Button(frame, text ="Enter", command = helloCallBack)
B.pack(side=LEFT)
#L1.pack(side=LEFT)
E1.pack(side=LEFT)
#L2.pack(side=LEFT)
top.mainloop()
So, basically, when you enter a number in the box and press Enter, a canvas gets created in the red part (frame) and a grid pattern should be drawn on that canvas. Essentially, there are 2 frames, the top frame contains the button and the entry box, the lower frame should be able to draw stuff inside on the canvas created within.
The reason why the canvas is not displayed is because you're not telling it to be displayed inside frame1, i.e. you forgot to pack (or grid, or place) it, so just do in the meantime:
...
mainCanvas=Tkinter.Canvas(frame1, bg="white", height=1000, width=1000)
mainCanvas.pack()
...
Now depending on what you really want to achieve from the layout point of view, you may need to think better how to use pack, grid and pack.
Here's the result after the correction above (on Mac OS X, Sierra)
Before clicking Enter
After clicking Enter
In general, just remember that a frame will have a empty body if it doesn't contain any widget with a certain specified size.

Python -> Labels cant be shown to Frame

Labels can't be shown into the leftFrame. I'm quite new to Python GUI. My code kinda goes like this:
from tkinter import *
root = Tk()
mainFrame = Frame(root, width=700, height=500)
mainFrame.pack()
leftFrame = Frame(mainFrame, bg="#c2c3c4")
leftFrame.place(relheight=1, relwidth=0.34, anchor=W)
label1 = Label(leftFrame, text="Label1")
label2 = Label(leftFrame, text="Label2")
label1.grid(columnspan=2, sticky=W, pady=(20, 0))
label2.grid(columnspan=3, sticky=W, pady=(5, 0))
root.mainloop()
In this particular case, you don't see the labels because they are off the screen. leftFrame has an anchor of W, which means that the vertical center of leftFrame is at 0,0. In other words, half of the frame is above the visible portion of the window.
A quick fix to prove this out is to use an anchor of NW instead of W, which will cause the upper-left corner of the frame to be at the upper-left corner of its parent.
However, I strongly encourage you to not use place at all. It has its uses, but really should rarely be used. You end up having to do a lot of work yourself, and the result is usually not very responsive to changes in fonts, resolutions, or window sizes.

Adding widgets over canvas in tkinter

I want to put a small image and other widgets over a canvas on which an image is displayed. I've tried options such ascompound and other things.
Background picture is fine and the small image that I want to put over the background image shows fine but it's always top or bottom of the window. I want it to be placed over any area of background image. I've tried many options of all the geometry manager (pack, grid, place) but none of them works. Please help, here's my code :
from Tkinter import *
root = Tk()
root.iconbitmap('E:/a.ico')
root.title('Unick Locker')
canvas = Canvas(root, width=730, height=600)
canvas.grid()
bgImg = PhotoImage(file="E:/a.gif")
canvas.create_image(370, 330, image=bgImg)
login = PhotoImage(file="E:/login.gif")
lo = Label(root, image=login)
lo.grid()
root.mainloop()
In order to add any widgets over or the foreground of any background image or canvas, the row and column values of all the widgets must be same as of the background image. so, my above mentioned program would be like this :
from Tkinter import *
root = Tk()
root.iconbitmap('E:/a.ico')
root.title('Unick Locker')
canvas = Canvas(root, width=730, height=600)
canvas.grid(row=0, column=0)
bgImg = PhotoImage(file="E:/a.gif")
canvas.create_image(370, 330, image=bgImg)
login = PhotoImage(file="E:/login.gif")
lo = Label(root, image=login)
lo.grid(row=0, column=0)
root.mainloop()
I tried putting the same row and column values to the widgets in grid() methods which I wanted to put over the image, and it worked fine as I wanted :-)
Have you considered using the paste method, which lets you define the position of the pasted image through a box argument?
See http://effbot.org/imagingbook/imagetk.htm.
Please also take a look at this thread: Tkinter, overlay foreground image on top of a background image with transparency, which seems very similar to your issue.
You are looking to draw the widgets over the canvas, this means you must specify the canvas as the parent widget, not the root as you did. For that, modify lo = Label(root, image=login) to lo = Label(canvas, image=login)
Also, do not forget to specify the rows and columns where you want to position the different widgets. This means you need to write, for example, lo.grid(row=0, column=0) instead of lo.grid(). For the moment you do not see big problems because you have only one label widget. But if you try to add an other widget without mentioning the exact positions (rows and columns) you will get unexpected results.
This question isn't about images at all, it's just a basic layout problem. You'll have the same issues with or without images. The problem is simply that you aren't giving any options to grid, so it naturally puts things at the top. Tkinter also has the behavior that a containing widget (eg: your canvas) will shrink or expand to exactly fit its contents.
Here's a version that creates several widgets over a background image. Notice the use of options to pack and grid, and the use of grid_rowconfigure and grid_columnconfigure to specify how extra space is allocated.
from Tkinter import *
root = Tk()
canvas = Canvas(root, width=730, height=600)
canvas.pack(fill="both", expand=True)
bgImg = PhotoImage(file="E:/a.gif")
canvas.create_image(370, 330, image=bgImg)
l1 = Label(canvas, text="Hello, world")
e1 = Entry(canvas)
t1 = Text(canvas)
l1.grid(row=0, column=0, sticky="ew", padx=10)
e1.grid(row=1, column=1, sticky="ew")
t1.grid(row=2, column=2, sticky="nsew")
canvas.grid_rowconfigure(2, weight=1)
canvas.grid_columnconfigure(2, weight=1)
root.mainloop()

How can I stack buttons rather than queue them in Tkinter?

At the moment I have 3 basic buttons being displayed:
from tkinter import *
root = Tk()
topFrame = Frame(root)
topFrame.pack(side=TOP)
leftFrame = Frame(root)
leftFrame.pack(side=LEFT)
botFrame = Frame(root)
botFrame.pack(side=BOTTOM)
button1 = Button(leftFrame, text="Button 1", fg="Black")
button2 = Button(leftFrame, text="Button 2", fg="Black")
button3 = Button(leftFrame, text="Button 3", fg="Black")
button1.pack(side=LEFT)
button2.pack(side=LEFT)
button3.pack(side=LEFT)
root.mainloop()
The 3 buttons at the moment will stick to the left frame on the window, however then will queue next to each other rather than stack one on top of the other, how do i fix this?
You're explicitly telling them to be side-by-side with side=LEFT. You want side=TOP so that they are placed at the top of the empty space in the frame.
button1.pack(side=TOP)
button2.pack(side=TOP)
button3.pack(side=TOP)
When you use pack, the values TOP, LEFT, RIGHT and BOTTOM tell the widget which side of the remaining space they should occupy. The first time you use LEFT it will reserve the left side of the whole frame for the widget. The next time you use LEFT, that refers to the space remaining in the widget excluding the left edge since that already has a widget in it. The net effect is that LEFT causes widgets to be arranged left-to-right, RIGHT arranges them right-to-left, and so on.
Explore the grid function. Change your pack statements to
button1.grid(row=0,column=0)
button2.grid(row=1,column=0)
button3.grid(row=2,column=0)

Categories