Skip to content

Quickly make a windows executable with a system tray icon and an configurable (read empty) PyQT5 window

License

Notifications You must be signed in to change notification settings

modularizer/programmify

Repository files navigation

Programmify

Quickly make a windows executable with a system tray icon and an configurable (read empty) PyQT5 window

Sample Widget

Task Manager Task Manager

Yes! You can use your own icon

Features

  • Use your own icon
  • System tray icon (in task bar)
  • Window title (in window title bar)
  • Window icon (in window title bar)
  • Executable name (in File Explorer & Task Manager)
  • Executable file icon (in File Explorer & Task Manager)
  • PyQT Widget OR PyQT Main Window
  • executable with icon on desktop
  • can be pinned to taskbar

Support

  • Windows
  • Linux
  • Mac

Quickstart

  1. Make a new python project folder, let's call it myprogram

  2. Make a virtual environment if you want, or just use your system python

  3. Install programmify

    pip install programmify
    
  4. Make a new file in myprogram, let's call it myapp.py

  5. import and use either ProgrammifyWidget or ProgrammifyMainWindow from programmify in your script

    # myprogram/myapp.py
    from PyQt5 import QtWidgets
    
    from programmify import ProgrammifyWidget
    
    
    class MyWidget(ProgrammifyWidget):
        def setupUI(self):
            # Create a layout
            layout = QtWidgets.QVBoxLayout(self)
    
            # Add a label
            label = QtWidgets.QLabel("Hello, Programmify!")
            layout.addWidget(label)
    
            # Add a button
            button = QtWidgets.QPushButton("Click Me")
            button.clicked.connect(self.on_button_clicked)  # Connect to a method to handle the click event
            layout.addWidget(button)
    
            # Set the layout on the QWidget
            self.setLayout(layout)
    
        def on_button_clicked(self):
            QtWidgets.QMessageBox.information(self, "Action", "Button was clicked!")
    
    
    if __name__ == '__main__':
        MyWidget.run()
  6. Build the executable

    From command prompt in the project directory:

    (venv) C:\Users\user\myprogram> programmify --desktop

NOTES:

  • If you have ONLY one .py file in the current working directory you don't need to specify the file to build, otherwise you may need to specify programmify myapp.py
  • include a favicon.ico in your current working directory to use as the icon for the program
  • --desktop will copy the executable to your desktop
  1. Run An executable should have been created at myprogram/myapp.exe and also copied to your desktop. Double click to run!

Usage:

programmify myapp.py --name testprogram --icon testicon.ico

Advanced usage:

  • programmify --help to see all options
  • add --show_cmd to show the pyinstaller command that will be run instead of running it (useful for debugging)
>programmify --help
usage: programmify [-h] [--name NAME] [--dst DST] [--icon ICON] [--mode MODE] [--nocleanup] [--show_cmd] [--cmd CMD] [--hidden_imports [HIDDEN_IMPORTS ...]]
                   [--extra_files [EXTRA_FILES ...]] [--debug] [--args ...] [--desktop] [--version VERSION]
                   file

positional arguments:
  file                  File to build. If not specified, will try ... 
                            1. main.py in current working directory if found 
                            2. __main__.py 
                            3. the only .py file in the current working directory if only one is found (excluding __init__.py) 
                            4. if there is a src directory, will search in src and its subdirectories to find a single option 
                            5. if the above fails, will raise an error and you will need to specify the file to build.

options:
  -h, --help            show this help message and exit
  --name NAME           Program name. If not specified, the name of the either the file or its parent directory will be used.
  --dst DST             Destination directory for the built program
  --icon ICON           Path to a 16x16 .ico file. If not specified, will try to find favicon.ico or any other .ico or .png in the current working directory.
  --mode MODE           Program mode: window or widget
  --nocleanup           Cleanup build files
  --show_cmd            Show the command that will be run instead of running it
  --cmd CMD             Expert level: command to run instead of pyinstaller
  --hidden_imports [HIDDEN_IMPORTS ...]
                        Hidden imports
  --extra-files [EXTRA_FILES ...]
                        Extra files to include
  --debug               Does not run in windowed mode, instead shows the terminal and stdout
  --args ...            Additional arguments to pass to pyinstaller
  --desktop             Copy the file to the desktop
  --version VERSION     Adds the version string to the end of the program name. e.g. --version 1 => my_program v1

Other Installed Scripts

  • png2ico to convert a .png to a .ico file
    • see png2ico --help for usage

Uses

Subprocess Widget

Run any subprocess command (bash) and display a live feed of stdout and stderr in a PyQT5 widget.

  1. The program which gets called
# count.py
import time
import sys

def count(start, stop, interval=1):
    for i in range(start, stop):
        print(i)
        sys.stdout.flush() # unfortunately, this is necessary to get the output to show up in the widget
        time.sleep(interval)
    sys.stderr.flush()
        
if __name__ == '__main__':
    start = int(sys.argv[1])
    stop = int(sys.argv[2])
    interval = int(sys.argv[3])
    count(start, stop, interval)

BUG

IMPORTANT: sys.stdout.flush() is necessary to get the output to show up in the widget. This is a bug I am working on fixing. It is not necessary when running main.py directly, only when running the executable.

  1. The application which makes the widget and runs the subprocess command
# main.py
from programmify import SubprocessWidget

if __name__ == '__main__':
    cmd = ["python", "count.py", '1000', '1010', '1']
    SubprocessWidget.run(cmd=cmd)
  1. Build the executable
programmify main.py --name count --extra-files count.py
  • Note: pyinstaller doesn't see that we are depending on the count.py to be included as well, so we must specify
  1. The output

Subprocess Widget

About

Quickly make a windows executable with a system tray icon and an configurable (read empty) PyQT5 window

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages