Ttk Frame, Background color - python-3.x

I'm using ttk, for my GUI. I know that it is also a very simple question ... I am trying to change the background color of the main window.
I tried to change the theme, because I am working on a Mac, (and Python 3.5) to avoid the problem with the theme 'aqua', which is the default.I've been reading about several solutions like these questions which are about the same problem... These are the numbers of the questions:
54476511,
38712352,
47327266,
23750141.
But, I haven't Solve the problem, yet.
Here it's my code.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from tkinter.scrolledtext import *
from tkinter import Tk, BOTH, W, N, E, S, messagebox, END
from tkinter.ttk import Button, Label, Style, Frame
class Example(Frame):
def __init__(self,master):
super().__init__()
self.initUI()
def initUI(self):
self.master.title("Example")
Style().theme_use("classic")
self.pack(fill=BOTH, expand=1)
self.columnconfigure(1, weight=1)
self.columnconfigure(3, pad=7)
self.rowconfigure(3, weight=1)
self.rowconfigure(5, pad=7)
self.txt_Pad = ScrolledText(self)
self.txt_Pad.grid(row=1, column=0, columnspan=2, rowspan=4, padx=5, sticky=E+W+S+N)
self.txt_Pad.insert(END,'Type your info here')
btn_save = Button(self, text="Save", command=self.save_command)
btn_save.grid(row=1, column=3)
btn_close = Button(self, text="Close", command=self.onClose)
btn_close.grid(row=2, column=3, pady=4)
btn_help = Button(self, text="Help", command=self.about_command)
btn_help.grid(row=5, column=0, padx=5)
def onClose(self):
self.master.destroy()
def about_command(self):
msb = messagebox.showinfo("About", "\"Insert a useful tip Here\"")
def save_command(self):
print('Your info it\'s save now')
def open_command(self):
print('Choose your File')
def main():
root = Tk()
root.geometry("350x300+300+300")
root.configure(bg='#0059b3')
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
Any Suggestions would be appreciated.

Create a style then apply it.
from tkinter.scrolledtext import *
from tkinter import Tk, BOTH, W, N, E, S, messagebox, END
from tkinter.ttk import Button, Label, Style, Frame
class Example(Frame):
def __init__(self, master):
super().__init__()
self.initUI()
def initUI(self):
self.master.title("Example")
# create a new style
self.style = Style()
# configure it to the background you want
self.style.configure('My.TFrame', background='#0059b3')
#Style().theme_use("classic")
# apply it
self.config(style='My.TFrame')
self.pack(fill=BOTH, expand=1)
self.columnconfigure(1, weight=1)
self.columnconfigure(3, pad=7)
self.rowconfigure(3, weight=1)
self.rowconfigure(5, pad=7)
self.txt_Pad = ScrolledText(self)
self.txt_Pad.grid(row=1, column=0, columnspan=2, rowspan=4, padx=5, sticky=E+W+S+N)
self.txt_Pad.insert(END,'Type your info here')
btn_save = Button(self, text="Save", command=self.save_command)
btn_save.grid(row=1, column=3)
btn_close = Button(self, text="Close", command=self.onClose)
btn_close.grid(row=2, column=3, pady=4)
btn_help = Button(self, text="Help", command=self.about_command)
btn_help.grid(row=5, column=0, padx=5)
def onClose(self):
self.master.destroy()
def about_command(self):
msb = messagebox.showinfo("About", "\"Insert a useful tip Here\"")
def save_command(self):
print('Your info it\'s save now')
def open_command(self):
print('Choose your File')
def main():
root = Tk()
root.geometry("350x300+300+300")
root.configure(background='#0059b3')
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
I left comments at the parts I changed.

Related

How to create a class to close GUI and exit Python

