How to make Tkinter and Selenium work together - python

Hello , my question is how can i make command a and b work at the same time , i tried threading but the thread executes the command immediatelly , thanks in advace for the help !
I am a beginner programmer so any help with this issue would help a lot , this project is intended to be a refresh bot but i can't figure it out !
import tkinter as tk
from time import sleep
from selenium import webdriver
def a():
driver1 = webdriver.Chrome(executable_path="/Users/user/Downloads/chromedriver")#your file
driver1.get(entry.get())
while True:
sleep(5)
driver1.refresh()
def b():
app.destroy()
def c():
entry.delete(0, tk.END)
app = tk.Tk()
app.title("Youtube Bot")
app.geometry("425x350")
app.resizable(False, False)
app.configure(bg="#333436")
textOne = tk.Label(
text = "Youtube Bot",
font = ("Helvetica", 28),
fg = "white",
bg = "#333436",
height = "1"
)
textOne.grid(pady = 10)
entry = tk.Entry(
app,
width = 25,
font = ("Arial", 15),
fg = "white",
bg = "#6b6d75"
)
entry.focus_set()
entry.grid(padx=10, pady=18 )
entry.get()
entry.insert(0, "Paste Video Link")
buttonRefresh = tk.Button(
text = "Delete",
font = ("Arial", 15),
width = 8,
command = c
)
buttonRefresh.grid(padx = 6)
buttonOne = tk.Button(
text = "Start process",
font =("Helvetica", 20),
height = "3",
width = "20",
command = a
)
buttonOne.grid()
buttonTwo = tk.Button(
text="Stop process",
font=("Helvetica", 20),
height="3",
width="20",
command = b
)
buttonTwo.grid(pady=20)
textOne.grid(row = 0, column = 1)
entry.grid(row = 1, column = 1)
buttonRefresh.grid(row = 1, column = 0)
buttonOne.grid(row = 2, column = 1)
buttonTwo.grid(row = 3, column = 1)
app.mainloop()

