How threads works in python - python

I'm trying to create app for controlling djitello basing on some tutorials and i want to create possibility to click on some gui tabs and during that control drone by keyboard.
So i thought about using threads but i can't write it. Right now when i use my app it freezes after clicking button which activates method for keyboard control. Can someone explain what am i doing wrong?
This is class for keyboardControl:
from Modules.KeyPressModule import GetKeyPressed as keyPressed
from time import sleep
import logging
class KeyboardControlService():
def __init__(self,passedTello):
self.tello = passedTello
self.startControl = False
def Initialize(self,ui):
self.ui = ui
def GetKeyboardInput(self):
lr,fb,ud,yv = 0,0,0,0
speed = 30
if(keyPressed("left")): lr = speed
elif (keyPressed("right")): lr = -speed
if(keyPressed("up")): fb = speed
elif (keyPressed("down")): fb = -speed
if(keyPressed("w")): ud = speed
elif (keyPressed("s")): ud = -speed
if(keyPressed("a")): yv = speed
elif (keyPressed("d")): yv = -speed
if(keyPressed("q")): self.tello.land()
elif (keyPressed("e")): self.tello.takeoff()
return [lr,fb,ud,yv]
def StartControl(self):
self.startControl = True
while self.startControl:
values = self.GetKeyboardInput()
print("test")
#self.tello.send_rc_control(values[0],values[1],values[2],values[3])
sleep(0.05)
def EndControl(self):
self.startControl = False
This class is for button clicking response:
from djitellopy import Tello
from threading import Thread
from Services.KeyboardControlService import KeyboardControlService as keyboardControlService
class TelloService():
def __init__(self):
self.tello = Tello()
self.keyboardControlService = keyboardControlService(self.tello)
def UseKeyboardControl(self,UseIt,UI):
if(UseIt == True):
self.keyboardControlService.Initialize(UI)
self.keyboardThread = Thread(target=self.keyboardControlService.StartControl(), daemon=True)
self.keyboardThread.start()
else:
self.keyboardControlService.EndControl()
self.keyboardThread.join()

Okey i resolved it
The trouble was here :
self.keyboardThread = Thread(target=self.keyboardControlService.StartControl(), daemon=True)
I passed function not the object

Related

How to thread two functions where one output effect the others actions

