[M1 Mac, Big Sur 11.6.5, Python 3.10.0]
前回のコードにボタン動作を追加しPyQt6アプリを完成させました。icnsファイル作成箇所はクラスファイルとして別にしました。このアプリではドラッグ&ドロップでファイルパスを取得することもできます。
appファイルにすると260MBの巨大サイズになりました。さくっと作れますがやはりファイルの大きさが問題です。
アプリはとりあえず自サイトにアップしました。ここからC++の本家Qtに移植の予定です。
PyQt6はこれまで見てきたウィジェットツールキットの中では最も扱いやすかったです。並べると、PyQt6 > Swing >>> Tkinter >>FLTK といったところでしょうか。上位2つは企業開発であり、商品としてそれなりに洗練されているということでしょう。
FLTKは外観・文法・ウィジェットの名称など、クセが強すぎて開発意欲が低いままです。ラジオボタンがFl_Round_Button、ラベルがFl_Boxなどなどネーミングがピンとこなくて困っています。
2022/03/25追記
pngからjpgに変換しなくても解像度を上げられましたので後日コードをアップします。
import sys
from PyQt6.QtWidgets import QLabel,QWidget,QApplication,QTextEdit,QLineEdit,QPushButton,QButtonGroup,QRadioButton
from PyQt6.QtCore import Qt
from pathlib import Path
from PIL import Image
import makeIcns
class ImageInspector(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("IMAGE INSPECTOR")
self.setGeometry(100,100,360,220)
self.setStyleSheet('background-color: #708090')
self.setAcceptDrops(True)
file = QLabel('File',self)
file.setGeometry(15,15,26,16)
file.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.input= QLineEdit('',self)
self.input.setGeometry(50,10,220,25)
self.input.setAcceptDrops(True)
execution = QPushButton('実行',self)
execution.setGeometry(290,10,50,30)
execution.released.connect(self.execute)
clear = QPushButton('クリア',self)
clear.setGeometry(290,50,50,30)
clear.released.connect(self.clear)
self.rbtns = QButtonGroup()
self.inspect = QRadioButton("Inspect",self)
self.inspect.setGeometry(50,40,90,20)
self.inspect.setChecked(True)
self.rbtns.addButton(self.inspect)
self.resize_img = QRadioButton("Resize",self)
self.resize_img.setGeometry(50,65,90,20)
self.rbtns.addButton(self.resize_img)
width_label = QLabel('W',self)
width_label.setGeometry(135,70,15,10)
width_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
width_label.setStyleSheet('font-size:10px')
self.width = QLineEdit('',self)
self.width.setGeometry(155,65,45,20)
height_label = QLabel('H',self)
height_label.setGeometry(205,70,15,10)
height_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
height_label.setStyleSheet('font-size:10px')
self.height = QLineEdit('',self)
self.height.setGeometry(220,65,45,20)
self.icns = QRadioButton("icns作成",self)
self.icns.setGeometry(50,90,90,20)
self.icns.setToolTip('PNG file[2048*2048,72px] required')
self.rbtns.addButton(self.icns)
self.output = QTextEdit('',self)
self.output.setGeometry(50,115,240,100)
self.output.setAcceptDrops(False)
def dragEnterEvent(self, e):
if(e.mimeData().hasUrls()):
e.accept()
def dropEvent(self, e):
urls = e.mimeData().urls()
path = Path(urls[0].toLocalFile())
print(f"Drop_path {path}")
self.input.setText(str(path))
def execute(self):
image_path = self.input.text()
print(f"Exe_path {image_path}")
img = Image.open(image_path)
if self.inspect.isChecked():
self.output.append("Size " + str(img.size) + "\n"+ "dpi " + str(img.info.get('dpi')))
elif self.resize_img.isChecked():
width = int(self.width.text())
height = int(self.height.text())
resize_img= img.resize((width,height))
resize_img_path = ".".join(self.input.text().split(".")[:-1]) + "_resized." + (self.input.text()).split(".")[-1]
print(f"Resize_path {resize_img_path}")
resize_img.save(resize_img_path)
else: # icns作成
makeIcns.MakeIcns.make(None,image_path,self)
def clear(self):
self.input.clear()
from PIL import Image
import subprocess, os
from PyQt6.QtWidgets import QDialog,QPushButton,QLabel
from PyQt6.QtCore import Qt
class MakeIcns():
def make(self, filepath0, window):
img = Image.open(filepath0)
print(str(img.size))
if str(img.size)=="(2048, 2048)": # 2048*2048
filepath0_jpg = ".".join(filepath0.split(".")[:-1]) + ".jpg" # 1024*1024 dpi=144
filepath = ".".join(filepath0.split(".")[:-1]) + "1.png" # 1024*1024 dpi=144
filepath2 = ".".join(filepath0.split(".")[:-1]) + "2.png" # 512*512 dpi=72
filedir = "/".join(filepath0.split("/")[:-1]) + "/" + (filepath0.split("/")[-1]).split(".")[-2] + ".iconset/"
print(f"filepath0_jpg {filepath0_jpg}")
print(f"filepath {filepath}")
print(f"filepath2 {filepath2}")
print(f"filedir {filedir}")
os.mkdir(filedir)
img1 = Image.open(filepath0).convert("RGB")
# 512*512 dpi=72
img1_resize = img1.resize((512,512))
img1_resize.save(filepath2)
# dpi=144にするため一旦jpgへ変換
img1_resize2 = img1.resize((1024,1024))
img1_resize2.save(filepath0_jpg,dpi=(144,144))
# jpgをpngへ変換
img3 = Image.open(filepath0_jpg).convert("RGBA")
img3.save(filepath,dpi=(144,144))
pixels = [32, 64, 256, 512, 1024]
pixels2 = [16, 32, 128, 256, 512]
filepaths = ['icon_16x16@2x.png','icon_32x32@2x.png','icon_128x128@2x.png','icon_256x256@2x.png','icon_512x512@2x.png']
filepaths2 = ['icon_16x16.png','icon_32x32.png','icon_128x128.png','icon_256x256.png','icon_512x512.png']
# dpi=144の各種pngファイル作成
for pixel,file in zip(pixels,filepaths):
img = Image.open(filepath)
img_resize = img.resize((pixel,pixel))
img_resize.save(filedir + file)
img.close()
# dpi=72の各種pngファイル作成
for pixel,file in zip(pixels2,filepaths2):
img = Image.open(filepath2)
img_resize = img.resize((pixel,pixel))
img_resize.save(filedir + file)
img.close()
# icnsファイル作成
dir = "/".join(filepath0.split("/")[:-1])
iconset = (filepath0.split("/")[-1]).split(".")[-2] + ".iconset"
cmd = f'iconutil -c icns {iconset}'
subprocess.run(cmd, cwd=dir,shell=True)
os.remove(filepath0_jpg)
os.remove(filepath)
os.remove(filepath2)
else:
MakeIcns.showDialog(self,window)
def showDialog(self,window):
dlg = QDialog(window)
dlg.setFixedSize(250,100)
label = QLabel('This file is invalid.\nPNG file[2048*2048,72dpi] required',dlg)
label.setAlignment(Qt.AlignmentFlag.AlignCenter)
label.move(15,20)
label.setStyleSheet('font-size:14px')
btn = QPushButton("OK",dlg)
btn.move(90,60)
def action():
dlg.close()
btn.released.connect(action)
dlg.setWindowTitle("Attention")
dlg.exec()