How do I use Tkinter buttons to open webrowsers properly? - python

Everything looks right, but when I run the program the buttons and the websites open at the same time and then the buttons don't work?
import webbrowser
from tkinter import *
from tkinter import ttk
root = Tk()
style = ttk.Style()
open_facebook = webbrowser.open('http://www.facebook.com')
open_google = webbrowser.open('http://www.google.com')
open_yahoo = webbrowser.open('http://www.yahoo.com')
open_youtube = webbrowser.open('http://www.youtube.com')
style.configure("TButton",
font="Serif 18",
padding=10)
main_frame = Frame(root)
main_frame.grid(row=0, columnspan=4)
button_facebook = ttk.Button(main_frame, text='Facebook', command=open_facebook).grid(row=1, column=0)
button_google = ttk.Button(main_frame, text='Google', command=open_google).grid(row=1, column=1)
button_yahoo = ttk.Button(main_frame, text='Yahoo', command=open_yahoo).grid(row=1, column=2)
button_youtube = ttk.Button(main_frame, text='Youtube', command=open_youtube).grid(row=1, column=3)
root.mainloop()

I couldn't manage to make it work with the code you had presented, but I could make it work using lambda in the command portion of the button. This was the only way I could ensure that the web browser didn't open the sites until the buttons were pressed.
import webbrowser
from tkinter import *
from tkinter import ttk
root = Tk()
style = ttk.Style()
style.configure("TButton",
font="Serif 18",
padding=10)
main_frame = Frame(root)
main_frame.grid(row=0, columnspan=4)
button_facebook = ttk.Button(main_frame, text='Facebook', command= lambda:
webbrowser.open('http://www.facebook.com'))
button_google = ttk.Button(main_frame, text='Google', command= lambda:
webbrowser.open('http://www.google.com'))
button_yahoo = ttk.Button(main_frame, text='Yahoo', command= lambda:
webbrowser.open('http://www.yahoo.com'))
button_youtube = ttk.Button(main_frame, text='Youtube', command= lambda:
webbrowser.open('http://www.youtube.com'))
button_facebook.grid(row=1, column=0)
button_google.grid(row=1, column=1)
button_yahoo.grid(row=1, column=2)
button_youtube.grid(row=1, column=3)
root.mainloop()

Related

Copy a label on tkinter and change the text on button click?

I have some program of this kind of type:
from tkinter import *
def apply_text(lbl_control):
lbl_control['text'] = "This is some test!"
master = Tk()
lbl = Label(master)
btn = Button(master, text="apply", command=lambda: apply_text(lbl))
lbl.pack()
btn.pack()
mainloop()
My aim now is to copy the text of the label lbl itself without any ability to change it. I tried the following way to solve the problem:
from tkinter import *
def apply_text(lbl_control):
lbl_control.insert(0, "This is some test!")
master = Tk()
lbl = Entry(master, state="readonly")
btn = Button(master, text="apply", command=lambda: apply_text(lbl))
lbl.pack()
btn.pack()
mainloop()
because of state = "readonly" it is not possible to change the text insert of lbl anymore. For that reason nothing happens if I click on the button apply. How can I change it?
There is a simple way to do that simple first change the state of entry to normal, Then insert the text, and then change the state back to readonly.
from tkinter import *
def apply_text(lbl_control):
lbl_control['state'] = 'normal'
lbl_control.delete(0,'end')
lbl_control.insert(0, "This is some test!")
lbl_control['state'] = 'readonly'
master = Tk()
lbl = Entry(master, state="readonly")
btn = Button(master, text="apply", command=lambda: apply_text(lbl))
lbl.pack()
btn.pack()
mainloop()
There is another way to do this using textvariable.
Code:(Suggested)
from tkinter import *
def apply_text(lbl_control):
eText.set("This is some test.")
master = Tk()
eText = StringVar()
lbl = Entry(master, state="readonly",textvariable=eText)
btn = Button(master, text="apply", command=lambda: apply_text(lbl))
lbl.pack()
btn.pack()
mainloop()

How to open a link with an specific button? Tkinter

