Software de entrada de datos PyQt en la práctica

Portal: software de gráficos PyQt (aprendizaje basado en proyectos)

análisis de la demanda

Software de cuantificación para pruebas de detección del desarrollo en un hospital

ingresar

Información básica del paciente
Formulario de prueba de detección (formulario de plantilla ya disponible)

producción

Varios puntajes brutos para deportes, adaptación social e inteligencia;
varios puntajes calculados para
las sugerencias correspondientes de IQ EQ

Formato de informe: fijo

Guardar en local (PDF/Word), considere reemplazar la plantilla

diseño del marco

Basado en Python 3.6 + QT

Capa de interfaz - QtDesigner

Estilo general

Debido a que la tabla de cuantificación tiene tres categorías principales y hay muchos indicadores de parámetros en cada parte, se adopta un diseño apilado.La
interfaz principal se compone de dos marcos.
inserte la descripción de la imagen aquí

cuadro de texto de varias líneas

https://blog.csdn.net/qq_28077617/article/details/121876632

Subpágina

información

Cuando hay varios cuadros de entrada (edición de línea), puede considerar la introducción de la tecla de método abreviado Tabulador Para configuraciones específicas, consulte este artículo;

fecha de anidamiento

Desplegable del calendario para seleccionar la hora

https://blog.csdn.net/weixin_39626452/article/details/86700178?spm=1001.2014.3001.5506
interfaz de usuario

self.dateEdit = QtWidgets.QDateEdit(self.gridLayoutWidget)
        self.dateEdit.setObjectName("dateEdit")
        # 设置日期显示格式
        self.dateEdit.setDisplayFormat('yyyy-MM-dd')
        # 设置允许日历控件弹出
        self.dateEdit.setCalendarPopup(True)
                # 当日期改变时触发槽函数
        self.dateEdit.dateChanged.connect(self.onTimeChanged)

Código comercial

    def onTimeChanged(self,time):
        birthtime = time
        print(birthtime)
Obtener la hora actual y mostrarla
    # 获取当前时间
    testTime = datetime.datetime.now().strftime('%Y-%m-%d')
    # 回传子页面 setText设置输入框显示值
    self.lineEdit_TestTime.setText(testTime)
    print(testTime)
Establecer rango de fechas para la selección del calendario
   # 设置日期范围
   self.dateEdit.setMinimumDate(QDate.currentDate().addDays(-365*10))
   self.dateEdit.setMaximumDate(QDate.currentDate().addDays(0))

diseño de pila

inserte la descripción de la imagen aquí
Widget apilado, y luego consulte el artículo anterior, las siguientes son las principales precauciones;

Señales y tragamonedas
        # 建立堆叠布局信号与槽连接
        self.pushButton_Sports.clicked.connect(self.frameController)
        self.pushButton_Social.clicked.connect(self.frameController)
        self.pushButton_Iq.clicked.connect(self.frameController)

Si el código para la creación de la señal y la ranura se coloca antes del código de creación del botón, se producirá
AttributeError: 'AppMainWindow' object has no attribute 'pushButton_Sports'un error.

Tamaño de pantalla adaptable a la ventana

Con respecto al diseño de la cuadrícula, las líneas de la cuadrícula no se generan automáticamente

inserte la descripción de la imagen aquí

qt-designer agrega imágenes personalizadas

Consulte este artículo
para convertir,
pyrcc5 -o re_rc.py, su propio nombre de archivo de recursos.qrcinserte la descripción de la imagen aquí

Capa empresarial

Atravesar para obtener el estado de la casilla de verificación y convertirlo en cálculo de puntuación

Reproducción de escena: Como se muestra arriba, tengo muchas casillas de verificación, y quiero obtener el estado de selección de las casillas de verificación a su vez; cabe señalar que cada casilla de verificación tiene un nombre único , y su formato generalmente es checkBox_XXX ( xxx es el número). Este método de nomenclatura proporciona comodidad para nuestro recorrido;
consulte esta respuesta , el bucle for tradicional + cadenas de objeto de empalme no es factible, porque obtiene una cadena en lugar de un nombre de objeto; **Usamos el getattr ()** método para generar el nombre del objeto checkBOX

