I am new to Python and even newer to Tkinter.
I am currently practicing how to use Frames and Labels and
the problem I am encountering is, when I put Labels on a frame with some buttons next to each label,
the alignment is not good to look at.
Here is the code:
from Tkinter import *
class GUI():
def __init__(self):
self.namelist = ["Mark","Anna","Jason","Lenna","Leo","Zucharich","Robinson","AReallyLongNameThatMightExist"]
self.canvas = Canvas(width=1200,height=700)
self.canvas.pack(expand=YES,fill=BOTH)
def Friends(self):
controlframe = Frame(self.canvas)
controlframe.place(x=600,y=300)
#Frame for showing names of friends
for x in self.namelist:
frame = Frame(controlframe)
frame.pack()
Name = Label(frame,text="%s "%x).pack(side=LEFT)
chatButton = Button(frame,text="Chat").pack(side=LEFT)
delButton = Button(frame,text="Delete").pack(side=LEFT)
setcloseButton = Button(frame,text="Set Close").pack(side=LEFT)
setgroupButton = Button(frame,text="Set Group").pack(side=LEFT)
mainloop()
GUI = GUI()
GUI.Friends()
What should I do so that the alignment of the Label(=name) and the button is equal to the other ones so that they will form a shape of a rectangle and not some zigzag?
It is almost always better in Tk to use the grid geometry manager. It is much more flexible once you come to understand how it works. Converting your example to use grid solves your problem as shown below but you should experiment with it a bit. Try removing the 'sticky="W"' from the label for instance and see that the centering of the widgets within the row or column can be controlled. To get your frame responding to resizes sensibly you should investigate the columnconfigure and rowconfigure options for the grid geometry management as well.
from Tkinter import *
class GUI():
def __init__(self):
self.namelist = ["Mark","Anna","Jason","Lenna",
"Leo","Zucharich","Robinson",
"AReallyLongNameThatMightExist"]
self.canvas = Canvas(width=1200,height=700)
self.canvas.pack(expand=YES,fill=BOTH)
def Friends(self):
frame = Frame(self.canvas)
frame.place(x=600,y=300)
#Frame for showing names of friends
row = 0
for x in self.namelist:
label = Label(frame,text="%s "%x)
chatButton = Button(frame,text="Chat")
delButton = Button(frame,text="Delete")
setcloseButton = Button(frame,text="Set Close")
setgroupButton = Button(frame,text="Set Group")
label.grid(row=row, column=0, sticky="W")
chatButton.grid(row=row, column=1)
delButton.grid(row=row, column=2)
setcloseButton.grid(row=row, column=3)
setgroupButton.grid(row=row, column=4)
row = row + 1
mainloop()
GUI = GUI()
GUI.Friends()
Related
I am writing an application in which the following steps are intended to be executed:
1 - user clicks in blue area (a wx.Panel) and a white circle appears;
2 - user clicks Select Start button;
3 - user clicks in the white circle and it changes to green (by drawing a green circle over the white one)
The problem is that when step 3 is executed the green circle does not appear where the mouse is clicked. For example, clicking in the blue area registers a point at (223, 486). After clicking the Select Start button and then clicking in the white circle a point registers at (211, 464), and a green circle appears outside the white circle. I don’t understand why this is happening and would appreciate any help in resolving the problem.
Using python 2.7 with wxPython 3.0.3.0 on MacOs
import wx
class Test(wx.Frame):
def __init__(self, parent, title):
super(Test, self).__init__(parent, title = title, size = (820,900))
self.startSelected = False
self.radius = 10
self.panel = wx.Panel(self, size=(800,800))
self.panel.SetBackgroundColour(wx.Colour(0,0,200))
self.panel.Bind(wx.EVT_LEFT_DOWN, self.onMouseDown)
self.gbs = wx.GridBagSizer(0,0)
self.startBtn = wx.Button(self, wx.ID_ANY, label = 'Select Start')
self.startBtn.Bind(wx.EVT_BUTTON, self.selectStart)
self.gbs.Add(self.panel, span = (1,4), pos=(1,1),flag=wx.EXPAND | wx.ALL)
self.gbs.Add(self.startBtn, pos=(2,1))
self.SetSizer(self.gbs)
def onMouseDown(self, e):
pt = e.GetPosition()
print pt.x, pt.y
if e.LeftDown():
if self.startSelected:
color = wx.Colour(0,255,0)
self.paint(pt, color)
else:
color = wx.Colour(255,255,255)
self.paint(pt, color)
def paint(self, pt, color):
dc = wx.ClientDC(self)
b = wx.Brush(color)
dc.SetBrush(b)
dc.DrawCircle(pt.x, pt.y, self.radius)
def selectStart(self, e):
self.startSelected = True
if __name__ == '__main__':
app = wx.App()
Test(None, 'Test')
app.MainLoop()
The wx.ClientDC is relative to the object passed to it. As coded in the paint method, dc = wx.ClientDC(self), self is the wx.Frame. Since drawing is done on the wx.Panel, dc = wx.ClientDC(self.panel) should be used. This results in the expected behavior.
I need to have a button which clears selected check boxes. Please anyone guide me. Thanks in advance.
import Tkinter
from Tkinter import*
top = Tkinter.Tk()
CheckVar1=IntVar()
CheckVar2=IntVar()
C1=Checkbutton(top, text = "Music", variable = CheckVar1,
onvalue = 1, offvalue = 0, height=5,
width = 20,activebackground="red",bg="green")
C2=Checkbutton(top, text = "Video", variable = CheckVar2,
onvalue = 1, offvalue = 0, height=5,
width = 20)
C1.pack()
C2.pack()
B = Tkinter.Button(top, text ="Hello",activebackground="red",
,bd=3,bg="green",width=5) #Button
B.pack()
top.mainloop()
Create a function that will set the value of CheckVar1 and CheckVar2 to 0.
def clear():
CheckVar1.set(0)
CheckVar2.set(0)
And then just link it with the button.
B = Tkinter.Button(top, text ="Hello",activebackground="red",
bd=3,bg="green",width=5, command = clear) #Button
BTW, you had an extra comma here.
class ManageExistingColleaguePanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
main_sizer = wx.BoxSizer(wx.VERTICAL)
con = sqlite3.connect("hs_audit.sqlite")
con.text_factory = str
cur = con.cursor()
cur.execute("SELECT engineer FROM T1")
myList = [r[0] for r in cur.fetchall()]
con.close()
main_sizer.AddStretchSpacer()
for n in range(0, len(myList)):
main_sizer.Add(wx.Button(self, wx.CENTER, label = str(myList[(n)]), size = (200, 35)))
main_sizer.AddStretchSpacer()
self.SetSizer(main_sizer)
I have been trying to get a column of buttons centered in the frame labeled with the contents of a column in a mysqlite3 table.
I can get the buttons in a column all labelled but can't get them centered. I have tried loads of different combinations to get this right, but get errors regarding undefined label or size variables. I can get a centered column of buttons but then I am unable to label them.
Any help please this is driving me mad.
At last. Can't seem to get the hang of the wxpython sizer syntax's.
Anyways here was the answer.
class ManageExistingColleaguePanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
main_sizer = wx.BoxSizer(wx.VERTICAL)
con = sqlite3.connect("hs_audit.sqlite")
con.text_factory = str
cur = con.cursor()
cur.execute("SELECT engineer FROM T1")
myList = [r[0] for r in cur.fetchall()]
con.close()
main_sizer.AddStretchSpacer()
for n in range(0, len(myList)):
main_sizer.Add(wx.Button(self, label=str(myList[(n)]), size=(200, 35)), 0, wx.CENTER)
main_sizer.AddStretchSpacer()
self.SetSizer(main_sizer)
Is there a way to get the cell size and x,y location of a cell's corner?I have radio buttons on the left side of my frame and I would like to resize an image based on the size of the frame.
What I'm going to end up doing is creating a block that takes up a large group of cells that will allow me to zoom in on my .tif and scroll left/right and up/down. Does this type of widget already exist?
Here's a very rough outline of what I currently have
from tkinter import *
from PIL import Image,ImageTk
import os
file_path = "C:/Users/..."
dirs = os.listdir(file_path)
root = Tk()
# Set window size slightly below screen size
width = int(root.winfo_screenwidth() - root.winfo_screenwidth()/9)
height = int(root.winfo_screenheight() - root.winfo_screenheight()/9)
root.geometry(str(width)+"x"+str(height))
class Application(Frame):
def __init__(self,master):
Frame.__init__(self,master)
os.chdir(file_path)
self.grid()
self.create_widgets()
def create_widgets(self):
Label(self,
text = "Available Files"
).grid(row=0,column=0,sticky=W)
Label(self,
text = "Select one:"
).grid(row=1,column=0,sticky=W)
self.filelist = StringVar()
self.filelist.set(0)
# Radio buttons of files in directory
i = 1
for files in dirs:
if os.path.isfile(os.path.join(file_path, files)):
i += 1
Radiobutton(self,
text=files,
variable=self.filelist,
value=files,
command=self.update_text
).grid(row=i,column=0,sticky=W)
# Message box
self.result = Text(self, width=40, height=5, wrap=WORD)
self.result.grid(row=i, column=0, columnspan=3)
def update_text(self):
message = "File selected is "
message += self.filelist.get()
self.display_image()
self.result.delete(0.0, END)
self.result.insert(0.0, message)
def display_image(self):
try:
self.image = Image.open(self.filelist.get())
except:
message += self.filelist.get() + " doesn't exist. This is awkward..."
img_width,img_height = self.image.size
self.preview_image = ImageTk.PhotoImage(self.image)
self.preview = Label(self, image=self.preview_image)
self.preview.grid(row=0, column=3, rowspan=20)
app = Application(root)
root.mainloop()
My programm create a Frame with three panels in an horizontal boxsizer. A menu with "new window" item for create a seconde Frame. I give the seconde panel as parent of the seconde window. I wante the seconde Frame stays in the seconde panel area of my first frame.
if user move one of the two windows, the seconde stays in the panel screen area.
Do you know a way or something for that?
I tried a little something, but using is not very aesthetic.
and
import wx
class MainWindow(wx.Frame):
def __init__(self,parent,id):
wx.Frame.__init__(self,parent,id,'Python Test App',size=(600,400))
#Widgets
panel_gch = wx.Panel(self,-1,size = (150,-1))
panel_gch.SetBackgroundColour('white')
self.panel=wx.Panel(self,-1,size=(300,400))
self.panel.SetBackgroundColour((200,230,200))
panel_drt = wx.Panel(self,-1,size = (150,-1))
panel_drt.SetBackgroundColour('white')
box = wx.BoxSizer(wx.HORIZONTAL)
self.SetSizer(box)
#Add
box.Add(panel_gch,0,wx.EXPAND)
box.Add(self.panel,1,wx.EXPAND)
box.Add(panel_drt,0,wx.EXPAND)
#Menu
status=self.CreateStatusBar()
menubar=wx.MenuBar()
file_menu=wx.Menu()
ID_FILE_NEW = 1
file_menu.Append(ID_FILE_NEW,"New Window","This is a new window")
menubar.Append(file_menu,"File")
self.SetMenuBar(menubar)
#bind and layout
self.Bind(wx.EVT_MENU, self.get_new_window)
panel_gch.Layout()
self.panel.Layout()
panel_drt.Layout()
self.Layout()
def get_new_window(self,event): # create new window
self.new = NewWindow(self.panel,-1)
self.new.Show(True)
self.new.Bind(wx.EVT_MOVE,self.window2_on_move)
def window2_on_move(self,event): # Window2 must stay in
x, y = event.GetPosition()
v,w =self.panel.GetScreenPosition()
s,t = self.panel.GetClientSizeTuple()
if x < v:
self.new.Move((v,-1))
if y < w:
self.new.Move((-1,w))
if x+200 > v+s:
self.new.Move((v+s-200,-1))
if y+200 > w+t:
self.new.Move((-1,w+t-200))
class NewWindow(wx.MiniFrame):
def __init__(self,MainWindow,id):
wx.MiniFrame.__init__(self, MainWindow, id, 'New Window', size=(200,200),\
style = wx.MINIMIZE | wx.CAPTION | wx.CLOSE_BOX | wx.CLOSE_BOX)
self.CenterOnParent()
if __name__=='__main__':
app=wx.PySimpleApp()
frame=MainWindow(parent=None,id=-1)
frame.Show()
app.MainLoop()
What you probably want is AUI. I personally recommend the wx.lib.agw.aui set rather than wx.aui as the former is pure Python and has had a LOT more recent work done on it. There are multiple examples in the wxPython demo package. You can also read about it here:
http://wxpython.org/Phoenix/docs/html/lib.agw.aui.framemanager.AuiManager.html
Thanks you very much Mike, exactly what I needed.
With wxpython I found This way:
the child stays in the panel area and it follows the window parent when moving.
import wx
class MainWindow(wx.Frame):
def __init__(self,parent,id):
wx.Frame.__init__(self,parent,id,'Python Test App',size=(600,400))
self.new = None
#Widgets
self.position = (0,0)
panel_gch = wx.Panel(self,-1,size = (150,-1))
panel_gch.SetBackgroundColour('white')
self.panel=wx.Panel(self,-1,size=(300,400))
self.panel.SetBackgroundColour((200,230,200))
panel_drt = wx.Panel(self,-1,size = (150,-1))
panel_drt.SetBackgroundColour('white')
box = wx.BoxSizer(wx.HORIZONTAL)
self.SetSizer(box)
#Add
box.Add(panel_gch,0,wx.EXPAND)
box.Add(self.panel,1,wx.EXPAND)
box.Add(panel_drt,0,wx.EXPAND)
#Menu
status=self.CreateStatusBar()
menubar=wx.MenuBar()
file_menu=wx.Menu()
ID_FILE_NEW = 1
file_menu.Append(ID_FILE_NEW,"New Window","This is a new window")
menubar.Append(file_menu,"File")
self.SetMenuBar(menubar)
#bind and layout
self.Bind(wx.EVT_MENU, self.get_new_window)
panel_gch.Layout()
self.panel.Layout()
panel_drt.Layout()
self.Layout()
def get_new_window(self,event): # create new window
if self.new == None:
self.win_one_move = False
self.new = NewWindow(self.panel,-1)
self.new.Show(True)
self.new.Bind(wx.EVT_MOVE,self.window2_on_move)
self.Bind(wx.EVT_MOVE,self.window1_on_move)
v,w =self.GetPosition()
x, y = self.new.GetPosition()
self.get_windows_position((x-v),(y-w))
def get_windows_position(self,x,y):
self.position = (x,y)
print "check",self.position
def window2_on_move(self,event): # Window2 must stay in
if self.win_one_move == False:
x, y = event.GetPosition()
v,w =self.panel.GetScreenPosition()
s,t = self.panel.GetClientSizeTuple()
new_x,new_y = self.new.GetClientSizeTuple()
if x < v:
self.new.Move((v,-1))
if y < w:
self.new.Move((-1,w))
if x+new_x > v+s:
self.new.Move((v+s-new_x,-1))
if y+new_y > w+t:
self.new.Move((-1,w+t-new_y))
v,w =self.GetPosition()
x,y = self.new.GetPosition()
self.get_windows_position((x-v),(y-w))
if self.win_one_move == True:
self.win_one_move = False
def window1_on_move(self,event):
self.win_one_move = True
print "1 move"
x,y = self.GetPosition()
self.new.Move((x+self.position[0],y+self.position[1]))
print self.position
class NewWindow(wx.MiniFrame):
def __init__(self,MainWindow,id):
wx.MiniFrame.__init__(self, MainWindow, id, 'New Window', size=(200,200),\
style = wx.CAPTION | wx.CLOSE_BOX | wx.CLOSE_BOX)
self.CenterOnParent()
if __name__=='__main__':
app=wx.PySimpleApp()
frame=MainWindow(parent=None,id=-1)
frame.Show()
app.MainLoop()
Can be use by another.Thanks