Basically, when I want to open a specific link with a specific button it won't work. When you click the second button, it opens all the links inside the function.
from tkinter import *
import webbrowser
root = Tk()
root.title("links")
root.geometry("700x500")
root.config(bg="#3062C7")
def links_unit1():
global vid_1, vid_2
bg_v1 = Canvas(root, bg="#3062C7", width=700, height=500)
bg_v1.place(x=0, y=0)
vid_1 = Button(root, text="Virtual memory", command=all_vids1)
vid_1.place(x=20, y=20)
vid_2 = Button(root, text="lossy, lossless", command=all_vids1)
vid_2.place(x=30, y=50)
def all_vids1():
if vid_1:
webbrowser.open("https://youtu.be/AMj4A1EBTTY")
elif vid_2:
webbrowser.open("https://youtu.be/v1u-vY6NEmM")
vid_unit1 = Button(root, text="Unit 1", command=links_unit1)
vid_unit1.place(x=10, y=10)
root.mainloop()
You can't do it by checking the values of vid_1 and vid_2 because they will always be truthy. Instead you can create to anonymous function "on-the-fly" by using a lambda expression for the command= option of the Button as shown below:
from tkinter import *
import webbrowser
root = Tk()
root.title("links")
root.geometry("700x500")
root.config(bg="#3062C7")
def links_unit1():
bg_v1 = Canvas(root, bg="#3062C7", width=700, height=500)
bg_v1.place(x=0, y=0)
vid_1 = Button(root, text="Virtual memory",
command=lambda: webbrowser.open("https://youtu.be/AMj4A1EBTTY"))
vid_1.place(x=20, y=20)
vid_2 = Button(root, text="Lossy, Lossless",
command=lambda: webbrowser.open("https://youtu.be/v1u-vY6NEmM"))
vid_2.place(x=30, y=50)
vid_unit1 = Button(root, text="Unit 1", command=links_unit1)
vid_unit1.place(x=10, y=10)
root.mainloop()

How to seperate Tkinter Gui app source code into multiple files

i'm working on downloading manager python gui app using Tkinter and halfway there my code started to look very messy so i decided to seperate functions on different file and then import it:
my main code:
from tkinter import *
from functions import add_download
root = Tk()
root.title("The Pownloader!")
canvas = Canvas(root, width=700, height=500).pack()
# Buttons:
ADD_BUTTON = Button(root, text="ADD", bd=4, height=2, width=5, command=add_download)
SETTINGS_BUTTON = Button(root, text="SETTINGS", bd=4, height=2, width=5)
ABOUT_BUTTON = Button(root, text="ABOUT", bd=4, height=2, width=5)
EXIT_BUTTON = Button(root, text="EXIT", bd=4, height=2, width=5, command=quit)
# Mini-Buttons:
PAUSE_MINI_BUTTON = Button(root, text="PAUSE", font=(None, "8"), height=2, width=3)
RESUME_MINI_BUTTON = Button(root, text="RESUME", font=(None, "8"), height=2, width=3)
REMOVE_MINI_BUTTON = Button(root, text="REMOVE", font=(None, "8"), height=2, width=3)
# Side_Mini_Buttons:
DOWNLOAD_WINDOW = Button(root, text="Downloads", font=(None, "8"), height=3, width=6)
ERRORS_WINDOW = Button(root, text="Failed", font=(None, "8"), height=3, width=6)
COMPLETED_WINDOW = Button(root, text="Completed", font=(None, "8"), height=3, width=6)
# Positionning Buttons:
ADD_BUTTON.place(x=70, y=20)
SETTINGS_BUTTON.place(x=145, y=20)
ABOUT_BUTTON.place(x=220, y=20)
EXIT_BUTTON.place(x=295, y=20)
PAUSE_MINI_BUTTON.place(x=290, y=455)
RESUME_MINI_BUTTON.place(x=340, y=455)
REMOVE_MINI_BUTTON.place(x=390, y=455)
DOWNLOAD_WINDOW.place(x=1, y=100)
ERRORS_WINDOW.place(x=1, y=160)
COMPLETED_WINDOW.place(x=1, y=220)
# Download Frame:
DOWNLOAD_LIST_LABEL = Label(root, text="Download List:")
DOWNLOAD_LIST_LABEL.place(x=70, y=80)
DOWNLOAD_ENTRIES = Listbox(root, width=70, height=19)
DOWNLOAD_ENTRIES.place(x=70, y=100)
# Main Loop:
root.mainloop()
However my functions.py code looks like this:
def add_download():
# Defining The Pop-up frame:
top = Toplevel(root, width = 420, height = 150)
top.title("New Download")
# Putting on widgets:
link = StringVar()
LINK_LABEL = Label(top, text = "Paste Link:")
FIELD_ENTRY = Entry(top, width = 40, textvariable=link)
def on_click():
link_to_verify = (link.get()).strip()
if len(link_to_verify)>15:
if link_to_verify[0:11]=="http://www.":
DOWNLOAD_ENTRIES.insert(0, link_to_verify)
else:
print("Stupid")
else:
print("not a valid link")
BUTTONS_WIDGET = Frame(top)
ADD_BUTTON = Button(BUTTONS_WIDGET, text = "Add", width=10, command=on_click)
CANCEL_BUTTON = Button(BUTTONS_WIDGET, text = "Cancel", width=10, command=top.destroy)
# Positionning everythig:
LINK_LABEL.grid(column=0,row=0)
FIELD_ENTRY.grid(column=1,row=0)
BUTTONS_WIDGET.grid(column=1,row=2)
ADD_BUTTON.grid(column=0,row=0)
CANCEL_BUTTON.grid(column=1,row=0)
basically i wanted the function to call and show a pop-up window, i'm sure this could done in a million times better but i'm just learning, however i receive an error says:
Toplevel is not defined
Every file needs to import tkinter.
In addition, any variables in the main file which are needed by the imported functions need to be passed into the functions. For example, you should define add_download to accept the root window as a parameter.
def add_download(root):
...
Then, in the main program, pass root as that parameter:
ADD_BUTTON = Button(root, ..., command=lambda: add_download(root))
You will need to build a class to manage it.
Inside run.py:
import tkinter as tk
from interface import GUI
root = tk.Tk()
GUI(root)
Then inside your interface.py script you can call in additional modules:
import tkinter as tk
from aux import AuxGUI
from menu import MenuGUI
class GUI:
def __init__(self, master):
self.master = master
self.GUI_list = []
self.AuxGUI = AuxGUI(self.master, self.GUI_list) # Additional module
self.MenuGUI = MenuGUI (self.master, self.GUI_list) # Additional module
Then you can use OOP to access functions or objects to dynamically interact with each other.
self.GUI_list.append(self.AuxGUI)
self.GUI_list.append(self.MenuGUI)
Inside menu.py identify the correct index from the GUI_list:
import tkinter as tk
class MenuGUI:
def __init__(self, master, GUI_list):
self.master = master
self.AuxGUI = GUI_list[0]