Here's my code:
import time
import keyboard #pip install keyboard - could use pynput listener instead.
from threading import Thread
hshtag = int(0)
done = False
fire = False
def StopStart(fire):
while not done:
global fire
if keyboard.is_pressed('#'):
hshtag = hshtag + 1
if hshtag % 2 ==0:
fire = False
else:
fire = True
return fire
def NormalFire():
while not done:
global fire
if fire == True:
#do x
else:
pass
t1 = Thread(target = StopStart)
t2 = Thread(target = NormalFire(fire))
t1.start()
t2.start()
The problem is function StopStart (should) effect what function Normalfire does but as the function only accepts a value for fire when it starts running (so it doesn't work). What I want is change what function normalfire does with function stopstart. and if you're wondering why I am using threading it because '#do x' actually takes a while to work so as one continuous script if I clicked hash at the wrong time it wouldn't stop. Maybe I could do this with classes instead but im not good with classes so if someone could either help with that or fix the above code that would be great thanks.
New attempt at explaining what's wrong with the top code - Ok, so both functions should be running simultaneously (which they are) - so no problems there. but as the function StopStart changes the boolean fire to true/false I want that to cause my NormalFire function to change what it is doing - nothing when I haven't clicked hash yet and something if I've clicked hash once but if I then click hash while its running it will finish whats its running then do nothing waiting for hash to be clicked again.
Sorry, my question wasn't clear take this code as a simplification of my core question.
##imports
import time
import keyboard #pip install keyboard - could use pynput listener instead.
from threading import Thread
##variable assigning
hshtag = int(0)
done = False
fire = False
def x():
while not done:
fire = True
return fire
def y(fire):
while not done:
if fire:
print('ok')
else:
pass
t1 = Thread(target = x)
t2 = Thread(target = y(fire))
t1.start()
t2.start()
Currently, the above code outputs nothing even though I've set 'fire = true' in function x and returned it how would I edit this code so that when boolean fire changes to true the function y starts printing ok?
Editing like Nair suggested also returns nothing and after 15 second the program stops running edited code:
##imports
import time
import keyboard #pip install keyboard - could use pynput listener instead.
from threading import Thread
##variable assigning
hshtag = int(0)
done = False
fire = False
def StopStart():
while not done:
fire = True
return fire
def NormalFire():
while not done:
if fire:
print('ok')
else:
pass
t1 = Thread(target = StopStart)
t2 = Thread(target = NormalFire)
t1.start()
t2.start()
I'm unable to comment so I apologize in advanced. I'm having trouble understanding your question above, but I reworked your code - fix/add whatever you need and get back to me!
import time
import keyboard #pip install keyboard - could use pynput listener instead.
from threading import Thread
hshtag = int(0)
done = False
fire = False
def StopStart():
while not done:
# global fire - You're setting StopStart up for a param that needs passed, that also is named another variable
# So it will just over write it (Also, no arg is passed for StopStart(fire))
if keyboard.is_pressed('#'):
hshtag = hshtag + 1
if hshtag % 2 == 0 : fire = False
else : fire = true
return fire
def NormalFire():
while not done:
#global fire - Don't need to global it, you would've had to global done if that was the case
if fire: # don't need == true, just need if fire (if true)
print("x")
t1 = Thread(target=StopStart)
t2 = Thread(target=NormalFire)
t1.start()
t2.start()
Not sure that this is exactly what you're asking for. I would maybe listen for keyboard events outside of either thread. Instead, just bind keyboard events to a callback which set a threading.Event object. Sorry for the weird and slightly morbid example:
from pynput import keyboard
from threading import Thread, Event
plate_dropped = Event()
def on_press(key):
if key is keyboard.Key.enter:
plate_dropped.set()
listener = keyboard.Listener(on_press=on_press)
def poll_plate_status():
from time import sleep
from random import choice
messages = [
"It sure is tempting, eh?",
"Are you gonna do it?"
]
print("It'd be a shame if someone would drop this plate and scare grandpa!")
while not plate_dropped.is_set():
print(choice(messages))
sleep(0.5)
print("The plate has been dropped!")
def poll_grandpa_status():
from time import sleep
from random import choice
messages = [
"*zzzZZZzzz*",
"*Snoooreee*"
]
print("Grandpa is sound asleep.")
while not plate_dropped.is_set():
print(choice(messages))
sleep(0.5)
print("HUH!?")
plate_thread = Thread(target=poll_plate_status, daemon=True)
grandpa_thread = Thread(target=poll_grandpa_status, daemon=True)
plate_thread.start()
grandpa_thread.start()
listener.start()
##imports
import time
import keyboard #pip install keyboard - could use pynput listener instead.
from threading import Thread
##variable assigning
hshtag = int(0)
done = False
fire = False
def StopStart(self, interval=1):
hshtag = 0
self.interval = interval
while not done:
if keyboard.is_pressed('#'):
hshtag = hshtag + 1
if hshtag % 2 ==0:
fire = False
else:
fire = True
def NormalFire():
while not done:
print('NormalFire Runs')
time.sleep(1)
if fire:
print('*fires*')
else:
print('*does nothing*')
#t1 = Thread(target = StopStart, daemon=True)
t2 = Thread(target = NormalFire, daemon=True)
#t1.start()
t2.start()
while not done:
#time.sleep()
if keyboard.is_pressed('#'):
hshtag = hshtag + 1
time.sleep(0.1)
if hshtag % 2 ==0:
fire = False
print(fire)
else:
fire = True
print(fire)
I realised my problem was my ides of threading (im new to it) this achieves what I wanted thanks for all the help.

How can I properly call a method from its callback method within a class?

I Have a code with two functions. Function 'send_thread' and Function 'receive_thread' which is the callback of 'send_thread'. What I want to do is to run 'send_thread', this activates 'receive_thread' and once it's over repeat it all again. To do so, I have come up with the code below. This is not giving the desired results, since the 'send_thread' gets called again but doesn't activate the callback anymore. Thank you in advance for your help.
I have noticed, that the function gets called at the end of the receive_thread and runs for the amount of time that I wait in the send_thread (rospy.sleep()). I does never activate the callback again after the first try though.
import rospy
import pepper_2d_simulator
import threading
class TROS(object):
def __init__(self):
self.cmd_vel_pub = rospy.Publisher('cmd_vel',Twist)
self.event = threading.Event()
def send_thread(self):
#send commmand
self.event.set()
sequence = [[1,0,0.05],[0,0,0],[0,0,0.1292]]
for cmd in sequence:
rospy.Rate(0.5).sleep()
msg = Twist()
msg.linear.x = cmd[0]
msg.linear.y = cmd[1]
msg.angular.z = cmd[2]
t = rospy.get_rostime()
self.cmd_vel_pub.publish(msg)
self.event.clear()
rospy.sleep(1)
def receive_thread(self,msg):
#if something is being send, listen to this
if self.event.isSet():
frame_id = msg.header.frame_id
self.x_odom = msg.pose.pose.position.x
self.y_odom = msg.pose.pose.position.y
self.z_odom = msg.pose.pose.position.z
self.pos_odom = [self.x_odom,self.y_odom,self.z_odom,1]
self.ang_odom = msg.pose.pose.orientation.z
self.time = msg.header.stamp.secs + msg.header.stamp.nsecs
#some transformations here to get self.trans...
else:
#after self.event() is cleared, rename and run again
self.x_odom = self.trans_br_x
self.y_odom = self.trans_br_y
self.ang_odom = self.rot_br_ang
self.send_thread()
def init_node(self):
rospy.init_node('pepper_cmd_evaluator',anonymous = True)
rospy.Subscriber('odom',Odometry,self.receive_thread)
if __name__ == '__main__':
thinking = Thinking()
thinking.init_node()
thinking.send_thread()
The expected result is that I am able to loop this two function so that I call send_thread, this activates receive thread. Then send_thread stops, receive_thread stops and activates the send_thread again. I want to do this 10 times.
I have now figured out how to this. I will post my solution in case anyone else runs into a similar problem. The working solution I came up with is pretty simple. I created a self.flag variable and alternatively set it to True and False in the send_thread and callback respectively. The code:
import rospy
import pepper_2d_simulator
import threading
class TROS(object):
def __init__(self):
self.cmd_vel_pub = rospy.Publisher('cmd_vel',Twist)
self.event = threading.Event()
self.count = 0
self.flag = True
def send_thread(self):
while self.count < 10:
if self.flag:
self.count = self.count + 1
#send commmand
self.event.set()
sequence = [[1,0,0.05],[0,0,0],[0,0,0.1292]]
for cmd in sequence:
rospy.Rate(0.5).sleep()
msg = Twist()
msg.linear.x = cmd[0]
msg.linear.y = cmd[1]
msg.angular.z = cmd[2]
t = rospy.get_rostime()
self.cmd_vel_pub.publish(msg)
self.event.clear()
rospy.sleep(0.3)
self.flag = False
rospy.signal_shutdown('Command finished')
def receive_thread(self,msg):
#if something is being send, listen to this
if self.event.isSet():
frame_id = msg.header.frame_id
self.x_odom = msg.pose.pose.position.x
self.y_odom = msg.pose.pose.position.y
self.z_odom = msg.pose.pose.position.z
self.pos_odom = [self.x_odom,self.y_odom,self.z_odom,1]
self.ang_odom = msg.pose.pose.orientation.z
self.time = msg.header.stamp.secs + msg.header.stamp.nsecs
#some transformations here to get self.trans...
else:
#after self.event() is cleared, rename and run again
self.x_odom = self.trans_br_x
self.y_odom = self.trans_br_y
self.ang_odom = self.rot_br_ang
self.flag = True
def init_node(self):
rospy.init_node('pepper_cmd_evaluator',anonymous = True)
rospy.Subscriber('odom',Odometry,self.receive_thread)
if __name__ == '__main__':
thinking = Thinking()
thinking.init_node()
thinking.send_thread()

Run multiple function in python

I am writing a program for Raspberry Pi that is utilizing multiple function in classes. I have one class that is dedicated to determining when a capacitive touch sensor is clicked and another one class dedicated to determining the weight from HX711 chip. I want to automatize all: when click the capacitive sensor the cell start the weight scale and then, when I click the capacitive sensor for the second times the system call the function cleanAndExit() but I don't know how I can do this stuff.
import time
import sys
import RPi.GPIO as GPIO
from hx711 import HX711
GPIO.setmode(GPIO.BCM)
padPin = 21
GPIO.setup(padPin, GPIO.IN)
class WeightScale:
def cleanAndExit(self):
print "Clean GPIO..."
GPIO.cleanup()
print "Complete!"
sys.exit()
def cliccato(self):
hx = HX711(5, 6)
hx.set_reading_format("LSB", "MSB")
hx.reset()
hx.tare()
hx.set_reference_unit(-421)
while True:
time.sleep(0.1)
n = 100
//Run for max 100 seconds and create an array with the last value from weight scale sensor
for i in range (1, n):
val = max(0, int (hx.get_weight(5)))
add = []
hx.power_down()
hx.power_up()
time.sleep(0.6)
add.append(val)
add1 = []
add1.append(add[-1:])
print add1
time.sleep(1)
class TouchSensor:
def click(self):
alreadyPressed = False
while True:
padPressed = GPIO.input(padPin)
if padPressed and not alreadyPressed:
print "click"
time.sleep(2)
c=WeightScale()
t=TouchSensor()
In order you to correctly create a class, you need to define an init method with in the class definition. So for example:
class TouchSensor:
def __init__(self):
self.padPin = 21
def click(self):
alreadyPressed = False
while True:
padPressed = GPIO.input(padPin)
if padPressed and not alreadyPressed:
print "click"
time.sleep(2)
Then once you create your object of that class, it is initialized with padPin = 21. Then you use the methods within each class to perform what you're calling 'functions.'
t = TouchSensor()
t.click()
Try making adjustments and post whatever errors you end up with!
I make some adjustments to my code:
import time
import sys
from multiprocessing import Process
import RPi.GPIO as GPIO
from hx711 import HX711
GPIO.setmode(GPIO.BCM)
padPin = 21
GPIO.setup(padPin, GPIO.IN)
class WeightScale:
def cleanAndExit(self):
print ("Clean GPIO...")
GPIO.cleanup()
print ("Complete!")
sys.exit()
def pesatura(self):
hx = HX711(5, 6)
hx.set_reading_format("LSB", "MSB")
hx.reset()
hx.tare()
hx.set_reference_unit(-421)
while t.status==True:
time.sleep(0.1)
n = 100
for i in range (1, n):
val = max(0, int (hx.get_weight(5)))
add = []
hx.power_down()
hx.power_up()
time.sleep(0.6)
add.append(val)
add1 = []
add1.append(add[-1:])
print (add1)
time.sleep(1)
cleanAndExit()
class TouchSensor:
def __init__(self):
self.status = False
def changeStatus(self):
if self.status == False:
self.status = True
print (self.status)
else:
self.status = False
print (self.status)
def click(self):
while True:
padPressed = GPIO.input(padPin)
if padPressed:
print ("click")
t.changeStatus()
alreadyPressed = padPressed
time.sleep(0.5)
c=WeightScale()
t = TouchSensor()
if __name__ == '__main__':
p1 = Process (target = t.click())
p1.start()
p2 = Process (target = c.pesatura())
p2.start()
I have added a multiprocessing function and method changeStatus for the button click,I want to use it to start the loop of pesatura(self) when self.status==True and after, when self.Status== False (another click) start cleanAndExit(). But when I start the script it gives me the error ''cleanAndExit() takes exactly 1 argument (0 given)''.

How to pause a thread (python)

The context:
I'm building a Graphical Interface with Qt creator and the "behaviour" file in python. A test version of my GUI is:
The expected behaviour:
I am running 2 different threads which are referred to the same function with different input arguments. With the SELECTOR button I can assign the value of 1 or 2 to a variable (and display it)
The button Start thread enables the correct thread to start (the first time).
The loop should be turned off by the stop button by modifying the global running variable.
This is my code
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui, uic
import sys
import threading
import time
import Queue
running = False
first_thread = None
second_thread = None
form_class = uic.loadUiType("simple2.ui")[0]
q = Queue.Queue()
select = 0
def action(string, queue): #function called by threads
global running
while(running):
phrase = string
if queue.qsize() < 10:
queue.put(phrase)
#else:
# print queue.qsize()
class MyWindowClass(QtGui.QMainWindow, form_class):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
#buttons
self.startButton.clicked.connect(self.start_clicked)
self.stopButton.clicked.connect(self.stop_clicked)
self.selector.clicked.connect(self.sel_click)
#variables
self.first = False
self.second = False
#queue
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.update_phrase)
self.timer.start(1)
def start_clicked(self): #start button callback
global select
if select > 0:
global running
running = True
print "started"
if (not self.first) & (select == 1):
first_thread.start()
self.first = True
if (not self.second) & (select == 2):
second_thread.start()
self.second = True
self.startButton.setEnabled(False)
self.startButton.setText('Starting...')
def stop_clicked(self): #stop button callback
global running
running = False
print "stopped"
self.startButton.setEnabled(True)
self.startButton.setText('Start Thread')
def sel_click(self): #selector button callback
global select
if select < 2:
select = select + 1
else:
select = 1
self.thread_counter.setText(str(select))
def update_phrase(self): #looping function
global running
if (not q.empty()) & running:
self.startButton.setText('Thread on')
abc = q.get()
print abc
def closeEvent(self, event):
global running
running = False
if __name__ == "__main__":
first_thread = threading.Thread(target=action, args = ("first", q))
second_thread = threading.Thread(target=action, args = ("second", q))
app = QtGui.QApplication(sys.argv)
w = MyWindowClass(None)
w.setWindowTitle('Multiple threads test in python')
w.show()
app.exec_()
For now, each thread should simple print on terminal their arguments ("First" or "Second").
If threads are started for the first time, my code works. But I would like to switch between threads infinite times.
Since threads cannot be stopped, is there a way to "pause" them?
I cannot find a solution, I hope someone will help me also with a piece of code. Thank you in advance
You can use Lock class to do that, a simple example would be:
import threading
lock = threading.Lock()
//here it will be lock
lock.acquire() # will block if lock is already held
...
then in other side do
//this will wake up
lock.release()
you can read more here http://effbot.org/zone/thread-synchronization.htm

