mirror of
https://github.com/LC044/WeChatMsg
synced 2024-11-14 05:21:41 +08:00
导出word文档
This commit is contained in:
parent
885ef1c5a1
commit
78eb89aa38
390
app/DataBase/output.py
Normal file
390
app/DataBase/output.py
Normal file
@ -0,0 +1,390 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
import docx
|
||||||
|
import pandas as pd
|
||||||
|
import requests
|
||||||
|
import xmltodict
|
||||||
|
from docx import shared
|
||||||
|
from docx.enum.table import WD_ALIGN_VERTICAL
|
||||||
|
from docx.enum.text import WD_COLOR_INDEX, WD_PARAGRAPH_ALIGNMENT
|
||||||
|
from docxcompose.composer import Composer
|
||||||
|
from PyQt5.QtWidgets import *
|
||||||
|
from PyQt5.QtCore import *
|
||||||
|
from PyQt5.QtGui import *
|
||||||
|
from . import data
|
||||||
|
|
||||||
|
|
||||||
|
def IS_5_min(last_m, now_m):
|
||||||
|
'''
|
||||||
|
#! 判断两次聊天时间是不是大于五分钟
|
||||||
|
#! 若大于五分钟则显示时间
|
||||||
|
#! 否则不显示
|
||||||
|
'''
|
||||||
|
'''两次聊天记录时间差,单位是秒'''
|
||||||
|
dt = now_m - last_m
|
||||||
|
return abs(dt // 1000) >= 300
|
||||||
|
|
||||||
|
|
||||||
|
def time_format(timestamp):
|
||||||
|
'''
|
||||||
|
#! 将字符串类型的时间戳转换成日期
|
||||||
|
#! 返回格式化的时间字符串
|
||||||
|
#! %Y-%m-%d %H:%M:%S
|
||||||
|
'''
|
||||||
|
timestamp = timestamp / 1000
|
||||||
|
time_tuple = time.localtime(timestamp)
|
||||||
|
return time.strftime("%Y-%m-%d %H:%M:%S", time_tuple)
|
||||||
|
|
||||||
|
|
||||||
|
def merge_docx(conRemark, n):
|
||||||
|
origin_docx_path = f"{path}/{conRemark}"
|
||||||
|
all_word = os.listdir(origin_docx_path)
|
||||||
|
all_file_path = []
|
||||||
|
for i in range(n):
|
||||||
|
file_name = f"{conRemark}{i}.docx"
|
||||||
|
all_file_path.append(origin_docx_path + '/' + file_name)
|
||||||
|
filename = f"{conRemark}.docx"
|
||||||
|
# print(all_file_path)
|
||||||
|
doc = docx.Document()
|
||||||
|
doc.save(origin_docx_path + '/' + filename)
|
||||||
|
master = docx.Document(origin_docx_path + '/' + filename)
|
||||||
|
middle_new_docx = Composer(master)
|
||||||
|
num = 0
|
||||||
|
for word in all_file_path:
|
||||||
|
word_document = docx.Document(word)
|
||||||
|
word_document.add_page_break()
|
||||||
|
if num != 0:
|
||||||
|
middle_new_docx.append(word_document)
|
||||||
|
num = num + 1
|
||||||
|
middle_new_docx.save(origin_docx_path + '/' + filename)
|
||||||
|
|
||||||
|
|
||||||
|
class Output(QThread):
|
||||||
|
"""
|
||||||
|
发送信息线程
|
||||||
|
"""
|
||||||
|
progressSignal = pyqtSignal(int)
|
||||||
|
successSignal = pyqtSignal(int)
|
||||||
|
|
||||||
|
def __init__(self, Me, ta_u, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.Me = Me
|
||||||
|
self.sec = 2 # 默认1000秒
|
||||||
|
self.ta_username = ta_u
|
||||||
|
self.my_avatar = self.Me.my_avatar
|
||||||
|
self.ta_avatar = data.get_avator(ta_u)
|
||||||
|
self.msg_id = 0
|
||||||
|
|
||||||
|
def create_table(self, doc, isSend):
|
||||||
|
'''
|
||||||
|
#! 创建一个1*2表格
|
||||||
|
#! isSend = 1 (0,0)存聊天内容,(0,1)存头像
|
||||||
|
#! isSend = 0 (0,0)存头像,(0,1)存聊天内容
|
||||||
|
#! 返回聊天内容的坐标
|
||||||
|
'''
|
||||||
|
table = doc.add_table(rows=1, cols=2, style='Normal Table')
|
||||||
|
table.cell(0, 1).height = shared.Inches(0.5)
|
||||||
|
table.cell(0, 0).height = shared.Inches(0.5)
|
||||||
|
text_size = 1
|
||||||
|
if isSend:
|
||||||
|
'''表格右对齐'''
|
||||||
|
table.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
|
||||||
|
avatar = table.cell(0, 1).paragraphs[0].add_run()
|
||||||
|
'''插入头像,设置头像宽度'''
|
||||||
|
avatar.add_picture(self.my_avatar, width=shared.Inches(0.5))
|
||||||
|
'''设置单元格宽度跟头像一致'''
|
||||||
|
table.cell(0, 1).width = shared.Inches(0.5)
|
||||||
|
content_cell = table.cell(0, 0)
|
||||||
|
'''聊天内容右对齐'''
|
||||||
|
content_cell.paragraphs[0].paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
|
||||||
|
else:
|
||||||
|
avatar = table.cell(0, 0).paragraphs[0].add_run()
|
||||||
|
avatar.add_picture(self.ta_avatar, width=shared.Inches(0.5))
|
||||||
|
'''设置单元格宽度'''
|
||||||
|
table.cell(0, 0).width = shared.Inches(0.5)
|
||||||
|
content_cell = table.cell(0, 1)
|
||||||
|
'''聊天内容垂直居中对齐'''
|
||||||
|
content_cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
|
||||||
|
return content_cell
|
||||||
|
|
||||||
|
def text(self, doc, isSend, message, status):
|
||||||
|
if status == 5:
|
||||||
|
message += '(未发出) '
|
||||||
|
content_cell = self.create_table(doc, isSend)
|
||||||
|
content_cell.paragraphs[0].add_run(message)
|
||||||
|
content_cell.paragraphs[0].font_size = shared.Inches(0.5)
|
||||||
|
# self.self_text.emit(message)
|
||||||
|
if isSend:
|
||||||
|
p = content_cell.paragraphs[0]
|
||||||
|
p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
|
||||||
|
doc.add_paragraph()
|
||||||
|
|
||||||
|
def image(self, doc, isSend, Type, content, imgPath):
|
||||||
|
'''
|
||||||
|
#! 插入聊天图片
|
||||||
|
#! isSend = 1 只有缩略图
|
||||||
|
#! isSend = 0 有原图
|
||||||
|
:param doc:
|
||||||
|
:param isSend:
|
||||||
|
:param Type:
|
||||||
|
:param content:
|
||||||
|
:param imgPath:
|
||||||
|
:return:
|
||||||
|
'''
|
||||||
|
content = self.create_table(doc, isSend)
|
||||||
|
run = content.paragraphs[0].add_run()
|
||||||
|
if Type == 3:
|
||||||
|
imgPath = imgPath.split('th_')[1]
|
||||||
|
imgPath = f'./app/data/image2/{imgPath[0:2]}/{imgPath[2:4]}/th_{imgPath}'
|
||||||
|
imgPath = data.clearImagePath(imgPath)
|
||||||
|
try:
|
||||||
|
run.add_picture(f'{imgPath}', height=shared.Inches(2))
|
||||||
|
doc.add_paragraph()
|
||||||
|
except Exception:
|
||||||
|
print("Error!image")
|
||||||
|
|
||||||
|
# run.add_picture(f'{Path}/{imgPath}', height=shared.Inches(2))
|
||||||
|
|
||||||
|
def emoji(self, doc, isSend, content, imgPath):
|
||||||
|
'''
|
||||||
|
#! 添加表情包
|
||||||
|
:param isSend:
|
||||||
|
:param content:
|
||||||
|
:param imgPath:
|
||||||
|
:return:
|
||||||
|
'''
|
||||||
|
imgPath = data.get_emoji(imgPath)
|
||||||
|
if 1:
|
||||||
|
is_Exist = os.path.exists(imgPath)
|
||||||
|
self.image(doc, isSend, Type=47, content=content, imgPath=imgPath)
|
||||||
|
|
||||||
|
def wx_file(self, doc, isSend, content, status):
|
||||||
|
'''
|
||||||
|
#! 添加微信文件
|
||||||
|
:param isSend:
|
||||||
|
:param content:
|
||||||
|
:param status:
|
||||||
|
:return:
|
||||||
|
'''
|
||||||
|
pattern = re.compile(r"<title>(.*?)<")
|
||||||
|
r = pattern.search(content).group()
|
||||||
|
filename = r.lstrip('<title>').rstrip('<')
|
||||||
|
self.text(doc, isSend, filename, status)
|
||||||
|
|
||||||
|
def retract_message(self, doc, isSend, content, status):
|
||||||
|
'''
|
||||||
|
#! 显示撤回消息
|
||||||
|
:param isSend:
|
||||||
|
:param content:
|
||||||
|
:param status:
|
||||||
|
:return:
|
||||||
|
'''
|
||||||
|
paragraph = doc.add_paragraph(content)
|
||||||
|
paragraph.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
||||||
|
|
||||||
|
def reply(self, doc, isSend, content, status):
|
||||||
|
'''
|
||||||
|
#! 添加回复信息
|
||||||
|
:param isSend:
|
||||||
|
:param content:
|
||||||
|
:param status:
|
||||||
|
:return:
|
||||||
|
'''
|
||||||
|
pattern1 = re.compile(r"<title>(?P<title>(.*?))</title>")
|
||||||
|
title = pattern1.search(content).groupdict()['title']
|
||||||
|
pattern2 = re.compile(r"<displayname>(?P<displayname>(.*?))</displayname>")
|
||||||
|
displayname = pattern2.search(content).groupdict()['displayname']
|
||||||
|
'''匹配回复的回复'''
|
||||||
|
pattern3 = re.compile(r"\n?title>(?P<content>(.*?))\n?</title>")
|
||||||
|
if not pattern3.search(content):
|
||||||
|
if isSend == 0:
|
||||||
|
'''匹配对方的回复'''
|
||||||
|
pattern3 = re.compile(r"<content>(?P<content>(.*?))</content>")
|
||||||
|
else:
|
||||||
|
'''匹配自己的回复'''
|
||||||
|
pattern3 = re.compile(r"</msgsource>\n?<content>(?P<content>(.*?))\n?</content>")
|
||||||
|
|
||||||
|
'''这部分代码完全可以用if代替'''
|
||||||
|
|
||||||
|
try:
|
||||||
|
'''试错'''
|
||||||
|
text = pattern3.search(content).groupdict()['content']
|
||||||
|
except Exception:
|
||||||
|
try:
|
||||||
|
'''试错'''
|
||||||
|
text = pattern3.search(content).groupdict()['content']
|
||||||
|
except Exception:
|
||||||
|
'''试错'''
|
||||||
|
pattern3 = re.compile(r"\n?<content>(?P<content>(.*?))\n?</content>")
|
||||||
|
'''试错'''
|
||||||
|
if pattern3.search(content):
|
||||||
|
text = pattern3.search(content).groupdict()['content']
|
||||||
|
else:
|
||||||
|
text = '图片'
|
||||||
|
if status == 5:
|
||||||
|
message = '(未发出) ' + ''
|
||||||
|
content_cell = self.create_table(doc, isSend)
|
||||||
|
content_cell.paragraphs[0].add_run(title)
|
||||||
|
content_cell.paragraphs[0].font_size = shared.Inches(0.5)
|
||||||
|
reply_p = content_cell.add_paragraph()
|
||||||
|
run = content_cell.paragraphs[1].add_run(displayname + ':' + text)
|
||||||
|
'''设置被回复内容格式'''
|
||||||
|
run.font.color.rgb = shared.RGBColor(121, 121, 121)
|
||||||
|
run.font_size = shared.Inches(0.3)
|
||||||
|
run.font.highlight_color = WD_COLOR_INDEX.GRAY_25
|
||||||
|
|
||||||
|
if isSend:
|
||||||
|
p = content_cell.paragraphs[0]
|
||||||
|
p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
|
||||||
|
reply_p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
|
||||||
|
doc.add_paragraph()
|
||||||
|
|
||||||
|
def pat_a_pat(self, doc, isSend, content, status):
|
||||||
|
'''
|
||||||
|
#! 添加拍一拍信息
|
||||||
|
todo 把wxid转化成昵称
|
||||||
|
:param isSend:
|
||||||
|
:param content:
|
||||||
|
:param status:
|
||||||
|
:return:
|
||||||
|
'''
|
||||||
|
pat_data = xmltodict.parse(content)
|
||||||
|
pat_data = pat_data['msg']['appmsg']['patMsg']['records']['record']
|
||||||
|
fromUser = pat_data['fromUser']
|
||||||
|
pattedUser = pat_data['pattedUser']
|
||||||
|
template = pat_data['template']
|
||||||
|
template = ''.join(template.split('${pattedusername@textstatusicon}'))
|
||||||
|
template = ''.join(template.split('${fromusername@textstatusicon}'))
|
||||||
|
template = template.replace(f'${{{fromUser}}}', data.get_conRemark(fromUser))
|
||||||
|
template = template.replace(f'${{{pattedUser}}}', data.get_conRemark(pattedUser))
|
||||||
|
print(template)
|
||||||
|
p = doc.add_paragraph()
|
||||||
|
run = p.add_run(template)
|
||||||
|
p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
||||||
|
'''设置拍一拍文字格式'''
|
||||||
|
run.font.color.rgb = shared.RGBColor(121, 121, 121)
|
||||||
|
run.font_size = shared.Inches(0.3)
|
||||||
|
# run.font.highlight_color=WD_COLOR_INDEX.GRAY_25
|
||||||
|
|
||||||
|
def video(self, doc, isSend, content, status, img_path):
|
||||||
|
print(content, img_path)
|
||||||
|
|
||||||
|
def to_docx(self, messages, i, conRemark):
|
||||||
|
'''创建联系人目录'''
|
||||||
|
data.mkdir(f"{os.path.abspath('.')}/data/聊天记录/{conRemark}")
|
||||||
|
filename = f"{os.path.abspath('.')}/data/聊天记录/{conRemark}/{conRemark}{i}.docx"
|
||||||
|
doc = docx.Document()
|
||||||
|
last_timestamp = 1601968667000
|
||||||
|
for message in messages:
|
||||||
|
msgId = message[0]
|
||||||
|
ta_username = message[7]
|
||||||
|
Type = int(message[2])
|
||||||
|
isSend = message[4]
|
||||||
|
content = message[8]
|
||||||
|
imgPath = message[9]
|
||||||
|
now_timestamp = message[6]
|
||||||
|
status = message[3]
|
||||||
|
createTime = time_format(now_timestamp)
|
||||||
|
# print(createTime, isSend, content)
|
||||||
|
if IS_5_min(last_timestamp, now_timestamp):
|
||||||
|
doc.add_paragraph(createTime).alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
||||||
|
last_timestamp = now_timestamp
|
||||||
|
if Type == 1:
|
||||||
|
try:
|
||||||
|
self.text(doc, isSend, content, status)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
elif Type == 3:
|
||||||
|
self.image(doc, isSend, 3, content, imgPath)
|
||||||
|
elif Type == 47:
|
||||||
|
self.emoji(doc, isSend, content, imgPath)
|
||||||
|
elif Type == 1090519089:
|
||||||
|
self.wx_file(doc, isSend, content, status)
|
||||||
|
elif Type == 268445456:
|
||||||
|
self.retract_message(doc, isSend, content, status)
|
||||||
|
elif Type == 822083633:
|
||||||
|
self.reply(doc, isSend, content, status)
|
||||||
|
elif Type == 922746929:
|
||||||
|
self.pat_a_pat(doc, isSend, content, status)
|
||||||
|
elif Type == 43:
|
||||||
|
# print(createTime)
|
||||||
|
self.video(doc, isSend, content, status, imgPath)
|
||||||
|
# doc.add_paragraph(str(i))
|
||||||
|
print(filename)
|
||||||
|
doc.save(filename)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if 1:
|
||||||
|
conRemark = data.get_conRemark(self.ta_username)
|
||||||
|
messages = data.get_all_message(self.ta_username)
|
||||||
|
# self.self_text.emit(conRemark)
|
||||||
|
# self.self_text.emit(path)
|
||||||
|
self.to_docx(messages, 0, conRemark)
|
||||||
|
# l = len(user_data)
|
||||||
|
# n = 50
|
||||||
|
# for i in range(n):
|
||||||
|
# q = i * (l // n)
|
||||||
|
# p = (i + 1) * (l // n)
|
||||||
|
# if i == n - 1:
|
||||||
|
# p = l
|
||||||
|
# len_data = user_data[q:p]
|
||||||
|
# self.to_docx(len_data, i, conRemark)
|
||||||
|
|
||||||
|
# self.self_text.emit('\n\n\n导出进度还差一点点!!!')
|
||||||
|
# self.bar.emit(99)
|
||||||
|
# merge_docx(conRemark, n)
|
||||||
|
# self.self_text.emit(f'{conRemark}聊天记录导出成功!!!')
|
||||||
|
# self.bar.emit(100)
|
||||||
|
|
||||||
|
# def run(self):
|
||||||
|
# self.ta_avatar = data.get_avator(self.ta_u)
|
||||||
|
# messages = data.get_all_message(self.ta_u)
|
||||||
|
# total_num = len(messages)
|
||||||
|
# for message in messages:
|
||||||
|
# msgId = message[0]
|
||||||
|
# ta_username = message[7]
|
||||||
|
# msgType = str(message[2])
|
||||||
|
# isSend = message[4]
|
||||||
|
# content = message[8]
|
||||||
|
# imgPath = message[9]
|
||||||
|
# msg_time = message[6]
|
||||||
|
# self.check_time(msg_time)
|
||||||
|
#
|
||||||
|
# if msgType == '1':
|
||||||
|
# # return
|
||||||
|
# self.show_text(isSend, content)
|
||||||
|
# elif msgType == '3':
|
||||||
|
# # return
|
||||||
|
# self.show_img(isSend, imgPath, content)
|
||||||
|
# elif msgType == '47':
|
||||||
|
# # return
|
||||||
|
# self.show_emoji(isSend, imgPath, content)
|
||||||
|
# elif msgType == '268445456':
|
||||||
|
# self.show_recall_information(content)
|
||||||
|
# elif msgType == '922746929':
|
||||||
|
# self.pat_a_pat(content)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# # conRemark = '张三' #! 微信备注名
|
||||||
|
# n = 100 # ! 分割的文件个数
|
||||||
|
# main(conRemark, n)
|
||||||
|
# img_self.close()
|
||||||
|
# img_ta.close()
|
||||||
|
me = data.Me('wxid_27hqbq7vx5hf22')
|
||||||
|
t = Output(Me=me, ta_u='wxid_q3ozn70pweud22')
|
||||||
|
# t.ta_info = {
|
||||||
|
# 'wxid': 'wxid_q3ozn70pweud22',
|
||||||
|
# 'conRemark': '小钱'
|
||||||
|
# }
|
||||||
|
# t.ta_info = {
|
||||||
|
# 'wxid': 'wxid_8piw6sb4hvfm22',
|
||||||
|
# 'conRemark': '曹雨萱'
|
||||||
|
# }
|
||||||
|
# # wxid_8piw6sb4hvfm22
|
||||||
|
# t.self_info = {
|
||||||
|
# 'wxid': 'wxid_27hqbq7vx5hf22',
|
||||||
|
# 'conRemark': 'Shuaikang Zhou'
|
||||||
|
# }
|
||||||
|
t.run()
|
0
app/ImageBox/__init__.py
Normal file
0
app/ImageBox/__init__.py
Normal file
6
app/ImageBox/config.py
Normal file
6
app/ImageBox/config.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import sys
|
||||||
|
from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QFileDialog
|
||||||
|
from PyQt5.Qt import QPixmap, QPoint, Qt, QPainter, QIcon
|
||||||
|
from PyQt5.QtCore import QSize
|
||||||
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
|
from PyQt5.QtGui import QImageReader
|
BIN
app/ImageBox/icons/zoom_in.jpg
Normal file
BIN
app/ImageBox/icons/zoom_in.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
BIN
app/ImageBox/icons/zoom_out.jpg
Normal file
BIN
app/ImageBox/icons/zoom_out.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
BIN
app/ImageBox/images/wallhaven-748705.jpg
Normal file
BIN
app/ImageBox/images/wallhaven-748705.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 543 KiB |
BIN
app/ImageBox/images/wallhaven-753155.jpg
Normal file
BIN
app/ImageBox/images/wallhaven-753155.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 678 KiB |
BIN
app/ImageBox/images/wallhaven-vml6em.jpg
Normal file
BIN
app/ImageBox/images/wallhaven-vml6em.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 405 KiB |
9
app/ImageBox/run.py
Normal file
9
app/ImageBox/run.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from ui import MainDemo
|
||||||
|
from config import *
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
box = MainDemo()
|
||||||
|
box.show()
|
||||||
|
app.exec_()
|
157
app/ImageBox/ui.py
Normal file
157
app/ImageBox/ui.py
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from .config import *
|
||||||
|
|
||||||
|
|
||||||
|
class ImageBox(QWidget):
|
||||||
|
def __init__(self):
|
||||||
|
super(ImageBox, self).__init__()
|
||||||
|
self.img = None
|
||||||
|
self.scaled_img = None
|
||||||
|
self.point = QPoint(100, 100)
|
||||||
|
self.start_pos = None
|
||||||
|
self.end_pos = None
|
||||||
|
self.left_click = False
|
||||||
|
self.scale = 1
|
||||||
|
|
||||||
|
def init_ui(self):
|
||||||
|
self.setWindowTitle("ImageBox")
|
||||||
|
|
||||||
|
def set_image(self, img_path):
|
||||||
|
"""
|
||||||
|
open image file
|
||||||
|
:param img_path: image file path
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
# img = QImageReader(img_path)
|
||||||
|
# img.setScaledSize(QSize(self.size().width(), self.size().height()))
|
||||||
|
# img = img.read()
|
||||||
|
self.img = QPixmap(img_path)
|
||||||
|
# print(self.img.size(),self.img.size().width(),self.img.size().height())
|
||||||
|
self.scaled_img = self.img
|
||||||
|
# print(img_size)
|
||||||
|
img_size = self.scaled_img.size()
|
||||||
|
x = min(500, max((1000 - img_size.width()) // 2, 0))
|
||||||
|
y = min(300, max((600 - img_size.height()) // 2-60, 0))
|
||||||
|
# print(x,y)
|
||||||
|
self.point = QPoint(x, y)
|
||||||
|
|
||||||
|
def paintEvent(self, e):
|
||||||
|
"""
|
||||||
|
receive paint events
|
||||||
|
:param e: QPaintEvent
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if self.scaled_img:
|
||||||
|
painter = QPainter()
|
||||||
|
painter.begin(self)
|
||||||
|
painter.scale(self.scale, self.scale)
|
||||||
|
painter.drawPixmap(self.point, self.scaled_img)
|
||||||
|
painter.end()
|
||||||
|
|
||||||
|
def wheelEvent(self, event):
|
||||||
|
angle = event.angleDelta() / 8 # 返回QPoint对象,为滚轮转过的数值,单位为1/8度
|
||||||
|
angleY = angle.y()
|
||||||
|
# 获取当前鼠标相对于view的位置
|
||||||
|
if angleY > 0:
|
||||||
|
self.scale *= 1.1
|
||||||
|
else: # 滚轮下滚
|
||||||
|
self.scale *= 0.9
|
||||||
|
self.adjustSize()
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def mouseMoveEvent(self, e):
|
||||||
|
"""
|
||||||
|
mouse move events for the widget
|
||||||
|
:param e: QMouseEvent
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if self.left_click:
|
||||||
|
self.end_pos = e.pos() - self.start_pos
|
||||||
|
self.point = self.point + self.end_pos
|
||||||
|
self.start_pos = e.pos()
|
||||||
|
self.repaint()
|
||||||
|
|
||||||
|
def mousePressEvent(self, e):
|
||||||
|
"""
|
||||||
|
mouse press events for the widget
|
||||||
|
:param e: QMouseEvent
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if e.button() == Qt.LeftButton:
|
||||||
|
self.left_click = True
|
||||||
|
self.start_pos = e.pos()
|
||||||
|
|
||||||
|
def mouseReleaseEvent(self, e):
|
||||||
|
"""
|
||||||
|
mouse release events for the widget
|
||||||
|
:param e: QMouseEvent
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if e.button() == Qt.LeftButton:
|
||||||
|
self.left_click = False
|
||||||
|
|
||||||
|
|
||||||
|
class MainDemo(QWidget):
|
||||||
|
def __init__(self):
|
||||||
|
super(MainDemo, self).__init__()
|
||||||
|
|
||||||
|
self.setWindowTitle("Image Viewer")
|
||||||
|
self.setFixedSize(1000, 600)
|
||||||
|
self.setWindowIcon(QIcon('./app/data/icon.png'))
|
||||||
|
self.zoom_in = QPushButton("")
|
||||||
|
self.zoom_in.clicked.connect(self.large_click)
|
||||||
|
self.zoom_in.setFixedSize(30, 30)
|
||||||
|
in_icon = QIcon("./app/ImageBox/icons/zoom_in.jpg")
|
||||||
|
self.zoom_in.setIcon(in_icon)
|
||||||
|
self.zoom_in.setIconSize(QSize(30, 30))
|
||||||
|
|
||||||
|
self.zoom_out = QPushButton("")
|
||||||
|
self.zoom_out.clicked.connect(self.small_click)
|
||||||
|
self.zoom_out.setFixedSize(30, 30)
|
||||||
|
out_icon = QIcon("./app/ImageBox/icons/zoom_out.jpg")
|
||||||
|
self.zoom_out.setIcon(out_icon)
|
||||||
|
self.zoom_out.setIconSize(QSize(30, 30))
|
||||||
|
|
||||||
|
w = QWidget(self)
|
||||||
|
layout = QHBoxLayout()
|
||||||
|
layout.addWidget(self.zoom_in)
|
||||||
|
layout.addWidget(self.zoom_out)
|
||||||
|
layout.setAlignment(Qt.AlignLeft)
|
||||||
|
w.setLayout(layout)
|
||||||
|
w.setFixedSize(550, 50)
|
||||||
|
|
||||||
|
self.box = ImageBox()
|
||||||
|
self.box.resize(500, 300)
|
||||||
|
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
layout.addWidget(w)
|
||||||
|
layout.addWidget(self.box)
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
def open_image(self):
|
||||||
|
"""
|
||||||
|
select image file and open it
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
img_name, _ = QFileDialog.getOpenFileName(self, "Open Image File", "*.jpg;;*.png;;*.jpeg")
|
||||||
|
self.box.set_image(img_name)
|
||||||
|
|
||||||
|
def large_click(self):
|
||||||
|
"""
|
||||||
|
used to enlarge image
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if self.box.scale < 2:
|
||||||
|
self.box.scale += 0.1
|
||||||
|
self.box.adjustSize()
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def small_click(self):
|
||||||
|
"""
|
||||||
|
used to reduce image
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if self.box.scale > 0.1:
|
||||||
|
self.box.scale -= 0.2
|
||||||
|
self.box.adjustSize()
|
||||||
|
self.update()
|
9
app/data/__init__.py
Normal file
9
app/data/__init__.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
@File : __init__.py.py
|
||||||
|
@Author : Shuaikang Zhou
|
||||||
|
@Time : 2022/12/13 14:19
|
||||||
|
@IDE : Pycharm
|
||||||
|
@Version : Python3.10
|
||||||
|
@comment : ···
|
||||||
|
"""
|
5
app/data/config.json
Normal file
5
app/data/config.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"username": "root",
|
||||||
|
"password": "123456",
|
||||||
|
"database": "chat_2020303457"
|
||||||
|
}
|
BIN
app/data/icon.png
Normal file
BIN
app/data/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Loading…
Reference in New Issue
Block a user