I have a button within a frame:
self.b = tk.Button(self.subframe1, text="UPDATE", command = self.update)
The text in this button will be centered horizontally but not vertically. Is it possible to do the latter?
As commented by #gandreadis, you can rely on anchor option to do the job.
Here is an MCVE (in Python 3.x):
import tkinter as tk
class Test:
def __init__(self, master):
self.master = master
self.configure_gui()
self.create_widgets()
self.configure_widgets()
def configure_gui(self):
self.master.title("Button Text Centering")
self.master.geometry('300x100')
self.master.resizable(0, 0)
def create_widgets(self):
self.create_demo_button()
def create_demo_button(self):
self.btn_with_centered_text = tk.Button(self.master, text="Centered")
self.btn_with_centered_text.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
self.btn_with_centered_text.config(bg="yellow")
def configure_widgets(self):
self.configure_btn_with_centered_text()
def configure_btn_with_centered_text(self):
self.btn_with_centered_text.config(bg="yellow", relief=tk.RAISED)
self.btn_with_centered_text.config(border="2px")
def main():
root = tk.Tk()
t = Test(root)
root.mainloop()
if __name__ == '__main__':
main()
Demo:
Related
Actually, i want to create a GUI to receive data via serial port, but i got a problem is that the button will be pressed continually till the whole data collation to be finished.
In order to make people to understand the situation what i encountered easily, i change the code in the bellow
from Tkinter import *
class GUIDemo(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.grid()
self.createWidgets()
# self.datarcv()
def createWidgets(self):
self.inputText = Label(self)
self.inputText["text"] = "Input:"
self.inputText.grid(row=0, column=0)
self.inputField = Entry(self)
self.inputField["width"] = 50
self.inputField.grid(row=0, column=1, columnspan=6)
self.regist = Button(self, command=self.datasave)
self.regist["text"] = "button"
self.regist.grid(row=2, column=0)
def datasave(self):
a=0
while a<100000000:
a+=1
print a
if __name__ == '__main__':
root = Tk()
app = GUIDemo(master=root)
app.mainloop()
You'll need to add a thread
from Tkinter import *
import threading
class GUIDemo(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.grid()
self.createWidgets()
# self.datarcv()
def createWidgets(self):
self.inputText = Label(self)
self.inputText["text"] = "Input:"
self.inputText.grid(row=0, column=0)
self.inputField = Entry(self)
self.inputField["width"] = 50
self.inputField.grid(row=0, column=1, columnspan=6)
self.regist = Button(self, command=self.datasave_thread)
self.regist["text"] = "button"
self.regist.grid(row=2, column=0)
def datasave_thread(self):
self.thread = threading.Thread(None, self.datasave, None, (), {})
self.thread.start()
def datasave(self):
a=0
while a<100000000:
a+=1
print a
if __name__ == '__main__':
root = Tk()
app = GUIDemo(master=root)
app.mainloop()
To keep this as short as possible - In my program I start with Page1 and when I press a button I want to open Page2 and close Page1, I have managed to open Page2 but I cant close Page1, I have tried using .destroy() but it closes everything not just the page. I looked around some questions here on SO but couldn't find much in the same layout as my code so I wasnt sure how to apply it to mine. This is my first tkinter project so I am still getting to grips with it.
My code is;
class Page1:
def __init__(self,master):
self.master = master
#lots of labels and buttons
self.BTNNextPage = ttk.Button(master, text = "Proceed",
command = self.NextPage)
self.BTNNextPage.place(x=450, y=420)
def NextPage(self):
self.newWindow = tk.Toplevel(self.master)
self.app = Page2(self.newWindow)
self.master.destroy()
class Page2():
def __init__(self,master):
self.master = master
#tried Page1.destroy() here but Page1 has no attibute destroy
#more labels and buttons
def main():
widthpixels=690
heightpixels=500
root = tk.Tk()
root.resizable(width=False, height=False)
root.configure(background='black')
root.iconbitmap("Image")
root.wm_title("Title")
root.geometry('{}x{}'.format(widthpixels, heightpixels))
app = Page1(root)
root.mainloop()
if __name__ == "__main__":
main()
If you destroy root, it destroys all the widgets contained, including Page2. To destroy only page 1, one possibility is to make the page classes inherit from tk.Frame, so that they have a destroy method:
import tkinter as tk
from tkinter import ttk
class Page1(tk.Frame):
def __init__(self, master, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
self.pack(fill='both', expand=True) # display page 1
#lots of labels and buttons:
tk.Label(self, text='Page 1').place(relx=0.5, rely=0.5)
self.BTNNextPage = ttk.Button(self, text="Proceed", command=self.NextPage)
self.BTNNextPage.place(x=450, y=420)
def NextPage(self):
self.app = Page2(self.master) # create page 2
self.destroy() # remove page 1
class Page2(tk.Frame):
def __init__(self, master, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
self.pack(fill='both', expand=True) # display page 2
# create widgets on page 2
tk.Label(self, text='Page 2').pack()
tk.Button(self, text='Quit', command=self.master.destroy).pack(side='bottom')
def main():
widthpixels=690
heightpixels=500
root = tk.Tk()
root.resizable(width=False, height=False)
root.configure(background='black')
root.wm_title("Title")
root.geometry('{}x{}'.format(widthpixels, heightpixels))
app = Page1(root)
root.mainloop()
if __name__ == "__main__":
main()
I am trying to create a main screen that is displayed only if the login is successful, but i cant figure out how to make the main screen visible/invisible
from tkinter import *
class Login_screen(Frame):
def __init__(self,master):
self.open_login()
def open_login(self):
self.root2 = Toplevel()
self.root2.geometry("400x200")
self.grid_forget()
self.app2 = Main_screen(self.root2)
class Main_screen(Frame):
def __init__(self,master):
Frame.__init__(self,master)
self.master.grid()
self.button = Button(master = self,text = "Close",command = lambda: self.close_windows())
self.button.grid()
def close_windows(self):
self.master.destroy()
Login_screen.master.grid()
root = Tk()
root.geometry("800x600")
app = Login_screen(root)
root.mainloop()
I figured out how it works:
from tkinter import *
class Main_screen(Frame):
def __init__(self,master):
Frame.__init__(self, master)
self.grid()
self.text = Label(text="Janela")
self.text.grid()
root.withdraw()
self.create_login()
def create_login(self):
self.root2 = Toplevel()
self.app2 = Login_screen(self.root2)
class Login_screen(Frame):
def __init__(self,master):
Frame.__init__(self,master)
self.grid()
self.botao1 = Button(self,text="Appear",command = lambda: self.show_main())
self.botao1.grid()
def show_main(self):
self.master.destroy()
root.deiconify()
root = Tk()
app = Main_screen(root)
root.mainloop()
I am new to python so I was trying to make a GUI, in that I have to place a button in a particular position.
I tried using self.nxt_form.place(x=200,y=100) instead of self.nxt_form.pack().
But the button disappeared and only the frame appeared when it ran. Can you tell me how to place the button in a particular position?
Here is the code:
import tkinter as tk
class Main_form:
def __init__(self, root,title="Simulated MTBF"):
self.root = root
self.frame = tk.Frame(self.root)
"""Button nxt_form which moves to next form"""
self.nxt_form = tk.Button(self.frame, text = 'Next Form', width = 25,command = self.new_window)
self.nxt_form.pack()
self.frame.pack()
"""command to open new window by clicking Button """
def new_window(self):
self.newWindow = tk.Toplevel(self.root)
self.app = Demo2(self.newWindow)
class Demo2:
def __init__(self, root):
self.root = root
self.frame = tk.Frame(self.root)
self.quitButton = tk.Button(self.frame, text = 'Quit', width = 25, command = self.close_windows)
self.quitButton.pack()
self.frame.pack()
def close_windows(self):
self.root.destroy()
def main():
root = tk.Tk()
app = Main_form(root)
root.mainloop()
if __name__ == '__main__':
main()
when i am using tkinter i used column and row to position objects
self.btn = tk.Button(self, text = "button")
self.btn.grid(row = 1, column = 1)
EDIT - expanded on information in response to comment (below)
I would make an label and change its width and height to make the spacing you need (note im a beginer at python as well so this is probly a bad way but it works)
from tkinter import *
import tkinter as tk
from tkinter.ttk import Combobox,Treeview,Scrollbar
class MainMenu(Frame):
def __init__(self, master):
""" Initialize the frame. """
super(MainMenu, self).__init__(master)
self.grid()
self.create_GUI()
def create_GUI(self):
frame1 = tk.LabelFrame(self, text="frame1", width=300, height=130, bd=5)
frame1.grid(row=0, column=0, columnspan=3, padx=8)
#the frame is not needed but it is a good thing to use as can group
#parts of your interface together
self.text1 = Entry(frame1)
#note if you were not using frames would just put self here
self.text1.grid(row = 1, column = 0)
self.text2 = Label(frame1, text = "",height = 10)
self.text2.grid(row = 2 , column = 0)
self.text3 = Entry(frame1)
self.text3.grid(row = 3, column = 0)
root = Tk()
root.title("hi")
root.geometry("500x500")
root.configure(bg="white")
app = MainMenu(root)
root.mainloop()
Also note that you can not use pack and grid together what you could do is group your objects in different frames then use grid in one frame and pack in a different frame. I personally prefer to use grid to pack as it gives you more control over your object then pack does
I am trying to create a program in tkinter which allows me to open an initial window then to keep it throughout all classes used. For example, if I was to create a button in a window then when I click this button, it would exuecute a method that destroys the widget, and then executes a new class that builds a new screen within the same window, such as text opposed to a button.
from tkinter import *
class Window1:
def __init__(self, master):
self.master = master
self.label = Button(self.master, text = "Example", command = self.load_new)
self.label.pack()
def load_new(self):
self.label.destroy()
## Code to execute next class
class Window2:
def __init__(self, master):
self.master = master
self.label = Label(self.master, text = "Example")
self.label.pack()
def main():
root = Tk()
run = Window1(root)
root.mainloop()
if __name__ == '__main__':
main()
I understand this is less practical, but I am curious. Cheers.
Tk() creates main window and variable root gives you access to this window. You can use root as argument for Window2 and you will have access to main window inside Window2
from tkinter import *
class Window1:
def __init__(self, master):
# keep `root` in `self.master`
self.master = master
self.label = Button(self.master, text="Example", command=self.load_new)
self.label.pack()
def load_new(self):
self.label.destroy()
# use `root` with another class
self.another = Window2(self.master)
class Window2:
def __init__(self, master):
# keep `root` in `self.master`
self.master = master
self.label = Label(self.master, text="Example")
self.label.pack()
root = Tk()
run = Window1(root)
root.mainloop()
--
Probably nobody use another class to create Label in place of Button ;)
--
EDIT: In this example using names Window1 and Windows2 is misleading because there is only one window and two classes which use this window. I would rather use names FirstOwner, SecondOwner
Everything is implemented in one Tk class and in this case there always is only one window.
from tkinter import *
from tkinter import ttk
class MainWindow():
def __init__(self, mainWidget):
self.main_frame = ttk.Frame(mainWidget, width=300, height=150, padding=(0, 0, 0, 0))
self.main_frame.grid(row=0, column=0)
self.some_kind_of_controler = 0
self.main_gui()
def main_gui(self):
root.title('My Window')
self.main_label_1 = ttk.Label(self.main_frame, text='Object_1')
self.main_label_1.grid(row=0, column=0)
self.main_label_2 = ttk.Label(self.main_frame, text='Object_2')
self.main_label_2.grid(row=1, column=0)
self.main_label_3 = ttk.Label(self.main_frame, text='Object_3')
self.main_label_3.grid(row=2, column=0)
self.setings_button = ttk.Button(self.main_frame, text='Setings')
self.setings_button.grid(row=0, column=1)
self.setings_button.bind('<Button-1>', self.setings_gui)
self.gui_elements = [self.main_label_1,
self.main_label_2,
self.main_label_3,
self.setings_button]
def setings_gui(self, event):
self.gui_elements_remove(self.gui_elements)
root.title('Setings')
self.main_label_1 = ttk.Label(self.main_frame, text='Object_1')
self.main_label_1.grid(row=2, column=0)
self.main_menu_button = ttk.Button(self.main_frame, text='Main menu')
self.main_menu_button.grid(row=0, column=1)
self.main_menu_button.bind('<Button-1>', self.back_to_main)
self.some_kind_of_controler = 1
self.gui_elements = [self.main_label_1,
self.main_menu_button]
def back_to_main(self, event):
if self.some_kind_of_controler == 1:
self.gui_elements_remove(self.gui_elements)
else:
pass
self.main_gui()
def gui_elements_remove(self, elements):
for element in elements:
element.destroy()
def main():
global root
root = Tk()
root.geometry('300x150+50+50')
window = MainWindow(root)
root.mainloop()
if __name__ == '__main__':
main()