# 这里的self是页面父类-主窗口
           try:
        # 针对运动表,判断其最后一个得分项
        for i in range(1, 31):
            # 遍历checkBox对象
            m = getattr(self, "checkBox_%d" % i)
            if m.isChecked():
                #     print("checked" + m)
                print("num" + str(i) + ": " + str(m.isChecked()))
                sports_pass = i
        print("the final score is:" + str(sports_pass))

    except Exception as e:
        print(e)

Lo que quiero explicar aquí es que si desea print(m)escribir el nombre del objeto, se informará un error. El mensaje de error probablemente debería ser:
debe ser str, no QCheckBox (esta es también la razón por la cual se detecta la excepción ).
La m aquí puede considerarse como una referencia de objeto, la función de impresión solo puede imprimir cadenas, por lo que no hay nada de malo en informar un error aquí. Creo que esta es también la razón por la que algunas personas informarán un error en la respuesta anterior ;
si insiste en imprimir m, puede usar str(m), entonces encontrará que es un objeto, ¿debería imprimirse la dirección?

docx generar plantilla de informe

dict (zip)

Se utiliza principalmente para generar un diccionario de palabras clave para comparar y reemplazar

biblioteca de tres partes py-docx

consulte este artículo

Guarde el archivo en la ubicación especificada (aparecerá el cuadro de diálogo Guardar archivo)

pyqt5 ya proporciona un cuadro de diálogo de recursos de archivo, a saber, getSaveFileName;

filepath, type = QFileDialog.getSaveFileName(self, '报告保存', '/'+ '%s_报告单.docx' % model, 'docx(*.docx)')
# '报告保存' 是对话框的标题,中间那一长串是保存的路径,后面是默认保存位置
# 这里我是根据患者测试时间和姓名 默认给出了文件名字,使用%s 占位符 将字符串model和 路径以及后缀名拼接
doc_t.save(filepath)
# 再使用doc_t.save将文件保存至指定filepath

Genere un informe y guarde el código completo en la ruta especificada

consulte este artículo

Precauciones

Después de abrir el cuadro de diálogo Guardar, si se cancela el guardado, el programa devolverá una ruta vacía ('') y se informará un error en este momento, por lo que es necesario determinar si la ruta del programa está vacía.

import datetime

import docx
from PyQt5.QtWidgets import QFileDialog


def createReport(self,list):

    try:

            # 需制作缴费通知单数据
        report_data = list
        # print(list)

            # 模板内设置的标志:
        tags_1 = ['name','id','gender','birthday','preweek','testdate','months','sports',
                      'social','intel','min','mi','dqn','dq','advice']
        # print(report_data)

            # 生成字典类型的数据集
        notice_dict = dict(zip(tags_1, report_data))
        # print(notice_dict)

        doc_t, runs_t = get_runs('报告模板.docx')
            # 遍历模板run对象 和 notice_dict key 匹配
            # 匹配成功则替换 run 内容
        for run_t in runs_t:
            if run_t.text in notice_dict.keys():
                run_t.text = str(notice_dict[run_t.text])
        #生成格式化文件名
        model = datetime.datetime.now().strftime('%Y%m%d') + '_'+ list[0]

        # 文件保存路径
        save_doc(self,doc_t,model)


    except Exception as e:
        print(e)


# 定义获取 word 模板正文段落、表格 run 对象函数
def get_runs(path):
    doc = docx.Document(path)
    runs_g = []
    # 获取段落 run 对象
    # print(doc.paragraphs)
    for par_g in doc.paragraphs:
        for run_g in par_g.runs:
            runs_g.append(run_g)
            # print(run_g.text)
    # # 获取表格 run 对象
    # table_g = doc.tables[0]
    # for cell_g in table_g._cells:
    #     for cell_par_g in cell_g.paragraphs:
    #         for cell_run_g in cell_par_g.runs:
    #             runs_g.append(cell_run_g)
    #             print(cell_run_g.text)
    return doc, runs_g

# 文件保存路径
def save_doc(self,doc_t,model):
    filepath, type = QFileDialog.getSaveFileName(self, '文件保存', '/'+ '%s_报告单.docx' % model, 'docx(*.docx)')
    print(filepath)
    doc_t.save(filepath)
#

Haga clic en la barra de menú para abrir el documento de ayuda

 def trigger_helpDoc(self):
        webbrowser.open('Help.pdf', new=1)

Abrir ruta guardada recientemente

Use software externo de word/WPS para obtener una vista previa de los documentos generados

