Shared screen screenshot exe app with python

Introduction

Recently, lessons and meetings are increasingly held using web conferencing systems such as zoom. However, the major drawback of online lessons is that the blackboard shared on the screen will flow shortly after you make a note. In order to solve such a problem, I tried to make an exe application ** that can be saved as pdf by squeezing the registered range (shared screen part etc.) with one click. (* Let's take screenshots only if you have permission to take screenshots)

The app and its details can be found on GitHub, so I'd appreciate it if you could use it and comment (advice, etc.). \ <GitHub version ↓ >

This time, as a memo of the creation procedure, I will use a simplified full screenshot application ** 1. [Graphic (appearance) design](# 1-Graphic design) 2. [Event (action) settings](# 2-Event settings) 3. [Create Icon](# 3-Create Icon Self-style) 4. [exe conversion](# 4-exe conversion) ** I will write in the order of. \ <Simplified version ↓ >

What you prepared

・ Windows10 ・ Python 3.7.9 (up to 3.7.X if exe is converted with py2exe) ・ WxPython (phoenix) ・ Power Point ・ Py2exe (Installation details described later)

1. Graphic design

Make your app look with ** wxpython **. There is an easy-to-use tkinter in the standard library, but wxpython has a lot of event processing and you can make elaborate apps. Basically, wx.Panel (panel) is spread in wx.Frame (frame, skeleton), and widgets such as wx.Button (button) are placed on it. Frames, panels, and widgets take almost the same arguments, but we'll focus on the ones we'll use this time.

argument Description
parent parent. Place yourself on the frame or panel you put in here. When the parent disappears, the child himself disappears.
label / value Set the characters to be displayed on yourself and the values that you hold. Which one can be used or not can be used for each widget. value is[Widget].GetLabel()/[Widget].GetValue()Get in,[Widget].SetLabel([value])/[Widget].SetValue([value])Can be changed with.
pos (x, y)In the form of a screen, orparentOwn x against-Set the y coordinate. Upper left corner
size (w, h)Set your own width and height in the form of.

There is also a way to arrange widgets with "sizar" such as wx.BoxSizer without using pos. Then, when the user changes the window size, each part can be moved or scaled according to the size. (This time, I will not use it because the window size is fixed)

Let's see the specific usage below.

sample_1.py


# coding: utf-8
import wx                                       #Import wxpython
try:                                            # ⏋
    from ctypes import windll                   #| App resolution setting
    windll.shcore.SetProcessDpiAwareness(True)  #| (Prevents out-of-focus)
except:                                         # |
    pass                                        # ⏌

app = wx.App()  #Write this at the beginning and start wx

#GUI settings ──────────────────────────────────────────────── ─────────────────────────────────────────────────
frame = wx.Frame(parent=None,            #Create a frame (outer frame)
                 title='Screenshot app',
                 pos=(0, 0),             # pos=(x, y)Is the x of the frame position with the upper left of the screen as the origin-y coordinate
                 size=(400, 230),        # size=(w, h)Is the width of the frame(w)And height(h)
                 style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX))
                                         #style is any additional setting.This time disable window resizing

panel = wx.Panel(parent=frame)  #Create a panel on the frame

wx.StaticText(parent=panel, label='Destination:',  #Create a string on the panel.pos is parent(panel)Relative coordinates on
              pos=(20, 20))
wx.TextCtrl(parent=panel, value='Unselected',     #Create a folder input field on the panel
            pos=(150, 17), size=(160, -1),   #to size"-1"Enter and leave it to wx
            style=wx.TE_READONLY)            # TE_Input can be disabled with READONLY
wx.Button(parent=panel, label='...',
          pos=(320, 16), size=(40, 35))

wx.StaticText(parent=panel, label='Last screenshot:', pos=(20, 70))
wx.StaticText(parent=panel, label='―', pos=(150, 70), size=(210, -1),
              style=wx.TE_CENTER)  # TE_At CENTER,Characters can be centered within the width given by size

wx.Button(parent=panel, label='Screenshot',
          pos=(20, 120), size=(340, 40))
# ───────────────────────────────────────────────────────────────────────────────────────────────────────

frame.Show()    #Show frame when it looks
app.MainLoop()  #Completed by accepting event input

When you run it, it will look good. Since no event is set, there is no response even if the button is pressed.

2. Event settings

Set an event in the button or input field. Basically, the contents to be processed for each operation are summarized in the function func_1 (event, [second argument], ...) and linked with [widget] .Bind ([event type], func_1). I will. Event types range from widget-specific ones such as wx.EVT_BUTTON (when the button is pressed) and'wx.EVT_SLIDER' (when the slider value changes) to wx.EVT_CLOSE (window closes). When) and so on.