I have been trying to find a way to do this for a while to no avail. I would like to create a class to completely close my GUI in tkinter and I'm not having much luck. I've tried sys.exit and .destroy() a few different ways. I can manage to do what I want without using classes but I'm rather new to OOP. Here is my code:
import sys as system
import tkinter as tk
from tkinter import ttk
class headerFrame(ttk.Frame):
def __init__(self, container):
super().__init__(container)
#setup the grid layout manager
self.columnconfigure(0, weight=1)
self._create_widgets()
def _create_widgets(self):
#header bar
canvas = tk.Canvas(self, bg='#0066cc', highlightthickness=0, height=45, width=600)
canvas.grid(column=0, row=0, sticky=tk.W)
label = ttk.Label(self, text='Production Assistant', background='#0066cc', foreground='White', font=('calibri', 18, 'bold'))
label.grid(row=0, column=0)
class loginFrame(ttk.Frame):
def __init__(self, container):
super().__init__(container)
#setup the grid layout manager
self.columnconfigure(0, weight =1)
self.columnconfigure(0, weight=3)
self._create_widgets()
def _create_widgets(self):
#username
ttk.Label(self, text='Username: ', justify='right').grid(row=0, column=0, sticky=tk.E)
username = ttk.Entry(self, width=33)
username.focus()
username.grid(row=0, column=1, sticky=tk.W)
#password
ttk.Label(self, text='Password: ', justify='right').grid(row=1, column=0, sticky=tk.E)
password = ttk.Entry(self, width=33, show='*')
password.grid(row=1, column=1, sticky=tk.W)
#add padding
for widget in self.winfo_children():
widget.grid(padx=0, pady=5)
class loginButtonFrame(ttk.Frame):
def __init__(self, container):
super().__init__(container)
#setup the grid layout manager
self.columnconfigure(0, minsize=62)
self._create_widgets()
def _create_widgets(self):
#buttons
ttk.Button(self, text='Login', width=15).grid(row=0, column=1)
ttk.Button(self, text='Forgot Login', width=15).grid(row=0, column=2)
ttk.Button(self, text='Request Access', width=15).grid(row=1, column=1)
ttk.Button(self, text='Exit', width=15, command=exitButton).grid(row=1, column=2)
#add padding to buttons
for widget in self.winfo_children():
widget.grid(padx=3, pady=3)
class exitButton():
def exit():
#code to close gui and program
#create the main application
class mainLogin(tk.Tk):
def __init__(self):
super().__init__()
self.title('Login')
self.geometry('325x175')
self.resizable(0, 0)
self.configure(background='#444444')
#windows only (remove the minimize/maximize buttons)
self.attributes('-toolwindow', True)
#TCL to center the screen
self.eval('tk::PlaceWindow . center')
#layout on the root window
self.columnconfigure(0, weight=1)
self._create_Styles()
self._create_widgets()
def _create_Styles(self):
#create styles
s = ttk.Style()
s.configure('TFrame', background='#444444')
s.configure('TLabel', background='#444444', foreground='white')
s.configure('TButton', background='#878683', foreground='black')
def _create_widgets(self):
#create the header frame
_header_frame = headerFrame(self)
_header_frame.grid(column=0, row=0)
#create the login frame
_login_frame = loginFrame(self)
_login_frame.grid(column=0, row=1, sticky=tk.N)
#create the button frame
_login_button_frame = loginButtonFrame(self)
_login_button_frame.grid(column=0, row=2)
if __name__ == '__main__':
app = mainLogin()
app.mainloop()
class exitButton() is what I would like to call from multiple different pages in the application to close everything.
Any help is appreciated, I'm trying to learn as I build so if you have any suggested reading based around Python that would help with this I would appreciate it!

How to show two Frames side by side in Tkinter

