import logging
import time
from PyQt5 import QtCore, QtGui
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
import os
from fontTools.ttLib import TTFont
import queue
logging.basicConfig(level=logging.INFO, format='%(asctime)s -line:%(lineno)d - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
comboBoxList = []
class CheckBoxHeader(QHeaderView):
"""自定义表头类"""
# 自定义 复选框全选信号
select_all_clicked = pyqtSignal(bool)
# 这4个变量控制列头复选框的样式,位置以及大小
_x_offset = 5
_y_offset = 100
_width = 20
_height = 20
def __init__(self, orientation=Qt.Horizontal, parent=None):
super(CheckBoxHeader, self).__init__(orientation, parent)
self.isOn = False
def paintSection(self, painter, rect, logicalIndex):
painter.save()
super(CheckBoxHeader, self).paintSection(painter, rect, logicalIndex)
painter.restore()
self._y_offset = int((rect.height() - self._width) / 2.)
if logicalIndex == 0:
option = QStyleOptionButton()
option.rect = QRect(rect.x() + self._x_offset, rect.y() + self._y_offset, self._width, self._height)
option.state = QStyle.State_Enabled | QStyle.State_Active
if self.isOn:
option.state |= QStyle.State_On
else:
option.state |= QStyle.State_Off
self.style().drawControl(QStyle.CE_CheckBox, option, painter)
def mousePressEvent(self, event):
index = self.logicalIndexAt(event.pos())
if 0 == index:
x = self.sectionPosition(index)
if x + self._x_offset < event.pos().x() < x + self._x_offset + self._width and self._y_offset < event.pos().y() < self._y_offset + self._height:
if self.isOn:
self.isOn = False
else:
self.isOn = True
# 当用户点击了行表头复选框,发射 自定义信号 select_all_clicked()
self.select_all_clicked.emit(self.isOn)
self.updateSection(0)
super(CheckBoxHeader, self).mousePressEvent(event)
# 自定义信号 select_all_clicked 的槽方法
def change_state(self, isOn):
# 如果行表头复选框为勾选状态
if isOn:
# 将所有的复选框都设为勾选状态
for i in comboBoxList:
i.setCheckState(Qt.Checked)
else:
for i in comboBoxList:
i.setCheckState(Qt.Unchecked)
# pyqt5 封装线程类
class Job(QtCore.QThread):
signal = pyqtSignal(list)
def run(self):
try:
global save_path
while not file_list_queue.empty():
data = file_list_queue.get()
i, file_path = data[0], data[1] # 索引 文件名 文件的绝对路径
file_name = ''.join(file_path.split('/')[-1].split('.')[0:-1]) # 获取文件名字
if os.path.exists(f'{save_path}/{file_name}.woff'):
# self.signal.emit(['文件索引','文件状态','文件字体颜色'])
self.signal.emit(list([i - 1, '该文件已存在', (17, 238, 204)]))
continue
try:
fnot = TTFont(file_path)
fnot.flavor = 'woff'
# 选择的文件夹 默认当前目录下的woff文件
fnot.save(f'{save_path}/{file_name}.woff')
self.signal.emit(list([i - 1, '完成', (0, 0, 255)]))
except Exception:
self.signal.emit(list([i - 1, '转换错误,请手动转换', (255, 0, 0)]))
# time.sleep(1)
except Exception as e:
print(e)
# def stop(self):
# print("Thread Stopped")
# self.requestInterruption()
# self.wait()
class MainUi(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowIcon(QIcon('./128x128.ico'))
self.setWindowTitle("字体转换器")
self.resize(900, 700)
# 创建网格布局
self.grid = QGridLayout()
self.grid.setSpacing(20)
self.setLayout(self.grid)
########################################################################
self.btn1 = QPushButton('选择字体文件夹')
self.btn1.clicked.connect(self.showTTFDir)
# self.btn1.setIcon(QtGui.QIcon('./128x128.ico'))
self.btn1.setIconSize(QtCore.QSize(25, 25)) # 设置icon大小
self.grid.addWidget(self.btn1, 0, 0)
self.btn2 = QPushButton('选择字体文件')
self.btn2.clicked.connect(self.showTTFs)
# self.btn2.setStyleSheet("QPushButton{font:25px}")
self.grid.addWidget(self.btn2, 0, 1)
self.btn3 = QPushButton('开始\n转换')
# self.btn3 = QPushButton('')
self.btn3.clicked.connect(self.start)
# self.btn3.setStyleSheet("QPushButton{font:100px ;border-image: url(./img/aaa.jfif)}")
self.btn3.setStyleSheet("QPushButton{font:30px}")
# self.btn3.setIcon(QtGui.QIcon('./img/aaa.jfif'))
self.grid.addWidget(self.btn3, 0,2,2,1)
self.btn4 = QPushButton('选择存储位置')
self.btn4.clicked.connect(self.sava_file)
self.grid.addWidget(self.btn4, 1, 0)
#
# self.btn5 = QPushButton('删除选中项')
# self.btn5.setStyleSheet("QPushButton{font:30px}")
#
# self.btn5.clicked.connect(self.del_table)
# self.grid.addWidget(self.btn5, 1, 0,1,2)
# self.pathEdit = QLineEdit()
self.pathEdit = QLabel()
self.pathEdit.setFocusPolicy(QtCore.Qt.NoFocus) # 设置不可编辑
self.grid.addWidget(self.pathEdit, 1, 1)
########################################################################
# 创建表格
self.tableWidget = QTableWidget()
self.tableWidget.setRowCount(0)
self.tableWidget.setColumnCount(3)
self.grid.addWidget(self.tableWidget, 2, 0, 2, 3)
header = CheckBoxHeader() # 实例化自定义表头
self.tableWidget.setHorizontalHeader(header) # 设置表头
self.tableWidget.setHorizontalHeaderLabels(['选择', '文件名', '状态']) # 设置行表头字段
self.tableWidget.setColumnWidth(0, 70)
self.tableWidget.setColumnWidth(1, 500)
self.tableWidget.setColumnWidth(2, 250)
header.select_all_clicked.connect(header.change_state) # 行表头复选框单击信号与槽
self.setLayout(self.grid)
self.show()
def add_table(self, tabeList):
# 遍历所有符合要求的数据
for filaPath in tabeList:
fileName = filaPath.split('/')[-1]
status = '待转换'
if fileName == '':
continue
if fileName[-3:] != 'ttf' and fileName[-3:] != 'otf' and fileName[-3:] != 'OTF' and fileName[-3:] != 'TTF':
continue
logger.info(fileName)
# 获取表格有多少行 添加到最后 添加到表格中
row_count = self.tableWidget.rowCount()
self.tableWidget.setRowCount(row_count + 1) # 添加一行
row_count = self.tableWidget.rowCount()
if row_count == 1:
row_count = 0
else:
row_count -= 1
# row_count = self.tableWidget.rowCount()
# 添加单选框 添加文件名 状态 居中
checkBox = QCheckBox()
comboBoxList.append(checkBox)
checkBox.setChecked(False)
checkBox.setStyleSheet('QCheckBox{margin:20px}')
self.tableWidget.setCellWidget(row_count, 0, checkBox)
new_item = QTableWidgetItem(filaPath)
self.tableWidget.setItem(row_count, 1, new_item)
new_item.setTextAlignment(Qt.AlignCenter | Qt.AlignBottom)
new_item = QTableWidgetItem(status)
self.tableWidget.setItem(row_count, 2, new_item)
new_item.setForeground(QBrush(QColor(255, 0, 0)))
new_item.setTextAlignment(Qt.AlignCenter | Qt.AlignBottom)
def sava_file(self):
global save_path
save_path = QFileDialog.getExistingDirectory(self, 'Open file', '.')
if save_path == '':
self.pathEdit.setText('<font color="red">请选择字体文件储存位置</font>')
return
self.pathEdit.setText(save_path)
def showTTFDir(self):
# 每次刷新
fList = []
dirPath = QFileDialog.getExistingDirectory(self, 'Open file', '.')
logger.info(dirPath)
if dirPath == '':
return
files = os.listdir(dirPath)
for f in files:
if f[-3:] == 'ttf' or f[-3:] == 'otf' or f[-3:] == 'OTF' or f[-3:] == 'TTF':
fList.append(dirPath + '/' + f)
logger.info(f'共{len(fList)}个字体文件')
self.add_table(fList)
def showTTFs(self):
fname_path = QFileDialog.getOpenFileNames(self, 'Open file', '.')[0]
self.add_table(fname_path)
def check_box_attr(self):
global comboBoxList
table_index = []
for i, box in enumerate(comboBoxList):
if box.isChecked() == True and box.isEnabled() == True:
table_index.append(i + 1)
return table_index
def set_table(self, pram):
'''
:param pram: 信号传递的数据 添加到表格中
:return:
'''
index, status, color = pram[0], pram[1], pram[2]
new_item = QTableWidgetItem(status) # 添加状态列
new_item.setForeground(QBrush(QColor(*color))) # 修改颜色
new_item.setTextAlignment(Qt.AlignCenter | Qt.AlignBottom)
new_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
self.tableWidget.setItem(index, 2, new_item) # 添加到表格中
# comboBoxList[index].setEnabled(False)
def start(self):
global save_path
try:
if not os.path.exists(save_path):
os.mkdir(save_path)
except Exception as e:
self.pathEdit.setText('<font color="red">请选择字体文件储存位置</font>')
return
table_index_list = self.check_box_attr()
# #开始时添加任务 遍历列表 添加任务
for row in table_index_list:
file_path = self.tableWidget.item(row - 1, 1).text()
file_list_queue.put([row, file_path])
self.t1 = Job()
self.t1.signal.connect(self.set_table)
self.t1.start()
self.t2 = Job()
self.t2.signal.connect(self.set_table)
self.t2.start()
self.t3 = Job()
self.t3.signal.connect(self.set_table)
self.t3.start()
self.t4 = Job()
self.t4.signal.connect(self.set_table)
self.t4.start()
def main():
app = QApplication(sys.argv)
gui = MainUi()
gui.show()
sys.exit(app.exec_())
if __name__ == "__main__":
file_list_queue = queue.Queue()
qmut = QMutex()
main()
pyqt5 otf2woff和ttf2woff界面及代码
最新推荐文章于 2025-09-12 00:31:31 发布
650

被折叠的 条评论
为什么被折叠?



