现代操作系统比如Win10, Mac都自带了很好用的照片浏览器,采用人像识别技术自动识别家庭成员,还有简单的画面增强功能。然而这些功能都是需要连接云端服务器来实现的。虽然说很难说这些大公司会对你的那些照片感兴趣,但就怕万一呢。这些功能只能说锦上添花,并不是必须的。那我们用Python做一个简单的照片浏览器就好了。
PyQt5已经是一个很成熟的产品,全部功能实现只用了82行,太容易了。
import sys
import os
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPixmap, QImage, QIcon
from PyQt5.QtCore import Qt, QSize, QRect
def list_files(folder):
files = []
filenames = []
for f in os.listdir(folder):
files.append(os.path.join(folder, f))
filenames.append(f)
return files, filenames
class MyApp(QWidget):
folder = ''
def __init__(self, folder, parent=None):
super(MyApp, self).__init__(parent)
self.folder = folder
self.sp = None
layout = QVBoxLayout()
listView = QTableWidget()
listView.setIconSize(QSize(300, 300))
listView.horizontalHeader().setVisible(False)
listView.verticalHeader().setVisible(False)
listView.setShowGrid(False)
listView.setColumnCount(5)
listView.itemDoubleClicked.connect(self.show_pic)
self.add_picture(listView)
layout.addWidget(listView)
self.setLayout(layout)
self.resize(1500, 800)
self.setWindowTitle(folder)
def add_picture(self, listView):
files, names = list_files(self.folder)
listView.setRowCount(len(files) / 5)
for i, file in enumerate(files):
item = QTableWidgetItem()
item.setFlags(Qt.ItemIsEnabled)
icon = QIcon()
qimg = QImage(file)
icon.addPixmap(QPixmap.fromImage(qimg), QIcon.Normal, QIcon.Off)
item.setIcon(icon)
item.setText(names[i])
listView.setRowHeight(i / 5, 300)
listView.setColumnWidth(i % 5, 300)
listView.setItem(i / 5, i % 5, item)
def show_pic(self, item):
path = item.text()
self.sp = Single_Pic(os.path.join(self.folder, path))
self.sp.setGeometry(QRect(self.x(), self.y(), self.sp.width(), self.sp.height()))
self.sp.show()
class Single_Pic(QWidget):
def __init__(self, path):
super().__init__()
self.path = path
self.initUI()
def initUI(self):
label = QLabel(self)
qimg = QImage(self.path)
label.resize(qimg.width() / qimg.height() * 800, 800)
self.resize(label.width(), label.height())
label.setPixmap(QPixmap.fromImage(qimg).scaled(label.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
if __name__ == '__main__':
app = QApplication(sys.argv)
t = MyApp(sys.argv[1])
www.8.show()
sys.exit(app.exec_())
首先我们需要在main里创建QApplication, 然后显示MyApp 这个我们自定义的主窗口。Qt标准控件并没有Gallary这样的专门用来做图片展示的控件,但我们可以用QtableWidget来模拟实现多行5列的效果。每个单元格的数据来自QTableWidgetItem这个类,它自带Icon, text属性,这基本就满足了我们的需求。在list_files方法里拿到了所有的图片文件名和路径名,QImage可以直接读取图片路径名(注意是完整路径)来生成,然后做为Icon放在QtableWidgetItem里。QTableWidget需要横纵坐标来添加Item, 因为我们要显示5列,变量i 是当前图片的索引, i/5 和 i%5 就可以做为横纵坐标转入。
双击图片放大显示完整图片是通过itemDoubleClicked.connect 调用show_pic方法来实现的。 在show_pic方法里,为了做到图片显示不变形,我们就需要使用QPixmap的scaled, KeepAspectRatio参数来保持横纵比。同时QLabel的大小也是固定高度为800像素后,用公式算出需要的宽度。公式很简单,但细节很重要,不然上下就会出现不必要的空白。虽然是自己用的,但专业的程序员怎么会忍受这样明显的毛病呢。