I have made a Simple GUI that launches when i run my Twitch TV IRC Bot. But, the main bot doesn't continue until after i close the GUI. How would i make it so the Script runs at the same time as the GUI?
This is the GUI:
##--GUI--##
def whitelist_wipe():
execfile('command_whitelist_wipe.py')
def modpack():
modpack = modpack_input.get()
return
root = Tk()
modpack_input = StringVar()
root.title('Geekster_Bot')
root.geometry('450x450+500+300')
WhitelistButton = Button(root, text = 'Clear Whitelist!', command + whitelist_wipe).pack()
SubmitButton = Button(root, text = 'Change Modpack', command = modpack).pack()
ModpackName = Entry(root, textvariable=modpack_input).pack()
root.mainloop()
This is the part where it launches the GUI from the main Bot scrpit:
try:
execfile('GUI.py')
except:
print('Error loading GUI')
How would i continue the code with the GUI open?
EDIT
GUI.py;
##--GUI--##
def whitelist_wipe():
execfile('command_whitelist_wipe.py')
def modpack_var():
modpack_input = modpack_user.get()
root = Tk()
modpack_user = StringVar()
root.title('Geekster_Bot')
root.geometry('350x100+500+300')
Label1 = Label(root, text = 'Geekster_Bot Controls!').pack()
WhitelistButton = Button(root, text = 'Clear Whitelist!', command =whitelist_wipe).pack(side = LEFT)
SubmitButton = Button(root, text = 'Change Modpack', command = modpack_var).pack()
ModpackName = Entry(root, textvariable=modpack_user).pack()
root.mainloop()
Main Bot;
try:
#Create thread
gui_thread = threading.Thread( target = execfile, args = ('GUI.py',) )
#Start thread
gui_thread.start()
#Code to run in the main thread
except:
print('Error loading GUI')
def message(msg): #function for sending messages to the IRC chat
global queue
queue = queue + 1
print queue
if queue < 20: #ensures does not send >20 msgs per 30 seconds.
twitch = ('OUTPUT ON ' + channel + ' :' + msg + '\r\n')
irc.send('PRIVMSG ' + channel + ' :' + msg + '\r\n')
print (twitch)
else:
print 'Message deleted'
def socialtimer(): #function for announcing social every 3 minutes
global ntimer
z = open(r'E:\Geekster_Bot\Twitter.txt')
SOCIAL = z.read()
message (SOCIAL)
print 'Social Timers Started!'
ntimer = threading.Timer(1200,socialtimer)
ntimer.start()
def queuetimer(): #function for resetting the queue every 30 seconds
global queue
print 'queue reset'
queue = 0
threading.Timer(30,queuetimer).start()
def modpack_var():
modpack_input = modpack_user.get()
##--Main Bot--##
#General variables
newsmsg = 'whitelist'
modpack = modpack_input
Since the gui itself runs in a loop it blocks the thread you start it in until you stop the loop (close the gui). You need to start the gui in a different thread from the main one.
You can do this using the threading module:
import threading
try:
#Create thread
gui_thread = threading.Thread( target = execfile, args = ('GUI.py',) )
#Start thread
gui_thread.start()
#Code to run in the main thread
except:
print('Error loading GUI')
In this code the gui_thread object is a thread, which runs the execfile callable (a function in this case) with the parameter 'GUI.py' on start.
Check the threading module documentation for further info: https://docs.python.org/3.3/library/threading.html
Related
so I am making a program on tkinter that gets a response from a server and depending on the answer, it will change the background color, to either green for success or red for error, the problem is that I realized that when running the code, the windows.after() method doesn't wait till is done to continue and when I do the request for the server, it have to do it three times to check if the response is correct, and it is suppossed to change the window background color each time, but it is only doing it one time. And not only the background color changing fails, also I want to change a label's text when it is doing the request,but it does it really quick and I'm not able to diferentiate the changes, so the question is: how can I
How can I make the program wait until one line finishes running to go to the next one and not everything happens at the same time and so fast?
Here is a piece of my code, I removed the request part because I'm trying to solve this problem first:
# import gpiozero
# import picamera
import json
import requests
import tkinter as tk
with open("config.json") as file:
config = json.load(file)
ENDPOINT = config["ENDPOINT"]
USUARIO = config["USUARIO"]
ESTACION = config["ESTACION"]
TIEMPO_ESPERA = config["TIEMPO_ESPERA"]
PIN_RELE = config["PIN_RELE"]
PATH_SALIDA = ENDPOINT + "Salida.getTicket/" + ESTACION + "/" + USUARIO + "/"
barcode = ""
# RELAY = gpiozero.OutputDevice(PIN_RELE, active_high=True, initial_value=False)
# CAMERA = picamera.PiCamera()
def check_scan_barcode(event=None):
info_label.config(text = "Wait...")
barcode = barcode_entry.get()
barcode_entry.delete(0, "end")
for i in range(3):
response = get_request(ENDPOINT + barcode)
if response["data"] == "True":
success()
open_barrier()
else:
error()
info_label.config(text = "Scan barcode")
def get_request(url):
response = requests.get(url)
response.raise_for_status()
response = response.json()
return response
def normal():
window.configure(bg="white")
info_label.configure(bg="white")
def success():
window.configure(bg="green")
info_label.configure(bg="green")
window.after(1000, normal)
def error():
window.configure(bg="red")
info_label.configure(bg="red")
window.after(1000, normal)
def open_barrier(barcode):
# CAMERA.capture(f"/home/pi/Pictures{barcode}.jpg")
# RELAY.on()
# window.after(TIEMPO_ESPERA, RELAY.off)
pass
window = tk.Tk()
# window.attributes('-fullscreen', True)
info_label = tk.Label(window, text= "Scan barcode.", font=("Arial", 40))
info_label.pack()
barcode_entry = tk.Entry(window, width=50)
barcode_entry.bind('<Return>', check_scan_barcode)
barcode_entry.pack(expand=True)
barcode_entry.focus()
window.mainloop()
I want to print a message on the UI when the user wishes to exit.
This is a part of code relevant to it
if word in quit_words:
user_to_quit = True
Print = "Pleasure serving you!"
print_bot_reply(Print)
time.sleep(5)
root.destroy()
The print bot_reply function is as follows:
def print_bot_reply(response):
response = "\nKalpana: " + str(response)
label = Label(frame,text = response,bg="#b6efb1", borderwidth=5, relief="raised")
label.pack(anchor = "w")
The window is closing after 5 seconds, as desired but not displaying the message.
Please point me the mistake or suggest some other method to do this
Thanks!
I'm creating a Tkinter GUI application using Python and one of the function in this application is pinging different IP addresses. I'm trying to show an undeterminate progress bar during the pinging process but I can't seem to make it work. Here is what I have tried:
def pingSwitches(ipDictionary):
validIPDictionary = {}
switchCounter = 1
popup = tk.Tk()
popup.wm_title("Processing...")
progress = ttk.Progressbar(popup, orient="horizontal", length=len(ipDictionary.keys()), mode="determinate")
progress.pack()
progress.start(50)
popup.mainloop()
for name, ip in ipDictionary.items():
#progress.step(1)
response = subprocess.Popen(["ping", "-n", "1", ip],stdout = subprocess.PIPE).communicate()[0]
if((b"unreachable" in response) or (b"timed out" in response) or (b"demande" in response)):
print(ip + " is down")
else:
validIPDictionary[name] = ip
print(ip + " is up")
print("Pinged " + str(switchCounter) + " of " + str(len(ipDictionary.keys())) + " total ips")
switchCounter = switchCounter + 1
progress.stop()
popup.destroy()
return validIPDictionary
The problem is when I run the program, I can see that the code stops at the popup.mainloop() line and it does not continue. If I put the popup.mainloop() after the pinging process, the popup appears after the pinging is done, rendering it useless.
How can I make the popup appear while my code is pinging? Is it only by multithreading?
I am writing a program in which I want to send data to socket after every 30 seconds.
import socket
from Tkinter import *
import tkMessageBox
#from threading import *
import thread
_connect = False
u_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def conn(IP,PORT):
try:
print 'start'
u_sock.connect((IP, PORT))
print 'success'
_connect = True
except socket.error, (value,message):
if u_sock:
print 'fail'
u_sock.close()
return
def connFunction():
IP = IP_entry.get()
if len(IP) < 7:
tkMessageBox.showinfo("Error", "Invalid IP Address")
return
PORT = int(PORT_entry.get())
print IP , PORT
thread.start_new_thread(conn,(IP, PORT, ))
def SEND():
print 'Send'
if(_connect == True):
print 'sending...'
Inv = 'DATA'
u_sock.send(Inv.decode('hex'))
data = u_sock.recv(4096)
d = data.encode('hex').upper()
print 'Received', repr(d)
GUI = Tk()
GUI.title('RFID')
#GUI.geometry("365x280")
GUI.wm_iconbitmap('RFID.ico')
GUI.columnconfigure(8, pad=3)
GUI.rowconfigure(8, pad=3)
IP_label = Label(GUI,text = "IP Address: ",borderwidth=5)
IP_label.grid(column=0, row=1, sticky=W)
IP_entry = Entry(GUI,width=15,borderwidth=3)
IP_entry.grid(column=3,row=1,sticky=E)
PORT_label = Label(GUI,text = "Port: ",borderwidth=5)
PORT_label.grid(column=8, row=1, sticky=E)
PORT_entry = Entry(GUI,width=6,borderwidth=3)
PORT_entry.grid(column=9,row=1,sticky=E)
Conn_button= Button(GUI,text="Connect",command=connFunction,borderwidth=1,height=1,width=12)
Conn_button.grid(column=16,row=1,padx=10,pady=5,sticky=(W,E))
#GUI.after(1000,SEND)
GUI.mainloop()
I need to call send function after every 30 seconds or how to create the event which is automatically called after every 30 seconds . I try to do this GUI.after(1000,SEND) but it does not works for me. it calls the SEND function only first time...
Kindly Help me out with an example. Thanks
Assuming that SEND takes less than a few hundred milliseconds, remove the threading code and use after. The key is to call after inside the SEND function so that it auto-repeats.
def SEND():
print 'Send'
...
GUI.after(30000, SEND)
...
GUI = Tk()
...
SEND()
GUI.mainloop()
I am doing a simulation of a print server in python, files are sent using sockets to a server which has to be placed in a printer queue. When the client initiates communication with the server must provide an ID (user) and PASSWORD, which will be checked against a list on the server can be verified in a file "passwordlist.txt" which has the following format:
akira Aaron
alazrea Ababa
alexander Abbott
andy Abe
andycapp Abel
anxieties Abelian
anxiety Abelson
bailey Aberdeen
batman robin
bd Abidjan
Both programs must have a graphical interface on the display:
* Client: user field, password, file to send to print and disconnect from the server.
* Server: A list of files that are queued for printing
On the server should be displayed a list of files that have been properly sent to the queue for printing.
For this I decided to use a "text area" but I have a problem, only shows me the first file in the command to print text area, when the client terminates the connection and if another client tries to connect to the server just crash the program does and does absolutely nothing. What am I doing wrong? I think the problem is that i'm putting part of the instruction code "root.mainloop ()", i have this doubt. how can resolve this failure? im stuck With This..thanks to all
Here's the Client Code:
#! /python26/python.exe
#! -*- coding: utf-8 -*-
from Tkinter import *
import Tkinter, Tkconstants, tkFileDialog
import Tkinter
import sys
import socket
import tkMessageBox
flag = False
class Exit_Button(Frame):
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.pack()
self.widget1()
def salir():
root.destroy()
def adjuntar_imprimir():
global flag
if (flag==False):
tkMessageBox.showinfo("Error", "You must login")
salir ()
else:
# get filename
filename = tkFileDialog.askopenfilename(**file_opt)
# open file on your own
if filename:
s.send (filename)
f= open(filename, 'rb')
l = f.read(1024)
while (l):
s.send(l)
l = f.read(512)
def iniciar_sesion():
global flag
#invoco el metodo connect del socket pasando como parametro la tupla IP , puerto
login = value.get()
password = value_2.get()
if ((len(login) == 0) or (len(password)) == 0):
tkMessageBox.showinfo("Error", "insert correct login and password")
salir ()
else:
s.send(login)
s.send(password)
recibido = s.recv(1024)
tkMessageBox.showinfo("Notify", recibido)
if (recibido=="Error Check user & Password"):
salir ()
else:
flag = True
####--------------------------------------------------------------------------------####
root = Tk()
s = socket.socket()
s.connect(("localhost", 9999))
# define options for opening or saving a file
file_opt = options = {}
options['defaultextension'] = '' # couldn't figure out how this works
options['filetypes'] = [('all files', '.*'), ('text files', '.txt')]
options['initialdir'] = 'C:\\'
options['initialfile'] = 'myfile.txt'
options['parent'] = root
options['title'] = 'This is a title'
frame = Frame(root)
frame.pack(side=LEFT)
frame.master.title("Servicio de impresion")
value = StringVar()
value_2 = StringVar()
w = Label(root, text="User Name", fg="red")
w.pack(side = LEFT)
entry_1 = Entry(root, textvariable=value_2, bd =5, show="*")
entry_1.pack(side = RIGHT)
z= Label(root, text="Password", fg="red")
z.pack(side = RIGHT)
entry_0 = Entry(root, textvariable=value, bd =5)
entry_0.pack(side = RIGHT)
##---------------login----------------
button_0= Button (frame, text = "login", command= iniciar_sesion, bg='black', foreground ="red")
button_0.pack()
##--------------Attach and print File------------
button_3 = Button (frame, text= "print", command=adjuntar_imprimir, bg='black',foreground ="red")
button_3.pack(side=LEFT)
##-----------------Exit------------------------
button_1 = Button(frame, text= "exit", command=salir, bg='black', foreground ="red")
button_1.pack()
root.mainloop()
The Server Code:
from Tkinter import *
import Tkinter, Tkconstants, tkFileDialog
import Tkinter
import sys
import socket
import tkMessageBox
def onclick():
pass
root = Tk()
root.title("Print Server")
text = Text(root, width=60, height=30)
text.pack()
s = socket.socket()
s.bind(("localhost", 9999))
s.listen(100)
i=0
while (True):
sc, address = s.accept()
print "Connection from: ", address
recibido1 = sc.recv(1024)
recibido2 = sc.recv(1024)
print "login:", recibido1, "password:", recibido2
salida = (str(recibido1)+" "+str(recibido2)+"\n")
archivo = open("passwordlist.txt", "r")
while True:
linea = archivo.readline() #Leo del archivo
if (salida==linea):
log_ok ="login ok"
sc.send(log_ok)
break
if (len(linea))==0:
error= "Error Check user & Password"
sc.send(error)
break
f = open('print_'+ str(i)+".pdf",'wb') #abierto en escritura binaria
i=i+1
# recibimos y escribimos en el fichero
nombre_archivo = sc.recv(1024)
cadena = "On Impresion Queue.."+nombre_archivo+"\n"
text.insert(INSERT, cadena)
print "On impresion Queue.."+nombre_archivo
l = sc.recv(1024)
while (l):
f.write(l)
l = sc.recv(1024)
if not l:
notification= "Complete transfer"
sc.send(notification)
break
f.close()
sc.close()
root.mainloop()
s.close()
The program does not tell me any error just when another client tries to login, the client interface is doing nothing.
I don't know why it crashes, but I know why only one client can connect. Your server just isn't designed to handle multiple clients. When one client connects, all the server does is listen to that client - any other client trying to connect is simply ignored.
The solution is simple: Multithreading. Spawn a new thread for each connecting client, and let the "main" thread accept new connections.
The resulting "while(True)" loop should look somewhat like this:
from threading import Thread
tkinterThread= Thread(target=Tk.mainloop, args=[root])#spawn a new Thread object
tkinterThread.start()#make the thread execute the tkinter mainloop
#please note: I'm not sure if the two lines above actually work; I can't test them because Tkinter won't work for me.
def listenToClient(sc, address):
recibido1 = sc.recv(1024)
recibido2 = sc.recv(1024)
print "login:", recibido1, "password:", recibido2
salida = (str(recibido1)+" "+str(recibido2)+"\n")
archivo = open("passwordlist.txt", "r")
while True:
linea = archivo.readline() #Leo del archivo
if (salida==linea):
log_ok ="login ok"
sc.send(log_ok)
break
if (len(linea))==0:
error= "Error Check user & Password"
sc.send(error)
break
f = open('print_'+ str(i)+".pdf",'wb') #abierto en escritura binaria
i=i+1
# recibimos y escribimos en el fichero
nombre_archivo = sc.recv(1024)
cadena = "On Impresion Queue.."+nombre_archivo+"\n"
text.insert(INSERT, cadena)
print "On impresion Queue.."+nombre_archivo
l = sc.recv(1024)
while (l):
f.write(l)
l = sc.recv(1024)
if not l:
notification= "Complete transfer"
sc.send(notification)
break
f.close()
sc.close()
while (True):
sc, address = s.accept()
print "Connection from: ", address
clientThread= Thread(target=listenToClient, args=[sc,address])#spawn a new thread object
clientThread.start()#start the thread; it'll execute the "listenToClient" function, passing it "sc" and "address" as arguments
This code will (well, should) spawn a thread that takes care of the GUI, meanwhile it'll accept connection requests from clients and spawn a new thread for every client, which checks the client's username and password, and then keeps listening until the client disconnects.