sample_2.py


# coding: utf-8
import os
import re
from glob import glob
from datetime import date
from PIL import ImageGrab
import wx
try:
    from ctypes import windll
    windll.shcore.SetProcessDpiAwareness(True)
except:
    pass

TODAY = format(date.today())  #Today's date
last_pic_num = 0              #Photo number

#Event function definition ─────────────────────────────────────────────── ─────────────────────────────────────────
def open_folder_dialog(event):  #The first argument of the function used in the event"event"Write
    """
Folder the path of the folder selected in the dialog_Displayed in txctrl,
Get the last photo number in the folder, picture_Function to update info information
    """
    global last_pic_num
    dlg = wx.DirDialog(parent=None, message='Select save destination')  #Dialog settings
    if dlg.ShowModal() == wx.ID_OK:                       # ShowModal()Start with,Once selected, do the following: ↓
        dirpath = dlg.GetPath()                           #Get the path to the selected folder,
        folder_txctrl.SetValue(dirpath)                   #Update input field,
        os.chdir(dirpath)                                 #Move into that folder,
        all_pictures = [p for p in glob(os.path.join(dirpath, '*.png'))  #Create a photo list with today's date
                        if re.search('{}_\\d'.format(TODAY), p)]
        if all_pictures:                                                             #If you have a photo,
            last_pic_num = max(list(map(lambda x: int(re.findall('_(\\d+)', x)[0]),  #Get the last number,
                                        all_pictures)))
            picture_info.SetLabel(str(last_pic_num))                                 #Update photo information
        else:
            last_pic_num = 0
            picture_info.SetLabel('─')
        scshot_button.Enable()  #Enable screenshot button

def screen_shot(event):
    """
Screenshot the screen,Save with the advanced photo number, picture_Function to update info information
    """
    global last_pic_num
    last_pic_num += 1                                   #Move the number up by one,
    picture_info.SetLabel(str(last_pic_num))            #Update photo information
    screen_picture = ImageGrab.grab()                   #Take a screenshot,
    save_name = TODAY + '_{}.png'.format(last_pic_num)  # "2020-01-23_(number)"In the format of,
    screen_picture.save(save_name)                      #Save
# ───────────────────────────────────────────────────────────────────────────────────────────────────────

app = wx.App()

#GUI settings ──────────────────────────────────────────────── ─────────────────────────────────────────────────
frame = wx.Frame(parent=None, title='Screenshot app', pos=(0, 0), size=(400, 230),
                 style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX))
panel = wx.Panel(parent=frame)

wx.StaticText(parent=panel, label='Destination:', pos=(20, 20))
folder_txctrl = wx.TextCtrl(parent=panel, value='Unselected', pos=(100, 17), size=(210, -1),  #Call later
                            style=wx.TE_READONLY)
folder_button = wx.Button(parent=panel, label='...', pos=(320, 16), size=(40, 35))        #Call later
wx.StaticText(parent=panel, label='Today's final screenshot number:', pos=(20, 70))
picture_info = wx.StaticText(parent=panel, label='―', pos=(200, 70), size=(160, -1),      #Call later
                             style=wx.TE_CENTER)
scshot_button = wx.Button(parent=panel, label='Screenshot', pos=(20, 120), size=(340, 40))  #Call later
# ───────────────────────────────────────────────────────────────────────────────────────────────────────

scshot_button.Disable()  #Disable the screenshot button until the save destination is selected

#Event setting ──────────────────────────────────────────────── ────────────────────────────────────────────
folder_button.Bind(wx.EVT_BUTTON, open_folder_dialog)  #When you press the button,Execute the function of the second argument
scshot_button.Bind(wx.EVT_BUTTON, screen_shot)         #note)At the end of the function"()"Do not put on.
# ───────────────────────────────────────────────────────────────────────────────────────────────────────

frame.SetIcon(wx.Icon('sample_icon.ico'))  #Icon setting (error if the specified path does not exist)
frame.Show()
app.MainLoop()

I haven't created an icon, so I get an error when I run it, but when I press the screenshot button, the photo is saved in the selected folder.

3. Icon creation (self-style)

A file with the extension .ico is required, but thankfully there is a site on the net that can convert .png.ico, so make a png with PowerPoint and convert it. (It doesn't have to be PowerPoint)

  1. First draw a large figure and group it
  2. Copy the shape → "Paste Options" → "Figure"
  3. Shrink and trim it so that it fits in a square with a side of 3.91 cm
  4. "Save it as a diagram" You can create .png with. You can convert it to .ico by using this conversion site Let's make a semi-transparent multi-icon favicon.ico!. .. This time, save it as "sample_icon.ico" in the same directory ** as sample_2.py **. (You can put the appropriate path in wx.Icon ([PATH]) anywhere.) When you execute "sample_2.py", you can see that the icon is set in the upper left of the window.

4. exe conversion

Use ** py2exe **, which has a short startup time.

Installation

If you use versions up to python 3.4

pip install py2exe

When using python 3.5-3.7 (hereinafter referred to as 3.X), go to py2exe release site and py2exe-0.9.3.2-cp3X-none- Download win_amd64.whl (64-bit) or py2exe-0.9.3.2-cp3X-none-win32.whl (32-bit) and

py -3.X -m pip install 'Path of downloaded file'

Preparation

You have to create a setup file called setup.py. (Short to say) Put it in the same directory ** as sample_2.py ** again.

setup.py


from distutils.core import setup
import py2exe

option = {'compressed': 1, 'optimize': 2 , 'bundle_files': 3, 'excludes': ['email', 'numpy', 'test', 'tkinter']}

setup(
    options={'py2exe': option},
    windows=[{'script': 'sample_2.py', 'icon_resources': [(1, 'sample_icon.ico')]}],
    zipfile='lib\\libs.zip'
)

Execution of exe

Start a command prompt in the directory containing sample_2.py and setup.py,

py -3.X -m setup py2exe

Then, I think that a dist folder will be created in the folder, so put the .ico file in it (or put it in the location of the description path) and you're done! After that, create a shortcut for .exe and put it on your desktop!

in conclusion

In addition to the above, I learned to use Threading to handle time-consuming event processing in a separate thread. It will not accept input until the processing is completed, and the application will be frozen lol

reference

Recommended Posts

Shared screen screenshot exe app with python
ScreenShot with Selenium (Python)
Get web screen capture with python
[Development environment] Python with Xcode [With screen transition]
Automatic update method with python Pyinstaller exe
Uncle SES modernizes VBA app with Python
Daemonize a Python web app with Supervisor
Easy web app with Python + Flask + Heroku
Create an English word app with python
Make a desktop app with Python with Electron
Othello app (iOS app) made with Python (Kivy)
FizzBuzz with Python3
Scraping with Python
Create an app that guesses students with python
Scraping with Python
Python with Go
Vienna with Python + Flask web app on Jenkins
Twilio with Python
GUI automation with Python x Windows App Driver
Integrate with Python
Play with 2016-Python
AES256 with python
Tested with Python
Develop Windows apps with Python 3 + Tkinter (exe file)
python starts with ()
with syntax (Python)
Bingo with python
Zundokokiyoshi with python
Excel with Python
Microcomputer with Python
Cast with python
[Practice] Make a Watson app with Python! # 2 [Translation function]
I made a net news notification app with Python
PIL with Python on Windows 8 (for Google App Engine)
Getting Started with Google App Engine for Python & PHP
PyInstaller memorandum Convert Python [.py] to [.exe] with 2 lines
Save screenshot of [Python] [Windows] screen as an image
Serial communication with Python
Zip, unzip with python
Django 1.11 started with Python3.6
Python with eclipse + PyDev.
Socket communication with Python
Data analysis with python 2
Scraping with Python (preparation)
Try scraping with Python.
Learning Python with ChemTHEATER 03
Sequential search with Python
"Object-oriented" learning with python
[Python] Take a screenshot
Handling yaml with python
Solve AtCoder 167 with python
Serial communication with python
[Python] Use JSON with Python
Learning Python with ChemTHEATER 05-1
Learn Python with ChemTHEATER
Run prepDE.py with python3
1.1 Getting Started with Python
Collecting tweets with Python
Binarization with OpenCV / Python
3. 3. AI programming with Python
Kernel Method with Python