This is where the thread runs, to call this thread, you would do a().start()
class a(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global driver1
driver1 = webdriver.Chrome(executable_path="/Users/user/Downloads/chromedriver")
driver1.get(entry.get())
while True:
sleep(5)
driver1.refresh()
Note I have defined driver1 so I can access it and close it when you call the function b
I changed this line:
buttonOne = tk.Button(text = "Start process",font =("Helvetica", 20),height = "3",width = "20",command = a)
To:
buttonOne = tk.Button(text = "Start process",font =("Helvetica", 20),height = "3",width = "20",command = lambda: a().start())
Becuase:
Since its a().start()) not just a, you need to include lambda, so the class a is only called when buttonOne is pressed.
I also included driver1.close() in the function b to also close the browser when you quit the app.
Full code:
from time import sleep
from selenium import webdriver
import threading
class a(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global driver1
driver1 = webdriver.Chrome(executable_path="/Users/user/Downloads/chromedriver")
driver1.get(entry.get())
while True:
sleep(5)
driver1.refresh()
def b():
app.destroy()
driver1.close()
def c():
entry.delete(0, tk.END)
app = tk.Tk()
app.title("Youtube Bot")
app.geometry("425x350")
app.resizable(False, False)
app.configure(bg="#333436")
textOne = tk.Label(text = "Youtube Bot",font = ("Helvetica", 28),fg = "white",bg = "#333436",height = "1")
textOne.grid(pady = 10)
entry = tk.Entry(app,width = 25,font = ("Arial", 15),fg = "white",bg = "#6b6d75")
entry.focus_set()
entry.grid(padx=10, pady=18 )
entry.get()
entry.insert(0, "Paste Video Link")
buttonRefresh = tk.Button(text = "Delete",font = ("Arial", 15),width = 8,command = c)
buttonRefresh.grid(padx = 6)
buttonOne = tk.Button(text = "Start process",font =("Helvetica", 20),height = "3",width = "20",command = lambda: a().start())
buttonOne.grid()
buttonTwo = tk.Button(text="Stop process",font=("Helvetica", 20),height="3",width="20",command = b)
buttonTwo.grid(pady=20)
textOne.grid(row = 0, column = 1)
entry.grid(row = 1, column = 1)
buttonRefresh.grid(row = 1, column = 0)
buttonOne.grid(row = 2, column = 1)
buttonTwo.grid(row = 3, column = 1)
app.mainloop()
The line driver1 = webdriver.Chrome(executable_path="/Users/user/Downloads/chromedriver") was originally defined outside class a
This meant it looked something like this
driver1 = webdriver.Chrome(executable_path="/Users/user/Downloads/chromedriver")
class a(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
driver1.get(entry.get())
while True:
sleep(5)
driver1.refresh()
This would mean that every time you start the program driver1would be automatically defined, resulting in the browser opening.
So I just moved driver1 in class a so that when buttonOne is pressed, that is when driver1 would be defined, and then that's when the browser would open.
I also made driver1 a global variable so you can access it when calling the function:
def b():
app.destroy()
driver1.close()

Related

First tkinter project ,trying to find a way to make my tkinter buttons change boolean values for future if statements

I couldnt seem to find a way to make my program realise that ive selected a button, so i changed the function of the celcius to farenheit to try to make it change a boolean value to determine what conversion the program is doing
def celcius_to_farenheit(_event = None):
c_to_f = True
f_to_c = False
the idea being later i can use if statments later in the end result function to find what conversion its doing and display results in the status bar
def end_result():
if c_to_f == True:
converted_temperature = (valid_temperature * 9/5) + 32
label_status.configure(text = converted_temperature, fg = "Orange")
currently i seem to have functions running without me pressing buttons as well, when start the program it immediatly goes to the error message ive created for input muct be numeric even if i havent pressed the celcius to farenheit button.
Any help regarding how to propely have my celcius to farenheit and farenheit to celcius buttons confirm its a float and change a value to use for determining which calculation its using would be helpfull. Knowing why the error message comes up automatically is a bonus.
Below is my code thank you for your time and help.
import sys
from tkinter import *
from tkinter.tix import *
c_to_f = True
def clear_reset(_event = None):
entry_temperature.delete(0, END)
label_status.configure(text = "All data cleared", fg = "Orange")
def end_program(_event = None):
sys.exit()
def convert_temp(_event = None):
try:
valid_temperature = float(entry_temperature.get())
except:
label_status.configure(text = "Input must be numeric", fg = "Orange")
def end_result():
if c_to_f == True:
converted_temperature = (valid_temperature * 9/5) + 32
label_status.configure(text = converted_temperature, fg = "Orange")
def celcius_to_farenheit(_event = None):
c_to_f = True
f_to_c = False
def farenheit_to_celcius(_event = None):
f_to_c = True
c_to_f = False
window = Tk()
window.geometry("550x200")
window.resizable(False, False)
window.title("Temperature Conversion")
tooltip = Balloon(window)
label_input_Temperature = Label(text = "Temperature",fg = "Green")
label_input_Temperature.grid(row= 0, column=0)
entry_temperature = Entry(window, bg = "light blue" )
entry_temperature.grid(row=0, column=1)
temp_button_c_to_f = Button(window, text = "Celcius to Farenheit", command = celcius_to_farenheit)
temp_button_c_to_f.grid(row = 1, column=0)
window.bind('<Shift-c>', celcius_to_farenheit)
tooltip.bind_widget(temp_button_c_to_f, msg = "Shift + C")
temp_button_f_to_c = Button(window, text = "Farenheit to Celcius")
temp_button_f_to_c.grid(row = 1, column = 1 )
conversion_button = Button(window, text = "Convert", command = convert_temp)
conversion_button.grid(row = 2, column = 0,padx =0 )
window.bind('<Enter>', convert_temp)
tooltip.bind_widget(conversion_button, msg = "Enter")
clear_button = Button(window, text = "Clear", command = clear_reset)
clear_button.grid(row = 2, column = 1)
window.bind('<Control-c>', clear_reset)
tooltip.bind_widget(clear_button, msg = "Ctrl + C")
exit_button = Button(window, text = "Exit")
exit_button.grid(row = 2, column = 2, padx = 20, pady = 20)
window.bind('<Control-x>', end_program)
tooltip.bind_widget(exit_button, msg = "Ctrl + X")
label_status = Label(window, width = 50, borderwidth = 2, relief= RIDGE,bg= "Grey" )
label_status.grid(row = 4, column = 1)
tooltip.bind_widget(label_status, msg = "Displays results / error messages")
label_status.configure(text = "Enter in your temperature and select your conversion", fg = "Orange")
window.mainloop()

Python program can't handle running exes

My program stops working after successfully running the two exes. here is the code:
from tkinter import *
import os
root = Tk()
root.geometry('350x150')
root.title("hurler")
photo = PhotoImage(file = "Logo_Image.png")
root.iconphoto(False, photo)
entry_text = Label(text = "Number of posts you wish to automate (between 1-12) * ")
entry_text.place(x = 15, y = 10)
num = StringVar()
time_entry = Entry(textvariable = num, width = "10")
time_entry.place(x = 15, y = 40)
def action():
global num
num = num.get()
if num == '1':
os.startfile('.\\hurl\\hurl.exe')
# exit()
if num == '2':
os.startfile('.\\hurl\\hurl.exe')
os.startfile('.\\hurl2\\hurl.exe')
# exit()
num = StringVar()
register = Button(root,text = "Make", width = "10", height = "2", command = action, bg = "lightblue")
register.place(x = 15, y = 70)
root.mainloop()
hurl takes in text entries and then runs a web driver exe after pressing the Post button. Heres a sample block from code from hurl:
from tkinter import *
import os
from time import sleep
root = Tk()
root.geometry('600x600')
root.title("hurl")
photo = PhotoImage(file = "Logo_Image.png")
root.iconphoto(False, photo)
def save_post():
emailE = email_in.get()
file1 = open ("user.txt", "w")
file1.write(emailE)
file1.close()
passE = pass_in.get()
file2 = open ('pass.txt', 'w')
file2.write(passE)
file2.close()
entry1_text = Label(text = "Email * ",)
entry2_text = Label(text = "Password * ",)
entry1_text.place(x = 15, y = 70)
entry2_text.place(x = 15, y = 130)
email_in = StringVar()
pass_in = StringVar()
email_entry = Entry(textvariable = email_in, width = "30")
pass_entry = Entry(textvariable = pass_in, width = "30")
def app():
os.system(".\Auto_Post_With_Photo.exe")
def everything():
save_post()
app()
register = Button(root,text = "Post", width = "10", height = "2", command = everything, bg = "lightblue")
register.place(x = 15, y = 380)
root.mainloop()
I'm hoping I don't need to show the last program to get an answer to the issue. The Issue I'm having is that the program runs perfectly until the button is pressed, and then the hurls exes crash.
But if I click on the two hurl.exe with my mouse and not this 3rd program pressing the post button won't crash.
Any ideas to fix this issue? Also, it's not due to the 'exit()s', it does the same thing with or without them. :)

Python tkinter maintaining gui and reading from pipe

I am trying to achieve reading from subprocess pipe stdout and stderr and updating GUI simultaneously. However my code is waiting all pipe reading process then updates all.
import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename
import subprocess
import threading
import time
from queue import *
class Application:
# load main window of application
def __init__(self, master):
self.current_script_file_name = None
self.q = Queue()
self.window = master
self.window.title("TK")
self.window.rowconfigure(1, minsize = 600, weight = 2)
self.window.columnconfigure(1, minsize = 600, weight= 2)
# create frame for buttons and create buttons
self.frame_buttons = tk.Frame(master = self.window, relief = tk.RAISED, bd = 2)
self.button_save = tk.Button(master = self.frame_buttons, text = "Save", command = self.save_script_to_file)
self.button_run = tk.Button(master = self.frame_buttons, text = "Run", command = self.run_script_from_file)
# create frame for tk.Text editor and output
self.frame_text = tk.Frame(master = self.window, relief = tk.RAISED, bd = 2)
self.text_editor = tk.Text(self.frame_text)
self.text_output = tk.Text(self.frame_text, background = "Black", foreground = "White")
#adjust buttons
self.button_save.grid(row = 0, column = 0, sticky = "ew", padx = 5, pady = 5)
self.button_run.grid(row = 1, column = 0, sticky = "ew", padx = 5)
self.frame_buttons.grid(row = 0, column = 0, sticky = "ns")
#adjust text editor and text output
self.text_editor.grid(row = 0, column = 0, sticky = "ew", padx = 10, pady = 10)
self.text_output.grid(row = 1, column = 0, sticky = "ew", padx = 5, pady = 5)
self.frame_text.grid(row = 0, column = 1, sticky = "ns")
self.text_output.insert(tk.END, 'Script Result:\n')
def run(self):
self.window.mainloop()
def save_script_to_file(self):
file_path = asksaveasfilename(
filetypes=[("Python Scripts", "*.py"), ("Kotlin Scripts", "*.kts*")]
)
if not file_path:
return
with open(file_path, "w") as output_file:
text = self.text_editor.get(1.0, tk.END)
output_file.write("#!/usr/bin/env python3\n")
output_file.write(text)
self.window.title(f"Text Editor Application - {file_path}")
def run_script_from_file(self):
# start thread so main window not going to freeze
threading.Thread(target=self.run_script).start()
self.update()
def run_script(self):
sub_proc = subprocess.Popen(['python','script.py'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
threading.Thread(target=self.pipe_reader, args=[sub_proc.stdout]).start()
threading.Thread(target=self.pipe_reader, args=[sub_proc.stderr]).start()
def update(self):
while not self.q.empty():
for source, line in iter(self.q.get, None):
self.text_output.insert(tk.END,line)
self.window.after(1000,self.update)
def pipe_reader(self, pipe):
try:
with pipe:
for line in iter(pipe.readline, b''):
self.q.put((pipe, line))
finally:
self.q.put(None)
if __name__ == '__main__':
root = tk.Tk()
app = Application(root)
app.run()
run_script_from_file is a button command. And self.q is a Queue belongs to same class of this functions.
Why my text_output tk.Text field is not updating asap
Script.py :
#!/usr/bin/env python3
import time
counter = 1
while counter < 6:
print ("The current counter value: %d" % counter)
counter = counter + 1
time.sleep(1)
print(asd)
Edit: I put all my code
Edit: Added script.py
Ok, so this is actually not too far off. One common gotcha, due to buffering you have to run python in -u mode. Only other thing really is to have the tkinter update loop running all the time. Try this:
import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename
import subprocess
import threading
import time
from queue import *
class Application:
# load main window of application
def __init__(self, master):
self.current_script_file_name = None
self.q = Queue()
self.window = master
self.window.title("TK")
self.window.rowconfigure(1, minsize = 600, weight = 2)
self.window.columnconfigure(1, minsize = 600, weight= 2)
# create frame for buttons and create buttons
self.frame_buttons = tk.Frame(master = self.window, relief = tk.RAISED, bd = 2)
self.button_save = tk.Button(master = self.frame_buttons, text = "Save", command = self.save_script_to_file)
self.button_run = tk.Button(master = self.frame_buttons, text = "Run", command = self.run_script_from_file)
# create frame for tk.Text editor and output
self.frame_text = tk.Frame(master = self.window, relief = tk.RAISED, bd = 2)
self.text_editor = tk.Text(self.frame_text)
self.text_output = tk.Text(self.frame_text, background = "Black", foreground = "White")
#adjust buttons
self.button_save.grid(row = 0, column = 0, sticky = "ew", padx = 5, pady = 5)
self.button_run.grid(row = 1, column = 0, sticky = "ew", padx = 5)
self.frame_buttons.grid(row = 0, column = 0, sticky = "ns")
#adjust text editor and text output
self.text_editor.grid(row = 0, column = 0, sticky = "ew", padx = 10, pady = 10)
self.text_output.grid(row = 1, column = 0, sticky = "ew", padx = 5, pady = 5)
self.frame_text.grid(row = 0, column = 1, sticky = "ns")
self.text_output.insert(tk.END, 'Script Result:\n')
self.update()
def save_script_to_file(self):
file_path = asksaveasfilename(
filetypes=[("Python Scripts", "*.py"), ("Kotlin Scripts", "*.kts*")]
)
if not file_path:
return
with open(file_path, "w") as output_file:
text = self.text_editor.get(1.0, tk.END)
output_file.write("#!/usr/bin/env python3\n")
output_file.write(text)
self.window.title(f"Text Editor Application - {file_path}")
def run_script_from_file(self):
sub_proc = subprocess.Popen(['python3', '-u','script.py'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
threading.Thread(target=self.pipe_reader, args=[sub_proc.stdout]).start()
threading.Thread(target=self.pipe_reader, args=[sub_proc.stderr]).start()
def update(self):
while not self.q.empty():
source, line = self.q.get()
if line is None:
line = "DONE"
self.text_output.insert(tk.END,line)
self.window.after(100, self.update)
def pipe_reader(self, pipe):
for line in iter(pipe.readline, b''):
self.q.put((pipe, line))
self.q.put((pipe, None))
if __name__ == '__main__':
root = tk.Tk()
app = Application(root)
root.mainloop()

Issue with crash in TKinter Application

I have a program running that is having issues when the timer runs. Every time "start" is hit, the application crashes. Any thoughts?
##-- Imports --##
import time
import openpyxl as xl
from Tkinter import *
##-- Classes --##
class App(Frame):
def startTimer(self):
self.check = True
self.now = time.strftime("%H:%M:%S")
while self.check == True:
self.timer.configure(text = self.now)
time.sleep(1)
def initUI(self):
self.parent.title("Emma's Time Manager")
self.pack(fill = BOTH, expand = 1)
def initWidget(self):
##Create button definitions##
self.buttonwidth = 12
self.quit = Button(self, text = "Quit", comman = self.quit, width = self.buttonwidth)
self.newClient = Button(self, text = "Add Client", command = lambda:self.newClientFunc(), width = self.buttonwidth)
self.timeStart = Button(self, text = "Start", command = lambda:self.startTimer(), width = self.buttonwidth)
self.timeEnd = Button(self, text = "End", command = lambda:self.endTimer(), width = self.buttonwidth)
self.saveBut = Button(self, text = "Save", command = lambda:self.saveFunc(), width = self.buttonwidth)
self.viewClient = Button(self, text = "View Client", command = lambda:self.viewCliFunc(), width = self.buttonwidth)
##Create lable definitions##
self.timer = Label(self, text = "00:00:00") ##self.timer used as display for timer##
##Create the listbox for Client Selection##
self.wb = xl.load_workbook("clients.xlsx")
self.clientNames = self.wb.get_sheet_names()
self.clivar = StringVar(self)
self.clivar.set(self.clientNames[0])
self.clilist = apply(OptionMenu, (self, self.clivar) + tuple(self.clientNames))
##Create Entry Box to describe work information##
self.info = Entry(self, width = 50)
##Create GUI for widgets##
self.clilist.grid(row = 0, column = 0)
self.timer.grid(row = 0, column = 1)
self.timeStart.grid(row = 0, column = 2)
self.timeEnd.grid(row = 0, column = 3)
self.info.grid(row = 1, column = 0, columnspan = 4)
self.newClient.grid(row = 2, column = 0)
self.viewClient.grid(row = 2, column = 1)
self.saveBut.grid(row = 2, column = 2)
self.quit.grid(row = 2, column = 3)
def __init__(self, parent):
Frame.__init__(self, parent, background = "light blue")
self.parent = parent
self.initUI()
self.initWidget()
def main():
try:
xl.load_workbook("clients.xlsx")
except:
temp = xl.Workbook()
temp.save("clients.xlsx")
temp.remove_sheet(temp.get_sheet_by_name("Sheet"))
root = Tk()
bob = App(root)
root.mainloop()
main()
Please note that most of the program is not yet finished. I just cannot seem to get this timer to run properly.
Looks like you have no way out of your while loop. You'll either need to set self.check to False, or break out of the loop.
while self.check == True:
self.timer.configure(text = self.now)
time.sleep(1)

Refering to Labels Python, Tkinter

I'd like to refer to labels in def check(self) . It should check if feedback from external device equals to something, but I don't know how to refer to label and change colour of it if it's equal or not. I'd like to change for example lab3 background to green or red, depending on equality. Here is my code:
# -*- coding: utf-8 -*-
import Tkinter as T, tkFileDialog
import os
from time import *
import serial
from ttk import Button, Label, Frame, Entry, Style
class Program(Frame):
def __init__(self, root):
Frame.__init__(self, root)
self.root = root
self.initUI()
def initUI(self):
self.root.title('OptoMaQ')
Style().configure('TFrame', background = '#6666ff')
Style().configure('TButton',background = '#6666ff')
lab1 = Label(self, text = 'Press Save to save a file', background = '#6666ff').grid(row = 0, columnspan = 5)
but1 = Button(self, text='Save', command=self.save).grid(row = 2,column = 1)
lab2 = Label(self, text = 'Press Exit to quite', background = '#6666ff').grid(row = 1, columnspan = 5)
but2 = Button(self, text = 'Exit',command = self.exit).grid(row = 2, column = 2)
lab3 = Label(self, text = 'Spectra-Hub', background = '#6666ff').grid(row = 3, columnspan = 5)
lab4 = Label(self, text = 'SpectraPro VM-504',background = '#6666ff').grid(row = 4,columnspan = 5)
lab5 = Label(self, text = 'SpectraPro SP-2-300i',background = '#6666ff').grid(row = 5, columnspan = 5)
but3 = Button(self, text = 'Check',command = self.check).grid(row = 6, columnspan = 5)
lab6 = Label(self, text = 'Type sth here', background = '#6666ff').grid(row = 7,columnspan = 5)
self.entry = Entry(self, justify = 'center',text = '1')
self.entry.grid(row = 8, columnspan =3)
self.fileop = options = {}
options['filetypes'] = [('all files', '.*'),('dat files','.dat'),('text files', '.txt')]
options['initialfile'] = 'file.txt'
options['parent'] = root
def check(self):
port = serial.Serial(15)
command = 'WHO'
port.write(command + '\r')
out = port.read(50)
if out == 'Acton Research Corp. \nSpectra-Hub':
lab3 = Label(self, text = 'Spectra-Hub', background = '#6666ff').grid(row = 3, columnspan = 5)
lab3.config(background = 'green')
port.close()
else:
lab3 = Label(self, text = 'Spectra-Hub', background = '#6666ff').grid(row = 3, columnspan = 5)
lab3.config(background = 'red')
port.close()
port2 = serial.Serial(16)
port2.write(command +'\r')
out2 = port2.read(50)
if out2 == 'Acton Research Corp. \nSpectraPro VM-504':
port2.close()
else:
port2.close()
port3 = serial.Serial(17)
port3.write(command + '\r')
out3 = port3.read(46)
if out3 == 'Acton Research Corp. \n SpectraPro SP-2-300i':
port3.close()
else:
port3.close()
def save(self):
filename = tkFileDialog.asksaveasfilename(**self.fileop)
if filename:
file = open(filename, 'a+')
time = strftime("%A, %d %b %Y, %H:%M:%S ", gmtime())
print time
file.write(time)
file.write('\n')
input = str(self.entry.get())
file.write(input)
file.close()
def exit(self):
root.destroy()
if __name__=='__main__':
root = T.Tk()
Program(root).pack()
root.mainloop()
I've tried something like this in lines 46-53 but it doesn't work. It shows that 'NoneType' object has no attribute 'config' in line 52. Any ideas? It's really important to me please help :)
That is because your labels are only defined in the scope of def initUI(self): and therefore inaccessible to def check(self)
Try defining your buttons as self.lab1 instead of lab1 and also refer to them in the same way.

Categories