This is what I got
This is what I want to get
I've tried it like 2 hours with reading the documentation and every tutorial I could possibly find but after all I'm not able to display two ttk.Frames side by side with a border around them.
What have I done wrong?
This is my code so far (and yeah, I know, I've never used self.path but I just like to have it available in need):
import os
import tkinter as tk
import tkinter.ttk as ttk
from ttkthemes import ThemedTk
class GUI(ThemedTk):
def __init__(self):
super().__init__()
self.set_theme("breeze")
self.path = os.path.dirname(__file__)
self.title("Kniffel All In One")
self.defineVariables()
# Root Window
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=5)
self.columnconfigure(1, weight=1)
self.LeftFrame = ttk.Frame(self, border=True, borderwidth=1)
self.LeftFrame.grid(row=0, column=0, padx=5, pady=5, sticky="NSWE")
self.RightFrame= ttk.Frame(self, border=True, borderwidth=1)
self.RightFrame.grid(row=0, column=1, padx=5, pady=5, sticky="NSWE")
# LeftFrame
self.LeftEntry = ttk.Entry(self.LeftFrame, textvariable=self.text1).grid(row=0, column=0, ipadx=5, ipady=5, sticky="WE")
self.LeftLabel = ttk.Label(self.LeftFrame, text="Little test left side").grid(row=1, column=0, ipadx=5, ipady=5, sticky="WE")
# RightFrame
self.RightEntry = ttk.Entry(self.RightFrame, textvariable=self.text2).grid(row=0, column=0, ipadx=5, ipady=5, sticky="WE")
self.RightLabel = ttk.Label(self.RightFrame, text="Litte test right side").grid(row=1, column=0, ipadx=5, ipady=5, sticky="WE")
self.mainloop()
def defineVariables(self):
self.text1 = tk.StringVar()
self.text2 = tk.StringVar()
if __name__ == '__main__':
GUI()
Note that I didn't use .pack() and .grid() together and it doesn't display a border even though I thought border=True would show one.
Please be so kind to just answer my question since I haven't ask for aesthetics, readability or programming style improvements. Also this won't be a professional application.
Thanks for understanding this.

Web shortcut not doing what i want it to do

