I am trying to develop a desktop notification system with python and Libnotify.
I found this tutorial and tried the example with an action callback, below is my code modification
#initialization of libnotify
Notify.init("Py-Notification")
#creating object
summary = "Wake Up!"
body = "Meeting at 9pm"
notification = Notify.Notification.new(
summary, body
)
# Define a callback function
def my_callback_func():
webbrowser.open('http://google.com')
#adding actions
notification.add_action(
"action_click",
"Reply to Alarm",
my_callback_func,
None # Arguments
)
notification.show()
The callback function is not called whenever I click on the "Reply to Alarm" button
Any help.
You need to integrate with D BUS to receive events from your notifications.
Here is good explanation use Glib for it.
Related
I face an issue and I want to understand why this problem happens and how to solve this problem. I know a lot of questions on stack overflow that talk about tkinter freeze when button pressed I saw many solutions but it is not working for me and I want some help to understand how to solve this problem, I work on some app using tkinter I trying use libraries like TikTokLive to learn new something and I tried to make a button that when pressed gives some information I tried threading but not working and tried to see about use queue and I understand the queue and I saw solutions like use multiprocess but nothing works for me so I thought that problem happens because of the tiktoklive library may be because we use async programming so I made some search and saw solution but not working, I want to some help to understand more how to solve this problem.
Sample code below:
from tkinter import *
root = Tk()
root.geometry("300x300")
get_information = Button(text="get", font='normal 30 bold', command=lambda: connect_with_tiktok_live())
get_information.pack()
def connect_with_tiktok_live():
# dependencies
import TikTokLive.types.events
from TikTokLive import TikTokLiveClient
from TikTokLive.types.events import ConnectEvent
username = "put the username of tiktok live"
# Instantiate the client with the user's username
client: TikTokLiveClient = TikTokLiveClient(
unique_id=username, **({
"process_initial_data": False,
"enable_extended_gift_info": True,
}))
#client.on('connect')
async def on_connect(_: ConnectEvent):
print("Connected to Room ID: ", client.room_id)
# Run the client and block the main thread
# await client.start() to run non-blocking
try:
return client.run()
except FailedConnection: # if live is ended
print('finished')
mainloop()
gif problrm:
some links solution not working for me
How can I prevent a tkinter Gui from freezing while an async task is running?
python running task in the background while allowing tkinter to be active
Tkinter window says (not responding) but code is running
How to easily avoid Tkinter freezing?
How to run a function in the background of tkinter
Tkinter: How to use threads to preventing main event loop from "freezing"
You can use multithreading here using threading.Thread method.
from tkinter import *
from threading import Thread
root = Tk()
root.geometry("300x300")
get_information = Button(text="get", font='normal 30 bold', command= lambda:Thread(target=connect_with_tiktok_live).start())
get_information.pack()
def connect_with_tiktok_live():
# dependencies
import TikTokLive.types.events
from TikTokLive import TikTokLiveClient
from TikTokLive.types.events import ConnectEvent
username = "put the username of tiktok live"
# Instantiate the client with the user's username
client: TikTokLiveClient = TikTokLiveClient(
unique_id=username, **({
"process_initial_data": False,
"enable_extended_gift_info": True,
}))
#client.on('connect')
async def on_connect(_: ConnectEvent):
print("Connected to Room ID: ", client.room_id)
# Run the client and block the main thread
# await client.start() to run non-blocking
try:
return client.run()
except FailedConnection: # if live is ended
print('finished')
mainloop()
I have a window application in which I am trying to refresh a table every x seconds after running my function. However I could not find any suitable method to rerun the function within the event loop of the app. This is my code and the function I'm trying to rerun is FLAS(I'm returning a list of objects).
flights = FLAS()
with dpg.window(width=785, height=600, no_collapse=True, no_move=True, no_title_bar=True, no_resize=True):
with dpg.table(header_row=True, policy=dpg.mvTable_SizingFixedFit, row_background=True, reorderable=True,
resizable=False, no_host_extendX=False, hideable=True,
borders_innerV=True, delay_search=True, borders_outerV=True, borders_innerH=True,
borders_outerH=True):
dpg.add_table_column(label="Callsign", width_fixed=True)
dpg.add_table_column(label="FIX", width_fixed=True)
dpg.add_table_column(label="Exit FIR", width_fixed=True)
dpg.add_table_column(label="Next FIR", width_fixed=True)
dpg.add_table_column(label="Entry FL", width_fixed=True)
dpg.add_table_column(label="Exit FL", width_fixed=True)
print(len(flights))
if len(flights) == 0:
flights.append(Flight("No flights in range", 000000, "XXX", 0, "XXXX", "XXXX",0,0,0,0))
for flight in flights:
with dpg.table_row():
dpg.add_text(flight.callsign)
dpg.add_text(flight.fix)
dpg.add_text(flight.cFIR)
dpg.add_text(flight.xFIR)
dpg.add_text(flight.efl)
dpg.add_text(flight.xfl)
dpg.show_viewport()
dpg.start_dearpygui()
dpg.destroy_context()
You can easy do it within the render loop:
https://dearpygui.readthedocs.io/en/latest/documentation/render-loop.html
The only thing you need now is to define a timer class.
The otherway would be to work with the Thread module.
DPG is not that popular so far, to ask on Stackoverflow. A better source to ask is on github or on the DPG Discord Server ( you will find some examples in the #support channel how to build a timer class and how to use it.
I am using dearpygui as an interface for a webscraping tool. I have a "status box" which I want to use to communicate messages to the user. It is setup as a read-only, multi-line input text box and is designed to update with the old value and append the new message. If I run the program, it will work but the updates to the status box do not show up until the webscraping(download_reports function) is finished. The gui is not updating each time the update_status function is called. What is the best way to get this to update and display when called and not when the entire process has finished?
def window_month_end_reports(sender, data):
with window('Month End'):
for building in buildings:
add_checkbox(building)
add_spacing()
add_button("Done", callback=run_month_end_reports)
add_spacing()
add_separator()
add_text("Select reports")
for report in reports_list:
add_checkbox(report)
def run_month_end_reports(sender, data):
item_list = []
building_list = []
delete_item('Month End')
for item in reports_list: # LIST OF REPORTS SELECTED
if get_value(item):
item_list.append(item)
for building in buildings:
if get_value(building):
building_list.append(building)
update_status('Running month end reports')
download_reports(building_list, item_list)
def update_status(message):
set_value('##status box', get_value('##status box') + str(message) + '\n')
with window("Main Window"):
add_button("Month End Reports", callback=window_month_end_reports)
add_text("Status Box:")
add_input_text("##status box", readonly=True, multiline=True, height=500)
start_dearpygui(primary_window="Main Window")
Probably, the best way to solve this is to use an async task to complete the download reports function. You could use run_async_function to launch the download. You can find an example of the long task management in the documentation: async functions
I am writing a script intended to be used by members of a project team. As part of the script, I am launching a 3rd party proprietary application run through Citrix. I am going to use the script mostly to send keys to this application, but the first step once it launches is for the user to log in.
Because I would like the user to log in while the script is running, rather than asking for user/pass from some kind of GUI input earlier, and because the time it takes Citrix to launch varies, I would like to include some kind of logic that detects when the user has logged in and then resume the script from there, rather than including an obnoxiously long implicit wait or risking the script timing out.
Is there a way to detect user keystrokes using win32com.client (or to detect a change in state of the application itself)? See below for the relevant code to launch the app:
import win32com.client
shell = win32com.client.Dispatch("WScript.Shell")
shell.Run('C:\Citrix\[rest of path])
EDIT:
Per Vasily's suggestion in the comments below, I attempted to adapt the "hook and listen" code to my scenario, but was unsuccessful. When I launch my file, I don't even get an exception message in my terminal, I get a Windows pop-up that says Python encountered a problem and needs to quit.
This is how I adapted it:
#[omitting import lines for brevity]
def on_timer():
"""Callback by timer out"""
win32api.PostThreadMessage(main_thread_id, win32con.WM_QUIT, 0, 0);
def on_event(args):
"""Callback for keyboard and mouse events"""
if isinstance(args, KeyboardEvent):
for i in range(1,100):
time.sleep(1)
if args.pressed_key == 'Lcontrol':
break
def init():
hk = Hook()
hk.handler = on_event
main_thread_id = win32api.GetCurrentThreadId()
t = Timer(55.0, on_timer) # Quit after 55 seconds
t.start()
hk.hook(keyboard=True, mouse=True)
At the point when the 3rd party Citrix app begins to launch in my main script, I call hookandlisten.init().
As a reminder, my goal is to wait until the user sends a certain keystroke (here I chose Control) before proceeding with the rest of the main script.
Solved this by eliminating the timer and unhooking the keyboard upon the correct keystroke:
import win32api
import win32con
from pywinauto.win32_hooks import Hook
from pywinauto.win32_hooks import KeyboardEvent
from pywinauto.win32_hooks import MouseEvent
def on_event(args):
"""Callback for keyboard and mouse events"""
if isinstance(args, KeyboardEvent):
if args.current_key == 'Lcontrol' and args.event_type == 'key down':
print("Success")
hk.unhook_keyboard()
return
def init():
hk.handler = on_event
hk.hook(keyboard=True, mouse=False)
hk = Hook()
I try to display the current windows for each click on the system.
I do this code :
from AppKit import NSWorkspace
def getwindows():
activeAppName = NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationName']
print activeAppName
return
def main():
getwindows()
main()
But only the current windows when i setup the script is displayed.
How can i bind this script in a loop with a click event ?
I already try to use Turtle but some errors appended.
Note that the activeApplication method of NSWorkSpace is deprecated. The following can be used to actively probe the running applications for their active status:
import AppKit
import time
rl = AppKit.NSRunLoop.currentRunLoop()
ws = AppKit.NSWorkspace.sharedWorkspace()
for i in xrange(10):
for app in ws.runningApplications():
if app.isActive():
print "active app:", app.localizedName()
date = AppKit.NSDate.date()
time.sleep(1)
rl.acceptInputForMode_beforeDate_( AppKit.NSDefaultRunLoopMode, date )
Active means it is the receiving keyboard input. Clicking on an application will cause it to become active. Note that the acceptInputForMode method must be called so that property changes are reflected in the current app. Run this program then click on various other applications -- you should see the active app change.
A kind of binding can be done through observers:
import AppKit
ws = AppKit.NSWorkspace.sharedWorkspace()
appL = ws.runningApplications()
class MyClass( AppKit.NSObject ):
def observeValueForKeyPath_ofObject_change_context_(self,
kpath, objid, change, context ):
print "path change", kpath, change['new'], appL[context].localizedName()
obj = MyClass.new()
for i in xrange(len(appL)):
appL[i].addObserver_forKeyPath_options_context_( obj,
"isActive", AppKit.NSKeyValueObservingOptionNew, i )
date = AppKit.NSDate.date().dateByAddingTimeInterval_( 10 )
rl = AppKit.NSRunLoop.currentRunLoop()
rl.acceptInputForMode_beforeDate_( AppKit.NSDefaultRunLoopMode, date )
for app in appL:
app.removeObserver_forKeyPath_( obj, "isActive" )
Run this program same as the last.
There are a few other properties of NSRunningApplication that you could probe/observe (such as hidden) but the list is quite short.