I would like to update a label once I press one of the buttons.
Here is my code - I added a label (caled label1), now I have two issues:
It presents some gibberish
How do I update the label with text right when the user is pressing the Browse button?
from tkinter import *
import threading
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.init_window()
def init_window(self):
self.var = IntVar()
self.master.title("GUI")
self.pack(fill=BOTH, expand=1)
quitButton = Button(self, text="Exit", command=self.client_exit)
startButton = Button(self, text="Browse", command=self.start_Button)
label1 = Label(self, text=self.lable_1)
quitButton.grid(row=0, column=0)
startButton.grid(row=0, column=2)
label1.grid(row=1, column=0)
def client_exit(self):
exit()
def lable_1(self):
print('starting')
def start_Button(self):
def f():
print('Program is starting')
t = threading.Thread(target=f)
t.start()
root = Tk()
root.geometry("250x50")
app = Window(root)
root.title("My Program")
root.mainloop()
Use self.label['text'] to change text
(Minimal?) Working example:
import tkinter as tk
class Window(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
# tk.Frame.__init__ creates self.master so you don't have to
#self.master = master
self.init_window()
def init_window(self):
self.pack(fill=tk.BOTH, expand=1)
quit_button = tk.Button(self, text="Exit", command=root.destroy)
start_button = tk.Button(self, text="Browse", command=self.on_click)
self.label = tk.Label(self, text="Hello")
quit_button.grid(row=0, column=0)
start_button.grid(row=0, column=1)
self.label.grid(row=1, column=0, columnspan=2)
def on_click(self):
self.label['text'] = "Starting..."
root = tk.Tk()
app = Window(root)
root.mainloop()
Related
Here is my code so far for a GUI I am making in tkinter, I have attempted to change the background colour of the window but it doesn't seem to work.
from tkinter import *
from tkinter.font import Font
class Window(Frame):
def __init__(self, master = None):
Frame.__init__(self, master)
self.master = master
self.init_window()
def init_window(self):
self.master.title("Main Menu")
self.pack(fill=BOTH, expand=1)
videoButton = Button(self, text="Video Mode", font=helv18, bg="white", height=1, width=18)
videoButton.place(relx=0.5, rely=0.35, anchor=CENTER)
timelapseButton = Button(self, text="Time-lapse Mode", font=helv18, bg="white", height=1, width=18)
timelapseButton.place(relx=0.5, rely=0.6, anchor=CENTER)
root = Tk()
helv18 = Font(family='Helvetica', size=18, weight='bold')
root.config(bg='black')
root.geometry("480x320")
root.resizable(0, 0)
app = Window(root)
root.mainloop()
I'm working on a small GUI to query information from our CMDB to display for users. The trouble I am having is after an event in one class occurs(button), I want to update a combobox in another class. I thought I should use tk.StringVar() to pass the list, but the combobox only shows a 'PC_VAR#' value and doesn't update. Could anyone offer any assistance please?
#!/usr/bin/python
import Tkinter as tk
import ttk
import signal
class LoginUI:
def __init__(self, frame):
self.frame = frame
# Set default list entry
self.dc_list = tk.StringVar()
self.dc_list.set(['Login first'])
# Add a button to log in
self.button = tk.Button(self.frame, text='Login', command=self.change_combobox)
self.button.grid(column=0, row=0, pady=5)
def change_combobox(self):
# Change combobox values
dc_list = ['Site_1', 'Site_2', 'Site_3']
self.dc_list.set(dc_list)
class QueryUI:
def __init__(self, frame, dc_list):
self.frame = frame
self.dc = tk.StringVar()
self.dc_list = tk.StringVar()
self.dc_list.set(dc_list)
# Create site combobox
tk.Label(self.frame, text='Site:').grid(column=0, row=0, sticky="w")
self.dc_combobox = ttk.Combobox(
self.frame,
textvariable=self.dc,
width=20,
state='readonly'
)
self.dc_combobox['values'] = self.dc_list.get()
self.dc_combobox.grid(column=1, row=0, sticky="w")
class App:
def __init__(self, root):
self.root = root
self.root.title('Logging Handler')
self.root.columnconfigure(0, weight=1)
self.root.rowconfigure(0, weight=1)
# Create the left frame panels
left_frame = tk.Frame(self.root, padx=5, pady=5)
login_frame = tk.LabelFrame(left_frame, text="Login", borderwidth=2, relief="groove", padx=5, pady=5)
query_frame = tk.LabelFrame(left_frame, text="Query", borderwidth=2, relief="groove", padx=5, pady=5)
# Align frames
left_frame.grid(row=0, column=0, sticky="nw")
login_frame.grid(row=0, column=0, pady=5, sticky="nw")
query_frame.grid(row=1, column=0, pady=5, sticky="nw")
# Initialize all frames
self.login = LoginUI(login_frame)
self.query = QueryUI(query_frame, self.login.dc_list)
self.root.protocol('WM_DELETE_WINDOW', self.quit)
self.root.bind('<Control-q>', self.quit)
signal.signal(signal.SIGINT, self.quit)
def quit(self, *args):
self.root.destroy()
def main():
root = tk.Tk()
app = App(root)
app.root.mainloop()
if __name__ == '__main__':
main()
What I would do here is pass the controlling class (app) to the class needed to update the combobox. This way we can interact with it later if need be. By passing self of App to LoginUI we can then interact with the class attributes and methods of App from within LoginUI. This makes it a simple matter to update the combobox.
That said you really don't Need all the StringVars. Just past the list as a list and you will be good to go.
import Tkinter as tk
import ttk
import signal
class LoginUI:
def __init__(self, controller, frame):
self.controller = controller
self.frame = frame
self.dc_list = ['Login first']
self.button = tk.Button(self.frame, text='Login', command=self.change_combobox)
self.button.grid(column=0, row=0, pady=5)
def change_combobox(self):
self.controller.query.dc_combobox['values'] = ['Site_1', 'Site_2', 'Site_3']
self.controller.query.dc.set('Site_1')
class QueryUI:
def __init__(self, frame, dc_list):
self.frame = frame
self.dc = tk.StringVar()
tk.Label(self.frame, text='Site:').grid(column=0, row=0, sticky="w")
self.dc_combobox = ttk.Combobox(self.frame, textvariable=self.dc, width=20, state='readonly')
self.dc_combobox['values'] = dc_list
self.dc_combobox.grid(column=1, row=0, sticky="w")
class App:
def __init__(self, root):
self.root = root
self.root.title('Logging Handler')
self.root.columnconfigure(0, weight=1)
self.root.rowconfigure(0, weight=1)
left_frame = tk.Frame(self.root, padx=5, pady=5)
login_frame = tk.LabelFrame(left_frame, text="Login", borderwidth=2, relief="groove", padx=5, pady=5)
query_frame = tk.LabelFrame(left_frame, text="Query", borderwidth=2, relief="groove", padx=5, pady=5)
left_frame.grid(row=0, column=0, sticky="nw")
login_frame.grid(row=0, column=0, pady=5, sticky="nw")
query_frame.grid(row=1, column=0, pady=5, sticky="nw")
self.login = LoginUI(self, login_frame)
self.query = QueryUI(query_frame, self.login.dc_list)
self.root.protocol('WM_DELETE_WINDOW', self.quit)
self.root.bind('<Control-q>', self.quit)
signal.signal(signal.SIGINT, self.quit)
def quit(self, *args):
self.root.destroy()
if __name__ == '__main__':
root = tk.Tk()
app = App(root)
app.root.mainloop()
I am writing a Password code. I need a way to put to commands into one button so that it will destroy the window and get the username and password when I click the login button. I have looked through this site and non of the methods work for me so I need clarity on what I need to do to fix this.
from tkinter import *
import tkinter.messagebox as tm
class LoginFrame(Frame):
def __init__(self, master):
super().__init__(master)
self.label_1 = Label(self, text="Username")
self.label_2 = Label(self, text="Password")
self.entry_1 = Entry(self)
self.entry_2 = Entry(self, show="*")
self.label_1.grid(row=0, sticky=E)
self.label_2.grid(row=1, sticky=E)
self.entry_1.grid(row=0, column=1)
self.entry_2.grid(row=1, column=1)
self.checkbox = Checkbutton(self, text="Keep me logged in")
self.checkbox.grid(columnspan=2)
***def destroy(self):
self.destroy()
self.logbtn = Button(self, text="Login", command = self._login_btn_clickked,)
self.logbtn.grid(columnspan=2)
self.pack()
def _login_btn_clickked(self):
username = self.entry_1.get()
password = self.entry_2.get()
if username == "jake" and password == "hey":
tm.showinfo("Login info", "Welcome Jake")
master=Tk()
def login2():
tm.showinfo("Logging in", "Logging In...")
b = Button(master, text="Enter GUI", command=login2)
b.pack()
else:
tm.showerror("Login error", "Incorrect username")***
root = Tk()
lf = LoginFrame(root)
root.mainloop()
You should never call Tk() more than once in your program. If you need additional windows, use Toplevel().
However, in your case you don't need that either. You are on the right track of destroying the frame, now you just need to initiate a new frame. We can put that logic into a Tk class:
import tkinter as tk
class Mainframe(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.frame = FirstFrame(self)
self.frame.pack()
def change(self, frame):
self.frame.pack_forget() # delete currrent frame
self.frame = frame(self)
self.frame.pack() # make new frame
class FirstFrame(tk.Frame):
def __init__(self, master=None, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
master.title("Enter password")
master.geometry("300x200")
self.status = tk.Label(self, fg='red')
self.status.pack()
lbl = tk.Label(self, text='Enter password')
lbl.pack()
self.pwd = tk.Entry(self, show="*")
self.pwd.pack()
self.pwd.focus()
self.pwd.bind('<Return>', self.check)
btn = tk.Button(self, text="Done", command=self.check)
btn.pack()
btn = tk.Button(self, text="Cancel", command=self.quit)
btn.pack()
def check(self, event=None):
if self.pwd.get() == 'password':
self.master.change(SecondFrame)
else:
self.status.config(text="wrong password")
class SecondFrame(tk.Frame):
def __init__(self, master=None, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
master.title("Main application")
master.geometry("600x400")
lbl = tk.Label(self, text='You made it to the main application')
lbl.pack()
if __name__=="__main__":
app=Mainframe()
app.mainloop()
I'm learning about Tkinter and trying to create a normal looking chat style window. However, when resizing the window there are some unexpected results, such as a gray frame appearing between the items, despite setting expand=1.
Also how can I set it so the space is shared when resizing the window to be smaller than the original?
Here is my code:
from Tkinter import *
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def initUI(self):
frame = Frame(self, relief=RAISED, borderwidth=1)
scrollbar = Scrollbar(self)
scrollbar.pack(side=RIGHT, fill=Y)
self.msgfield = Text(self, wrap=WORD, yscrollcommand=scrollbar.set)
self.msgfield.pack(side=TOP, fill=BOTH, expand=1)
self.msgfield.config(state=DISABLED)
self.inputbox = Text(self, height=2, width=30)
self.inputbox.pack(fill=BOTH, side=BOTTOM, expand=0)
self.inputbox.bind('<Return>', self.retrieve_input)
frame.pack(fill=BOTH, expand=1, side=BOTTOM)
self.pack(fill=BOTH, expand=1, side=TOP)
def retrieve_input(self, event):
msg = self.inputbox.get(1.0, END)[:-1]
self.msgfield.config(state=NORMAL)
self.msgfield.insert(END, msg)
self.msgfield.see(END) # Scroll if necessary
self.msgfield.config(state=DISABLED)
self.inputbox.delete(0.0, END)
def main():
root = Tk()
root.geometry("300x400+300+300")
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
The issue is that you are packing both your msgfield and inputbox into self instead of frame, and self is the Tk instance which acts a bit different than a Frame. Try packing into your frame and I think you'll get the behaviour you want (note I added a black border to the Text widget so I could see it):
from Tkinter import *
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
frame = Frame(self, relief=RAISED, borderwidth=1)
scrollbar = Scrollbar(self)
scrollbar.pack(side=RIGHT, fill=Y)
self.msgfield = Text(frame, wrap=WORD, yscrollcommand=scrollbar.set)
self.msgfield.pack(side=TOP, fill=BOTH, expand=1)
self.msgfield.config(state=DISABLED)
self.inputbox = Text(frame, height=2, width=30, borderwidth=2)
self.inputbox.config(highlightbackground="Black")
self.inputbox.pack(fill=BOTH, side=BOTTOM, expand=0)
self.inputbox.bind('<Return>', self.retrieve_input)
frame.pack(fill=BOTH, expand=1, side=BOTTOM)
self.pack(fill=BOTH, expand=1)
def retrieve_input(self, event):
msg = self.inputbox.get(1.0, END)[:-1]
self.msgfield.config(state=NORMAL)
self.msgfield.insert(END, msg)
self.msgfield.see(END) # Scroll if necessary
self.msgfield.config(state=DISABLED)
self.inputbox.delete(0.0, END)
def main():
root = Tk()
root.geometry("300x400+300+300")
app = Example(root)
app.mainloop()
if __name__ == '__main__':
main()
I'm trying to create a root window with a black background to blend with my button backgrounds.
I have the following:
class Application(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
...
def initUI(self):
self.outputBox = Text(bg='black', fg='green', relief=SUNKEN, yscrollcommand='TRUE')
self.outputBox.pack(fill='both', expand=True)
self.button1 = Button(self, text='button1', width=40, bg ='black', fg='green', activebackground='black', activeforeground='green')
self.button1.pack(side=RIGHT, padx=5, pady=5)
self.button2 = Button(self, text='button2', width=20, bg='black', fg='green', activebackground='black', activeforeground='green')
self.button2.pack(side=LEFT, padx=5, pady=5)
...
def main():
root = Tk()
root.geometry('1100x350+500+300')
root.configure(background = 'black')
app = Application(root)
root.mainloop()
But root.configure(background = 'black') isn't changing the root window's background color... any suggestions?
This works (Check how parent root is referenced):
Edit: I edited the code and figure to make clear where colors are set:
from Tkinter import *
class Application(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.parent = master
self.initUI()
def initUI(self):
self.outputBox = Text(self.parent, bg='yellow', height= 10, fg='green', relief=SUNKEN, yscrollcommand='TRUE')
self.outputBox.pack(fill='both', expand=True)
self.button1 = Button(self.parent, text='button1', width=20, bg ='blue', fg='green', activebackground='black', activeforeground='green')
self.button1.pack(side=RIGHT, padx=5, pady=5)
self.button2 = Button(self.parent, text='button2', width=25, bg='white', fg='green', activebackground='black', activeforeground='green')
self.button2.pack(side=LEFT, padx=5, pady=5)
def main():
root = Tk()
app = Application(root)
app.parent.geometry('300x200+100+100')
app.parent.configure(background = 'red')
app.mainloop()
main()
Its 'bg' not 'background' in the .configure line.