Busqué mucho en Internet, la mayoría de los cuales llaman a la palabra interfaz y luego muestran el documento en el marco Pyqt; mi requisito aquí es usar python para llamar a un software externo para abrir el documento en el software correspondiente; use la biblioteca
pywin32compip install -i https://pypi.tuna.tsinghua.edu.cn/simple pypiwin32

from win32com.client import Dispatch
# 这里定义了打开的程序接口
app = Dispatch('Word.Application')
# 这里是打开文件的路径
app.Documents.Open(self.pathtemp)
# 设置word文件可见
app.Visible = True
time.sleep(0.5)

Aquí hay un problema, es decir, mi informe solo se puede obtener una vista previa después de generarlo y guardarlo. Quiero obtener una vista previa del informe antes de guardarlo, pero falla.

# 具体过程参见前面的 docx文件生成并保存
doc_t, runs_t = get_runs('报告模板.docx')

app.Documents.Open(doc_t)

empaquetado de software

Acerca del archivo de configuración de especificaciones

UPX no está disponible

Convierta su archivo '.png' a '.ico' y vuelva a intentarlo.

exe.notaxejecutable

generar no ejecutable

No se puede abrir el archivo de icono \image\logo.ico

1. Se entiende que el tamaño del icono es incorrecto 16*16
2. La ruta del archivo ico es image\logo.ico en lugar de \image\logo.ico

el icono desaparece

Debe copiar el archivo del icono en el archivo de ejecución exe,

El archivo del paquete pyinstaller es demasiado grande

usar pipenv

Este artículo es la sugerencia de yyds de usar el archivo de configuración pyinstaller XXX.spec para generar el programa
en el entorno pipenv.Mi software se ha reducido de los 200M originales a 40M;

Error al instalar PyQt5

inserte la descripción de la imagen aquí

Instale directamente pip install PyQt5-sip== 12.9.1
y luego instale PyQt5 con éxito

Empaquetado secundario de archivos de recursos y exe

Se puede ver que los archivos de recursos antes del empaquetamiento están todos dispersos debajo de la carpeta, que se ve muy baja.Después
inserte la descripción de la imagen aquí
del segundo empaquetamiento con Winrar, los archivos se vuelven un todo:
inserte la descripción de la imagen aquí

Use Winrar
para consultar el artículo 2
, pero el icono no se puede cambiar después del empaquetado Más tarde, descubrí que era un problema con mi versión de Winrar y que no había ninguna opción para cambiar el icono.

Resumen de preguntas Q

Problema de Python: el objeto 'Nonetype' no es iterable

Aquí, la función generalmente se define pero no se proporciona el valor de retorno

Error al tokenizar datos. Error de C: se esperaban 1 campos en la línea 3, vio 2

Esto no funciona
Más tarde descubrí que esa fue la razón por la que cambié directamente el documento .xlsx a .csv

ModuleNotFoundError: ningún módulo llamado 'excepciones'

consulte este texto

Acerca de atravesar párrafos con pydocx, pero se omiten algunas partes

El campo de consejos de la sugerencia de capacitación en la figura a continuación debe reemplazarse lógicamente
inserte la descripción de la imagen aquí

def get_runs(path):
    doc = docx.Document(path)
    runs_g = []
    # 获取段落 run 对象
    print(doc.paragraphs)
    for par_g in doc.paragraphs:
        for run_g in par_g.runs:
            runs_g.append(run_g)
            print(run_g.text)
    # 获取表格 run 对象
    # table_g = doc.tables[0]
    # for cell_g in table_g._cells:
    #     for cell_par_g in cell_g.paragraphs:
    #         for cell_run_g in cell_par_g.runs:
    #             runs_g.append(cell_run_g)
    return doc, runs_g

Para encontrar el problema, imprima el proceso transversal. Tenga en cuenta que necesita usar el método run_g.text para imprimir el contenido específico, de lo contrario, simplemente imprima la dirección del objeto; después de imprimir, encontrará que lo
último lo que obtienes es un consejo, es decir, el consejo está separado, entonces en el reemplazo final, no encontré las palabras clave correspondientes,
la solución es escribir el consejo y las palabras clave en la plantilla y el programa nuevamente, no sé porque hay este problema? ? ? ¿metafísica? ? ?
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/weixin_54594861/article/details/123955868
Recomendado
Clasificación