Create a small control panel on screen for pyautogui monitoring and control purposes

Question:

How do I display a small control panel screen that can control and monitoring pyautogui process? I expect there is a pinned window that for monitoring purpose such as displaying current log.txt that has been generated by logging and controlling purpose such as pause and resume button? Actually these are inteded for debugging purposes.

Here are my simple code:

main.py

if __name__ == '__main__':
  # Get current timestamp
  current_time: str = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')

  # Initialize logging config
  logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(levelname)s - %(message)s',
    filename=f'./log/bot_{current_time}.log'
    )

  logging.info('Start of program.')
  execute()
  logging.info('End of program.')

executes.py

'''
  Here list of order of actions to be executed that has been defined from actions.py file.
'''

from actions import open_firefox, open_new_tab

def execute():
  """
    This is main program.
  """
  open_firefox()
  open_new_tab()

actions.py:

'''
 Here is list of actions defined that wrapped in functions to be used in executes.py file.
'''

from time import sleep
import logging
import pyautogui as pag

def open_firefox():
  """
    Open Firefox browser.
  """
  logging.info('Open Firefox browser.')
  firefox_icon_location = pag.locateCenterOnScreen('./asset/firefox.png', confidence=0.75)
  pag.moveTo(firefox_icon_location, duration=1)
  sleep(1)
  pag.leftClick()
  sleep(1)
  logging.info('Firefox browser has been opened.')

def open_new_tab():
  """
    Open new tab.
  """
  pag.hotkey('ctrl', 't')
  sleep(1)

Answers:

You can wrap your existing scripts with a simple tkinter application, and add two buttons and a text widget there to view the logger info. Here’s a basic example wrapped into one script:

import tkinter as tk
from time import sleep
import logging
from tkinter.scrolledtext import ScrolledText
import pyautogui as pag


def open_firefox():
    """Open Firefox browser."""
    logging.info('Open Firefox browser.')
    try:
        firefox_icon_location = pag.locateCenterOnScreen('./asset/firefox.png', confidence=0.75)
        if firefox_icon_location is not None:
            pag.moveTo(firefox_icon_location, duration=1)
            sleep(1)
            pag.leftClick()
            sleep(1)
            logging.info('Firefox browser has been opened.')
        else:
            logging.error('Firefox icon not found on screen.')
    except Exception as e:
        logging.error(f"Error opening Firefox: {e}")

def open_new_tab():
    """Open new tab."""
    try:
        pag.hotkey('ctrl', 't')
        sleep(1)
        logging.info('New tab opened.')
    except Exception as e:
        logging.error(f"Error opening new tab: {e}")


class TextHandler(logging.Handler):
    """ Custom logging handler sending logs to a Tkinter Text widget. """
    def __init__(self, text_widget):
        super().__init__()
        self.text_widget = text_widget

    def emit(self, record):
        msg = self.format(record)
        self.text_widget.configure(state='normal')
        self.text_widget.insert(tk.END, msg + 'n')
        self.text_widget.configure(state='disabled')
        # Scroll to the bottom
        self.text_widget.yview(tk.END)

if __name__ == '__main__':
    # Set up Tkinter window
    root = tk.Tk()
    root.title("Firefox Control")
    root.geometry("400x400")

    # Create ScrolledText widget for logs
    log_widget = ScrolledText(root, state='disabled')
    log_widget.pack(fill=tk.BOTH, expand=True)

    # Set up custom logging handler
    text_handler = TextHandler(log_widget)
    logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
    logger = logging.getLogger()
    logger.addHandler(text_handler)
    
    logging.info('Start of program.')
    
    # Buttons
    button_firefox = tk.Button(root, text="Open Firefox", command=open_firefox)
    button_firefox.pack(pady=10)

    button_new_tab = tk.Button(root, text="Open New Tab", command=open_new_tab)
    button_new_tab.pack(pady=10)

    # Start the Tkinter event loop
    root.mainloop()

Output:

enter image description here

Check out tkinter documentation to learn more: https://docs.python.org/3/library/tkinter.html

Answered By: Musabbir Arrafi