0

I'm trying to create application which runs block of code every X seconds, which has system tray icon with only "Quit" option. But the problem is that when it get to the tray function, it doesn't read next lines of code, and as a result, "While" loop can't be launched. Is there any other approach to do that?

import time
import os
import sys
from PySide2 import QtWidgets, QtGui

class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
    def __init__(self, icon, parent=None):
        QtWidgets.QSystemTrayIcon.__init__(self, icon, parent)
        self.setToolTip(f'Wallpy')
        menu = QtWidgets.QMenu(parent)

        exit_ = menu.addAction("Exit")
        exit_.triggered.connect(lambda: sys.exit())

        menu.addSeparator()
        self.setContextMenu(menu)


def tray():
    app = QtWidgets.QApplication(sys.argv)
    w = QtWidgets.QWidget()
    tray_icon = SystemTrayIcon(QtGui.QIcon("tray.ico"), w)
    tray_icon.show()
    app.exec_()


def loop_function():
    print("Nice") # anything executable


tray() # launch tray icon


while True:
    loop_function() # executing every minute
    time.sleep(60)
J Arun Mani
  • 620
  • 3
  • 20
qeqoos
  • 32
  • 4

1 Answers1

0

Its because, when you used the tray(), your main application started and the GUI main loop is initiated. It runs till your application exits, after which the while loop is executed.

However, if you want the loop to run simultaneously, you should integrate it with Qt's main loop. In Gtk we do this using GLib.add_main_thread and other methods, I don't know about Qt, but you can use this general solution using Threading.

from threading import Thread
import time
import os
import sys
from PySide2 import QtWidgets, QtGui


def loop_function():
    print("Nice") # anything executable

def thread_loop():
    while True:
        loop_function() # executing every minute
        time.sleep(60)

class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
    def __init__(self, icon, parent=None):
        QtWidgets.QSystemTrayIcon.__init__(self, icon, parent)
        self.setToolTip(f'Wallpy')
        menu = QtWidgets.QMenu(parent)

        exit_ = menu.addAction("Exit")
        exit_.triggered.connect(lambda: sys.exit())

        menu.addSeparator()
        self.setContextMenu(menu)


def tray():
    app = QtWidgets.QApplication(sys.argv)
    w = QtWidgets.QWidget()
    tray_icon = SystemTrayIcon(QtGui.QIcon("tray.ico"), w)
    tray_icon.show()
    app.exec_()

my_loop = Thread(target=thread_loop, args=()) # Start the thread with no args
my_loop.start()
tray() # launch tray icon
J Arun Mani
  • 620
  • 3
  • 20
  • there's an issue, when I click "Exit", it stucks till I close CMD window, any resolve to this? – qeqoos Jan 18 '20 at 16:43
  • Maybe its, because, you are connecting the "Exit" button with `sys.exit`. It is not good. Python closes your script, but the window is still there on the screen, without any controller. So the solution is to use the proper main loop quitting in Qt. – J Arun Mani Jan 18 '20 at 16:46
  • I'll try to find proper main loop quitting, hope this works, thanks. It will be nice if u can point me where to search it – qeqoos Jan 18 '20 at 16:51
  • It is a basic info. You can find it, in almost all tutorial and demo code. I have not used Qt, so let me also search. You can accept my answer, if you wish – J Arun Mani Jan 18 '20 at 16:56
  • Okay, so from Qt scripts, they are using `sys,exit(app.exec_())`, I don't know why. You can read it here https://github.com/shuage/Qt-Python-Binding-Examples – J Arun Mani Jan 18 '20 at 17:00
  • Hello, any way to apply this to my question? https://stackoverflow.com/questions/62010865/tray-icon-script-that-uses-a-while-true-loop-cant-be-closed – Daniel May 25 '20 at 21:48
  • @DanielBeilin sorry I don't know about the modules used in your code. The idea I suggested here is to run the blocking code (that is while loop) in a separate thread. You can copy the same logic (i.e. `thread_loop` function) and see if it works. – J Arun Mani May 26 '20 at 07:43
  • 1
    @JArunMani Thanks, I tried to apply the same code but it didn't work and I might have used it wrong. – Daniel May 26 '20 at 08:36