So before you question the code, im just trying to learn tkinter a bit more so i though this be best way haha.
I am currently stuck on the web input, everytime i input a website it comes as "https://%21browser.%21text!" and i dont know why. Random web works but it doesnt work as inputting it.
import webbrowser as wb
from tkinter import *
from tkinter import ttk
import tkinter as tk
import ctypes, random, time
class Browser(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.start()
def start(self):
global webinput
self.title = Label(self, text="Web Shortcut", fg="purple", font="Kokila 20 bold")
self.title.pack(fill=BOTH)
self.webinput = Text(self, height=1, width=57)
self.webinput.pack(side=TOP, fill=BOTH, pady=30, padx=30)
self.openweb = Button(self, height=2, width=20, text="Open Web", bg="gray", fg="lightgreen", command=self.web)
self.openweb.pack(side=LEFT, padx=10)
self.random = Button(self, height=2, width=20, text="Random Web", bg="gray", fg="lightgreen", command=self.randomweb)
self.random.pack(side=LEFT, padx=5)
self.exit = Button(self, height=2, width=20, text="Exit", bg="gray", fg="lightgreen", command=exit)
self.exit.pack(side=LEFT, padx=5)
def web(self):
try:
self.sites = "https://{}".format(self.webinput)
if self.sites:
wb.open(self.sites)
except Exception as e:
ctypes.windll.user32.MessageBoxW(0, str(e), "CRASHED", 0)
def randomweb(self):
self.websites = [
"www.facebook.com",
"www.google.com",
"www.youtube.com",
"www.amazon.co.uk"
]
self.sites = random.choice(self.websites)
self.visit = "https://{}".format(self.sites)
wb.open(self.visit)
if __name__ == "__main__":
root = Tk()
root.title("Web Shortcut")
root.resizable(False, False)
root.geometry("500x200")
app = Browser(master=root)
app.mainloop()
root.destroy()
I have made some change, now it works very well
import webbrowser as wb
from tkinter import *
from tkinter import ttk
import tkinter as tk
import ctypes, random, time
class Browser(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.start()
def start(self):
global webinput
self.title = Label(self, text="Web Shortcut", fg="purple", font="Kokila 20 bold")
self.title.pack(fill=BOTH)
self.webinput = Entry(self)
self.webinput.pack(side=TOP, fill=BOTH, pady=30, padx=30)
self.openweb = Button(self, height=2, width=20, text="Open Web", bg="gray", fg="lightgreen", command=self.web)
self.openweb.pack(side=LEFT, padx=10)
self.random = Button(self, height=2, width=20, text="Random Web", bg="gray", fg="lightgreen", command=self.randomweb)
self.random.pack(side=LEFT, padx=5)
self.exit = Button(self, height=2, width=20, text="Exit", bg="gray", fg="lightgreen", command=exit)
self.exit.pack(side=LEFT, padx=5)
def web(self):
try:
self.sites = f"https://{self.webinput.get()}"
if self.sites:
wb.open(self.sites)
except Exception as e:
ctypes.windll.user32.MessageBoxW(0, str(e), "CRASHED", 0)
def randomweb(self):
self.websites = [
"www.facebook.com",
"www.google.com",
"www.youtube.com",
"www.amazon.co.uk"
]
self.sites = random.choice(self.websites)
self.visit = "https://{}".format(self.sites)
wb.open(self.visit)
if __name__ == "__main__":
root = Tk()
root.title("Web Shortcut")
root.resizable(False, False)
root.geometry("500x200")
app = Browser(master=root)
app.mainloop()
root.destroy()
Hope it helps. (●'◡'●)

How to update matplotlib embedded into tkinter?

The problem is that I want to draw a plot by clicking on a button but it doesn't work. However, when I call draw from __init__, the plot appears on the screen.
Plotter.py
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
class Plotter(FigureCanvasTkAgg):
def __init__(self, master):
self.figure = Figure(dpi=100)
super().__init__(self.figure, master=master)
self.axes = self.figure.add_subplot(111)
self.get_tk_widget().grid(column=0, row=0, sticky='nsew')
def draw(self):
self.axes.clear()
x_list = [x for x in range(0, 100)]
y_list = [x^3 for x in x_list]
self.axes.plot(x_list, y_list, color='y')
MainApplication.py
from tkinter import ttk
import tkinter as tk
import plotter
class MainApplication(ttk.Frame):
def __init__(self, master, *args, **kwargs):
super().__init__(root)
self.grid(column=0, row=0, sticky='nsew')
frame = ttk.Frame(self, borderwidth=8)
frame.grid(column=0, row=0, sticky='nsew')
frame.rowconfigure(0, weight=1)
notes = ttk.Notebook(frame)
notes.grid(column=0, row=0, sticky='nsew')
notes.rowconfigure(0, weight=1)
page = ttk.Frame(notes)
notes.add(page, text='Picture')
plot = plotter.Plotter(page)
# plot.draw() # This call updates the plot
input_frame = ttk.Frame(self)
input_frame.grid(column=1, row=0, sticky='nsew')
# this binding doesn't update the plot
button = ttk.Button(input_frame, text='Plot', \
command=lambda: plot.draw())
button.grid(column=0, row=4, columnspan=2, sticky='ew')
root = tk.Tk()
MainApplication(root)
root.mainloop()
Personally I would write this up in a single class so that we can use class attributes and methods to control everything with ease. Also you do not need a lambda here. Just save the reference to the command button and not a lambda call. That said you were also overwriting the draw method of FigureCanvasTkAgg so change the draw() method to something else.
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from tkinter import ttk
import tkinter as tk
class MainApplication(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
notes = ttk.Notebook(self)
notes.grid(column=0, row=0, sticky='nsew')
notes.rowconfigure(0, weight=1)
self.page = ttk.Frame(notes)
notes.add(self.page, text='Picture')
self.plotter()
input_frame = ttk.Frame(self)
input_frame.grid(column=1, row=0, sticky='nsew')
button = ttk.Button(input_frame, text='Plot', command=self.new_draw)
button.grid(column=0, row=4, columnspan=2, sticky='ew')
def plotter(self):
self.figure = Figure(dpi=100)
self.plot_canvas = FigureCanvasTkAgg(self.figure, self.page)
self.axes = self.figure.add_subplot(111)
self.plot_canvas.get_tk_widget().grid(column=0, row=0, sticky='nsew')
def new_draw(self):
self.axes.clear()
x_list = [x for x in range(0, 100)]
y_list = [x^3 for x in x_list]
self.axes.plot(x_list, y_list, color='y')
self.plot_canvas.draw_idle()
MainApplication().mainloop()
You overwrote the canvas' draw method without reimplementing it. But since you do not want to update your plot on every draw-event anyways, I'd suggest to call the method to update the plot differently, e.g. draw_lists. Inside draw_lists you would then need to call the draw method of the canvas (or in this case better draw_idle).
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
class Plotter(FigureCanvasTkAgg):
def __init__(self, master):
self.figure = Figure(dpi=100)
super().__init__(self.figure, master=master)
self.axes = self.figure.add_subplot(111)
self.get_tk_widget().grid(column=0, row=0, sticky='nsew')
def draw_lists(self):
self.axes.clear()
x_list = [x for x in range(0, 100)]
y_list = [x^3 for x in x_list]
self.axes.plot(x_list, y_list, color='y')
self.draw_idle()
from tkinter import ttk
import tkinter as tk
class MainApplication(ttk.Frame):
def __init__(self, master, *args, **kwargs):
super().__init__(root)
self.grid(column=0, row=0, sticky='nsew')
frame = ttk.Frame(self, borderwidth=8)
frame.grid(column=0, row=0, sticky='nsew')
frame.rowconfigure(0, weight=1)
notes = ttk.Notebook(frame)
notes.grid(column=0, row=0, sticky='nsew')
notes.rowconfigure(0, weight=1)
page = ttk.Frame(notes)
notes.add(page, text='Picture')
plot = Plotter(page)
input_frame = ttk.Frame(self)
input_frame.grid(column=1, row=0, sticky='nsew')
# this binding doesn't update the plot
button = ttk.Button(input_frame, text='Plot', \
command=lambda: plot.draw_lists())
button.grid(column=0, row=4, columnspan=2, sticky='ew')
root = tk.Tk()
MainApplication(root)
root.mainloop()

askopenfilename() disables editing tkinter Entry [duplicate]

This question already has answers here:
No input possible after tk
(2 answers)
Closed 4 years ago.
I'm using the following code to open a file, read its lines into a list and filter them using a substring from an Entry:
def get_entries(self):
"""
Open a file and load entries into a list.
"""
try:
# self.file_name = "p1.py"
self.file_name = askopenfilename(title="Open file")
self.file_handle = open(self.file_name, "r")
except IOError:
messagebox.showinfo("Info", "No file has been openned.")
self.destroy()
else:
self.entry_list = self.file_handle.readlines()
self.update_list()
def update_list(self, *args):
"""
Update the list after each editing of the search filter
"""
search_term = self.search_var.get()
self.lbox.delete(*self.lbox.get_children())
for index, item in enumerate(self.entry_list):
if search_term.lower() in item.lower():
self.lbox.insert('', END, values=(index, item))
Why does it work fine using self.file_name = "p1.py" but using askopenfilename() disables editing the Entry?
Minimizing and restoring the window with the Entry fixes the problem.
I'm using PyCharm on Windows 10
Here is the rest of the code for reference:
from tkinter import *
from tkinter import messagebox
from tkinter import ttk
from tkinter.filedialog import askopenfilename
class Application(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.file_name = ""
self.file_handle = ""
self.entry_list = None
self.search_label = Label(self, text="Filter: ")
self.search_var = StringVar()
self.search_var.trace("w", self.update_list)
self.search_entry = Entry(self, textvariable=self.search_var)
self.lbox = ttk.Treeview(self, columns=('indices', 'entries'), displaycolumns='entries', show='headings')
self.lbox.heading('entries', text="Entries", anchor="w")
self.confirm = Button(self, text="Confirm", width=10, command=self.confirm_action)
self.cancel = Button(self, text="Cancel", width=10, command=quit)
self.search_label.grid(row=0, column=0, sticky=E, padx=12, pady=5)
self.search_entry.grid(row=0, column=1, sticky=W, columnspan=4, pady=5)
self.lbox.grid(row=1, column=0, columnspan=3, sticky=(N, W, S, E), padx=12, pady=5)
self.cancel.grid(row=2, column=0, pady=5)
self.confirm.grid(row=2, column=1, sticky=W, padx=12, pady=5)
self.grid_columnconfigure(0, weight=1, uniform="u")
self.grid_columnconfigure(1, weight=1, uniform="u")
self.grid_columnconfigure(2, weight=4, uniform="u")
self.get_entries()
def get_entries(self): ...
def update_list(self, *args): ...
def confirm_action(self): ...
root = Tk()
root.title('Filter Listbox Test')
app = Application(master=root)
app.mainloop()
This seems to be a problem due to calling the askfilename before the root window is drawn. As a workaround you can add self.update() before you call askopenfilename.
class Application(Frame):
def __init__(self, master=None):
# ... stuff ...
self.update()
self.get_entries()
I'll file a bug report about this right now.

Resources