TTk radio button

I have defined a class 'exemple' where i did two radio buttons , when i press 'bu1 ' spangender dont take any value.help me please
from tkinter import *
from tkinter import ttk
class exemple():
def like(self):
root = Tk()
style = ttk.Style()
style.theme_use('classic')
spangender = StringVar()
rb1 = ttk.Radiobutton(root, text='male', variable=spangender, value='male')
rb1.grid(column=0, row=0)
rb2 = ttk.Radiobutton(root, text='female', variable=spangender, value='female')
rb2.grid(column=1, row=0)
bu1 = ttk.Button(root, text='ok', command=lambda: get())
bu1.grid(column=2, row=1)
def get():
print(spangender.get())#Dosen't work
root.mainloop()
root = Tk()
style = ttk.Style()
style.theme_use('classic')
def get():
ab = exemple()
ab.like()
bu1 = ttk.Button(root, text='ok', command=lambda: get())
bu1.grid(column=2, row=1)
root.mainloop()

How to add themes?

I just picked up python recently and I've been working on a project called "ToDoList.py".It's finished but I want to add a button to change the theme of the GUI using tkinter / ttk but its not working.
This is the error:
Traceback (most recent call last):
File "todolist.py", line 64, in <module>
lbl_title = Label(root, text="ToDoList", bg="white")
File "C:\Users\Sam\AppData\Local\Programs\Python\Python37-32\lib\tkinter\ttk.py", line 761, in __init__
Widget.__init__(self, master, "ttk::label", kw)
File "C:\Users\Sam\AppData\Local\Programs\Python\Python37-32\lib\tkinter\ttk.py", line 559, in __init__
tkinter.Widget.__init__(self, master, widgetname, kw=kw)
File "C:\Users\Sam\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 2296, in __init__
(widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: unknown option "-bg"
I don't understand why this error is possible since i haven't adjusted the widgets yet
from tkinter import *
from tkinter import ttk
from tkinter.ttk import *
from ttkthemes import themed_tk as tk
import random
import tkinter.messagebox
#--------root style
root = Tk()
#--------root backgroud
root.configure(bg="white")
#--------root title
root.title("Reminder")
#--------root size
root.geometry("225x300")
#--------create empty list
tasks = []
#--------fuction
def darkmd():
root.get_themes()
root.set_theme("equilux")
#--------command
lbl_title = Label(root, text="ToDoList", bg="white")
lbl_title.grid(row=0, column=0)
lbl_display = Label(root, text="", fg="black", bg="white")
lbl_display.grid(row=0, column=1)
txt_input = Entry(root, width=20, fg="black", bg="white")
txt_input.grid(row=1, column=1)
bt_add_task = Button(root, text="Add Task", fg="black", bg="white", command = add_task)
bt_add_task.grid(row=1, column=0)
bt_del_all = Button(root, text="Del all", fg="black", bg="white", command = del_all)
bt_del_all.grid(row=2, column=0)
bt_del_one= Button(root, text="Del", fg="black", bg="white", command = del_one)
bt_del_one.grid(row=3, column=0)
bt_sort_asc = Button(root, text="Sort (ASC)", fg="black", bg="white", command = sort_asc)
bt_sort_asc.grid(row=4, column=0)
bt_sort_desc = Button(root, text="Sort (DESC)", fg="black", bg="white", command = sort_desc)
bt_sort_desc.grid(row=5, column=0)
bt_total_task = Button(root, text="Num Of Task", fg="black", bg="white", command = total_task)
bt_total_task.grid(row=6, column=0)
bt_darkmd = Button(root, text="Darkmode", fg="black", bg="white", command = darkmd)
bt_darkmd.grid(row=7, column=0)
lb_tasks = Listbox(root,fg="black", bg="white")
lb_tasks.grid(row=2, column=1, rowspan=9)
#--------main
root.mainloop()
As an alternative to ThemedTk, you can use ThemedStyle. This way your code will be exactly like if you were using one of the standard ttk themes except that you define your style with style = ThemedStyle(root) instead of style = Style(root). Then you simply use style.theme_use(<theme name>) to change theme and you can list the available themes with style.theme_names().
from tkinter import ttk
import tkinter as tk
from ttkthemes import ThemedStyle
#--------root style
root = tk.Tk()
#--------root backgroud
root.configure(bg="white")
#--------root title
root.title("Reminder")
#--------root size
root.geometry("225x300")
# white theme
style = ThemedStyle(root)
style.theme_use('arc') # white style
#--------create empty list
tasks = []
#--------function
def darkmd():
style.theme_use("equilux") # only changes the theme of the ttk widgets
# change style of tk widgets manually:
bg = style.lookup('TLabel', 'background')
fg = style.lookup('TLabel', 'foreground')
root.configure(bg=style.lookup('TLabel', 'background'))
lb_tasks.configure(bg=bg, fg=fg)
#--------command
lbl_title = ttk.Label(root, text="ToDoList")
lbl_title.grid(row=0, column=0)
lbl_display = ttk.Label(root, text="")
lbl_display.grid(row=0, column=1)
txt_input = ttk.Entry(root, width=20)
txt_input.grid(row=1, column=1)
bt_add_task = ttk.Button(root, text="Add Task")
bt_add_task.grid(row=1, column=0)
bt_del_all = ttk.Button(root, text="Del all")
bt_del_all.grid(row=2, column=0)
bt_del_one = ttk.Button(root, text="Del")
bt_del_one.grid(row=3, column=0)
bt_sort_asc = ttk.Button(root, text="Sort (ASC)")
bt_sort_asc.grid(row=4, column=0)
bt_sort_desc = ttk.Button(root, text="Sort (DESC)")
bt_sort_desc.grid(row=5, column=0)
bt_total_task = ttk.Button(root, text="Num Of Task")
bt_total_task.grid(row=6, column=0)
bt_darkmd = ttk.Button(root, text="Darkmode", command=darkmd)
bt_darkmd.grid(row=7, column=0)
lb_tasks = tk.Listbox(root, fg="black")
lb_tasks.grid(row=2, column=1, rowspan=9)
#--------main
root.mainloop()
Clear theme:
Dark theme:
Note that only the ttk widgets become dark after setting the theme to "equilux". So you need to manually change the colors of your tk widgets in darkmd() (like I did for root and lb_tasks).
Comment: HowTo using: ttkthemes
To use ttkthemes change to the following:
No style.theme_use(... statement, as this is alredy done in __init__(....
from ttkthemes import ThemedTk
class App(ThemedTk):
def __init__(self):
super().__init__("equilux")
# ATTENTION!!
# The following could fail as i couldn't test with `ThemedTk`
# ATTENTION!!
style = ttk.Style(self)
style.configure("TLabel", background="white")
Question: How to add themes?
First you have to understand, not to mix tkinter and tkinter.ttk widgets in a uncontrolled way. Only tkinter.ttk widgets can be styled using theme and style.
TkDocs - Tk Tutorial - Styles and Themes
tkinterbook - Widget Styling
Use only the following common import statements
import tkinter as tk
import tkinter.ttk as ttk
To instantiate a ttk widget use:
Note: You can't use bg= on a ttk widget!
lbl_title = ttk.Label(root, text="ToDoList")
Application wide usage:
Note: It's important to do all style definition once and before any widget instantiation.
class App(tk.Tk):
def __init__(self):
super().__init__()
style = ttk.Style(self)
style.theme_use('clam')
style.configure("TLabel", background="white")
self.title("Tkinter Style")
self.geometry("225x300")
lbl_title = ttk.Label(self, text="ToDoList")
lbl_title.grid(row=0, column=0)
if __name__ == "__main__":
App().mainloop()
Tested with Python: 3.5
After reading your comment, I thought my input may help.
First, identify your OS. Windows/Mac
Second, open IDLE and then open IDLE preferences
You will see the settings and in "Highlights", below the radio buttons for the themes, you will see a drop box that allows you to switch your themes from IDLE Dark to Classic and New!

Categories