Thread synchronization in GTK3+ and Python

I'm currently learning both Python and GTK 3+ and I've a problem when synchronizing threads. I'll try to be quick and clear:
I have to make a Social Network client. As the purpose is to learn how to create a GUI the "access to the social network API" will be simulated, but I have to "wait" for network responses with time.sleep(). Calling time.sleep() in the main thread freezes the GUI (it stops the execution of Gtk.Main()) so I have to make all my connections in a separate thread.
And here lies my problem. When I'm authenticating a user (verifying_credentials) I need to wait from that thread to finish to continue the execution of the main program. If I try a Thread.join GUI freezes. I've tried using queues, but queue.get is also blocking Gtk.main().
I've tried emitting a signal when my thread is finished , but the handler starts in the same thread, so when I try to modify the GUI (which I need) , program crashes (you're not supposed to touch the GUI from anywhere except main thread).
My solution ? I do busy-waiting / active-waiting , which is by definition an antipattern. I keep asking if the thread has finished and forcing cicles of Gtk.main()
There has to be another way, a more elegant / efficient way than mine.
I don't know if I can signal another thread, or there is a way of using queues without blocking the main thread. Any help will be very much appreciated.
The python code :
from os.path import abspath, dirname, join
import gettext
import threading
import math
import time
import random
import locale
from gi.repository import Gtk, Gdk, GLib, GObject
import list
APP = "UDC_Social_API"
user_list = {
"user": "password",
"admin": "admin",
"carnotan": "1234"
}
class UDC_Social_API:
def on_applicationwindow1_key_press_event(self, widget, event):
# keyname = Gdk.keyval_name(event.keyval)
# print (_("Key %(name)s (%(val)d) was pressed" )%{"name":keyname, "val":event.keyval})
if event.keyval == 65293:
self.on_login_button_clicked()
def delay(self):
if self.delay_option.get_active():
time.sleep(math.exp(random.random()*5))
else:
pass
def active_waiting(self):
while self.finished is False:
Gtk.main_iteration_do(False)
self.finished = False
self.z_handler(None)
def verify_credentials(self, user, password):
GLib.idle_add(self.active_waiting)
self.delay()
if user in user_list:
if password == user_list.get(user):
self.authentication = True
self.finished = True
else:
self.authentication = False
self.finished = True
else:
self.authentication = False
self.finished = True
def on_login_button_clicked(self, data=None):
user = self.user_entry.get_text()
password = self.password_entry.get_text()
thread = threading.Thread(target=self.verify_credentials, args=(user, password))
thread.daemon = True
thread.start()
def z_handler(self, data=None):
if self.authentication is False:
self.message_dialog.set_markup(_("User/Password incorrect\nPlease, verify login information"))
self.message_dialog.run()
self.message_dialog.hide()
return False
else:
self.window.hide()
print ("Success!")
def on_applicationwindow1_destroy(self, data=None):
Gtk.main_quit()
def on_gtk_about_activate(self, menuitem, data=None):
self.aboutdialog.run()
self.aboutdialog.hide()
def on_gtk_cut_activate(self, widget):
# Get the bounds of the selected text
bounds = self.focus.get_selection_bounds()
# if the bounds of the selection are not an empty tuple,
# put the selection in the variable chars
# and copy it to the clipboard
# (get_selection_bounds returns an empty tuple if there is no selection)
# then delete the selection
if bounds:
chars = self.focus.get_chars(*bounds)
self.clipboard.set_text(chars, -1)
self.focus.delete_text(bounds[0], bounds[1])
else:
pass
def on_gtk_copy_activate(self, widget):
# Get the bounds of the selected text
bounds = self.focus.get_selection_bounds()
# if the bounds of the selection are not an empty tuple,
# put the selection in the variable chars
# and copy it to the clipboard
# (get_selection_bounds returns an empty tuple if there is no selection)
if bounds:
chars = self.focus.get_chars(*bounds)
self.clipboard.set_text(chars, -1)
else:
pass
def on_gtk_paste_activate(self, widget):
# Get the text from the clipboard
text = self.clipboard.wait_for_text()
if text is not None:
# If there's text selected in the target
# delete it and paste the contents of the clipboard
bounds = self.focus.get_selection_bounds()
if bounds:
self.focus.delete_text(bounds[0], bounds[1])
self.focus.insert_text(text, bounds[0])
# else insert the text in the current position of the cursor in the target
else:
pos = self.focus.get_position()
self.focus.insert_text(text, pos)
else:
pass
def on_entry_focus(self, widget, event):
self.focus = widget
def create_menubar(self):
self.file_menu=self.builder.get_object("menuitem1")
self.edit_menu=self.builder.get_object("menuitem2")
self.options_menu=self.builder.get_object("option")
self.help_menu=self.builder.get_object("menuitem4")
self.languages_menu=self.builder.get_object("menuitem3")
self.delay_option = self.builder.get_object("delay_option")
self.gtk_quit_menu=self.builder.get_object("gtk_quit_menu")
self.gtk_cut_menu=self.builder.get_object("gtk_cut_menu")
self.gtk_copy_menu=self.builder.get_object("gtk_copy_menu")
self.gtk_paste_menu=self.builder.get_object("gtk_paste_menu")
self.gtk_about_menu=self.builder.get_object("gtk_about_menu")
self.galician_option=self.builder.get_object("radiomenuitem1")
self.spanish_option=self.builder.get_object("radiomenuitem2")
self.english_option=self.builder.get_object("radiomenuitem3")
def set_menubar_names(self):
self.file_menu.set_label(_("_File"))
self.edit_menu.set_label(_("_Edit"))
self.options_menu.set_label(_("_Options"))
self.help_menu.set_label(_("_Help"))
self.languages_menu.set_label(_("_Languages"))
self.delay_option.set_label(_("_Delay"))
self.gtk_quit_menu.set_label(_("Quit"))
self.gtk_copy_menu.set_label(_("Copy"))
self.gtk_cut_menu.set_label(_("Cut"))
self.gtk_paste_menu.set_label(_("Paste"))
self.gtk_about_menu.set_label(_("About"))
self.galician_option.set_label(_("_Galician"))
self.spanish_option.set_label(_("_Spanish"))
self.english_option.set_label(_("_English"))
def create_login_box(self):
self.user_entry = self.builder.get_object("user_entry")
self.password_entry = self.builder.get_object("password_entry")
self.user_label=self.builder.get_object("user_label")
self.password_label=self.builder.get_object("password_label")
self.login_button=self.builder.get_object("login_button")
def set_login_box_names(self):
self.user_entry.set_placeholder_text(_("user"))
self.password_entry.set_placeholder_text(_("password"))
self.user_label.set_label(_("User"))
self.password_label.set_label(_("Password"))
self.login_button.set_label(_("Login"))
def create_about_dialog(self):
self.aboutdialog = self.builder.get_object("aboutdialog1")
self.aboutdialog.set_transient_for(self.window)
def set_about_dialog(self):
self.aboutdialog.set_comments(_("Developed for GTK 3+ and Python 3.4"))
def reset_names(self):
self.set_menubar_names()
self.set_login_box_names()
def on_radiomenuitem1_toggled(self, widget):
if widget.get_active():
self.lang_gl_ES.install()
self.reset_names()
self.window.queue_draw()
else:
pass
def on_radiomenuitem2_toggled(self, widget):
if widget.get_active():
self.lang_es_ES.install()
self.reset_names()
self.window.queue_draw()
else:
pass
def on_radiomenuitem3_toggled(self,widget):
if widget.get_active():
self.lang_en_US.install()
self.set_menubar_names()
self.window.queue_draw()
else:
pass
def set_languages(self):
WHERE_AM_I = abspath(dirname(__file__))
locale.setlocale(locale.LC_ALL, '')
locale.bindtextdomain(APP, WHERE_AM_I)
locale_path = WHERE_AM_I +'/'
self.builder.set_translation_domain(APP)
gettext.find(APP,localedir=locale_path,languages=['gl_ES'])
gettext.find(APP,localedir=locale_path,languages=['es_ES'])
gettext.find(APP,localedir=locale_path,languages=['en_US'])
gettext.install(APP,locale_path)
gettext.textdomain(APP)
gettext.bindtextdomain(APP,locale_path)
self.lang_gl_ES=gettext.translation(APP,localedir=locale_path, languages=['gl_ES'])
self.lang_es_ES=gettext.translation(APP,localedir=locale_path, languages=['es_ES'])
self.lang_en_US=gettext.translation(APP,localedir=locale_path, languages=['en_US'])
def set_signals(self):
handlers = {
"on_applicationwindow1_destroy": self.on_applicationwindow1_destroy,
"on_gtk_about_activate": self.on_gtk_about_activate,
"on_login_button_clicked": self.on_login_button_clicked,
"on_applicationwindow1_key_press_event": self.on_applicationwindow1_key_press_event,
"on_entry_focus": self.on_entry_focus,
"on_gtk_cut_activate": self.on_gtk_cut_activate,
"on_gtk_copy_activate": self.on_gtk_copy_activate,
"on_gtk_paste_activate": self.on_gtk_paste_activate,
"on_radiomenuitem1_toggled": self.on_radiomenuitem1_toggled,
"on_radiomenuitem2_toggled": self.on_radiomenuitem2_toggled,
"on_radiomenuitem3_toggled": self.on_radiomenuitem3_toggled
}
self.builder.connect_signals(handlers)
def __init__(self):
# GObject.signal_new("z_signal", Gtk.ApplicationWindow, GObject.SIGNAL_RUN_FIRST, GObject.TYPE_NONE, ())
self.builder = Gtk.Builder()
self.builder.add_from_file("p1.glade")
self.window = self.builder.get_object("applicationwindow1")
self.set_languages()
self.create_menubar()
self.create_login_box()
self.create_about_dialog()
self.reset_names()
self.set_signals()
self.focus = None
self.finished = False
self.authentication = False
# self.statusbar = self.builder.get_object("statusbar1")
# self.context_id = self.statusbar.get_context_id("status")
# self.status_count = 0
self.message_dialog = self.builder.get_object("messagedialog1")
self.message_dialog.set_transient_for(self.window)
self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
self.window.show_all()
if __name__ == "__main__":
GObject.threads_init()
main = UDC_Social_API()
Gtk.main()
Glade file is in pastebin, because it will exceed post size limit.
http://pastebin.com/8S3k7f6J
Thanks in advance for any help you could provide.
You can use GLib.idle_add to schedule a callback to be executed by the event loop in the main thread of your program. This means it provides a safe way to schedule a GUI update from a background thread. So, you can just let your background thread run normally, let the main thread return control to the event loop, and then make the appropriate GUI updates from the background thread via GLib.idle_add once it's done:
def verify_credentials(self, user, password):
self.delay()
if user in user_list:
if password == user_list.get(user):
self.authentication = True
else:
self.authentication = False
else:
self.authentication = False
# Schedule z_handler to be called by the event loop in the main thread.
GLib.idle_add(z_handler, None)
def z_handler(self, data=None):
if not self.authentication:
self.message_dialog.set_markup(_("User/Password incorrect\nPlease, verify login information"))
self.message_dialog.run()
self.message_dialog.hide()
return False
else:
self.window.hide()
print ("Success!")
You're actually pretty close to using this same method, you're just doing it in an awkward way - you're scheduling active_waiting to run in the main thread, which waits until the background thread is done, and then calls z_handler. Scheduling z_handler directly, after the background thread is done with its work, is much simpler.

Categories

Resources