実際の PyQt データ入力ソフトウェア

ポータル: PyQt グラフィック ソフトウェア (プロジェクトベースの学習)

需要分析

病院における発達スクリーニング検査用の定量化ソフトウェア

入力

患者基本情報
スクリーニング検査フォーム(テンプレートフォームはすでに用意されています)

出力

スポーツ、社会適応、知能に関するさまざまな生スコア、
IQ EQ に
対応するさまざまな計算スコア

レポート形式 - 固定

ローカル (PDF/Word) に保存、テンプレートの置き換えを検討してください

フレームワーク設計

Python 3.6 + QT ベース

インターフェイス層 - QtDesigner

全体的なスタイル

量子化テーブルは大きく3つのカテゴリーに分かれており、各パートに多くのパラメータインジケーターがあるため、スタックレイアウトが採用されており、メイン
インターフェイスは2つのフレームで構成されています。
ここに画像の説明を挿入

複数行のテキストボックス

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

サブページ

情報

複数の入力ボックス(lineEdit)がある場合は、Tabショートカットキーの導入を検討してください。具体的な設定方法については、こちらの記事を参照してください。

日付の入れ子

カレンダーのドロップダウンで時間を選択します

https://blog.csdn.net/weixin_39626452/article/details/86700178?spm=1001.2014.3001.5506
UI

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)

事業者コード

    def onTimeChanged(self,time):
        birthtime = time
        print(birthtime)
現在時刻を取得して表示する
    # 获取当前时间
    testTime = datetime.datetime.now().strftime('%Y-%m-%d')
    # 回传子页面 setText设置输入框显示值
    self.lineEdit_TestTime.setText(testTime)
    print(testTime)
カレンダー選択の日付範囲を設定する
   # 设置日期范围
   self.dateEdit.setMinimumDate(QDate.currentDate().addDays(-365*10))
   self.dateEdit.setMaximumDate(QDate.currentDate().addDays(0))

スタックデザイン

ここに画像の説明を挿入
Stacked Widget については、上記の記事を参照してください。主な注意事項は次のとおりです。

信号とスロット
        # 建立堆叠布局信号与槽连接
        self.pushButton_Sports.clicked.connect(self.frameController)
        self.pushButton_Social.clicked.connect(self.frameController)
        self.pushButton_Iq.clicked.connect(self.frameController)

シグナルとスロット作成のコードがボタン作成コードの前にあると
AttributeError: 'AppMainWindow' object has no attribute 'pushButton_Sports'エラーが発生します

ウィンドウ適応画面サイズ

グリッドレイアウトに関して、グリッド線は自動生成されません

ここに画像の説明を挿入

qt-designer はカスタム画像を追加します

この記事
を参照して、
pyrcc5 -o re_rc.py 独自のリソース ファイル名.qrcを変換してください。ここに画像の説明を挿入

ビジネス層

トラバースしてチェックボックスの状態を取得し、スコア計算に変換する

シーンの再現: 上に示したように、たくさんのチェック ボックスがあり、チェック ボックスの選択状態を順番に取得したいのですが、各 checkBox には一意の名前があり、その形式は通常 checkBox_XXX ( xxx は数字です). この命名方法は、トラバーサルに便利です。
この回答を参照してください。オブジェクト名の代わりに文字列を取得するため、従来の for ループ + オブジェクト文字列の結合は実現できません。 **getattr を使用します。 ()** 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)

ここで説明したいのは、print(m)オブジェクトの名前を入力しようとすると、エラーが報告されるということです。エラー メッセージはおそらく次のようになります:
QCheckBox ではなく、str である必要があります(これが例外がキャッチされる理由でもあります) ).
ここの m はオブジェクト参照と見なすことができ、print 関数は文字列のみを出力できるため、ここでエラーを報告しても何も問題はありません。これが、一部の人が前の回答でエラーを報告する理由でもあると思います;
m を出力したい場合は、str(m) を使用すると、それが見つかります これはオブジェクトですが、アドレスを出力する必要がありますか?

docx レポート テンプレートを生成する

辞書(zip)

主に比較と置換のためのキーワード辞書を生成するために使用されます。

py-docx スリーパーティ ライブラリ

この記事を参照してください

指定した場所にファイルを保存します (ファイルの保存ダイアログが表示されます)。

pyqt5 はすでにファイル リソース ダイアログ、つまり getSaveFileName を提供しています。

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

レポートを生成し、完全なコードを指定されたパスに保存します

この記事を参照してください

予防

保存ダイアログを開いた後、保存をキャンセルするとプログラムは空のパス ('') を返し、このときエラーが報告されるため、プログラムのパスが空かどうかを判断する必要があります。

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)
#

メニューバーをクリックしてヘルプドキュメントをポップアップ表示します

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

最近保存したパスを開く

外部の Word/WPS ソフトウェアを使用して生成されたドキュメントをプレビューする

インターネットでたくさん検索しましたが、そのほとんどは Word インターフェイスを呼び出し、Pyqt フレームワークでドキュメントを表示します。ここでの要件は、Python を使用して外部ソフトウェアを呼び出し、対応するソフトウェアでドキュメントを開くことです。pywin32com ライブラリを使用します
pip 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)

ここには問題があります。レポートは生成され保存された後でのみプレビューできるということです。レポートを保存する前にプレビューしたいのですが、失敗します。

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

app.Documents.Open(doc_t)

ソフトウェアのパッケージ化

スペック構成ファイルについて

UPXは利用できません

「.png」ファイルを「.ico」に変換して、再試行してください。

exe.notan実行可能ファイル

実行不可能なファイルを生成する

アイコン ファイル \image\logo.ico を開けません

1. アイコンのサイズが間違っていることがわかります 16*16
2. ico ファイルのパスが \image\logo.ico ではなく image\logo.ico になっています

アイコンが消える

アイコンファイルをexe実行ファイルにコピーする必要があります。

pyinstaller パッケージ ファイルが大きすぎます

Pipenvを使用する

この記事は、pyinstaller XXX.spec
構成ファイルを使用して、pipenv 環境でプログラムを出力するというyyds の提案です。私のソフトウェアは、元の 200M から 40M に縮小しました。

PyQt5のインストールに失敗しました

ここに画像の説明を挿入

pip install PyQt5-sip== 12.9.1 を直接インストールし
、PyQt5 を正常にインストールします

リソースファイルとexeの2次パッケージ化

パッケージ化前のリソース ファイルは、非常に低い位置にあるフォルダーの下にすべて散在していることがわかります。Winrar
ここに画像の説明を挿入
で 2 回目のパッケージ化を行うと、ファイルは全体になります。
ここに画像の説明を挿入

Winrar を使用して
記事 2 を参照
してください。ただし、パッケージ化後にアイコンを変更できません。後で、これは Winrar のバージョンの問題であることがわかり、アイコンを変更するオプションがありませんでした。

Qの質問のまとめ

Python の問題: 'Nonetype' オブジェクトは反復可能ではありません

ここでは関数は一般的に定義されていますが、戻り値は与えられていません

データのトークン化エラー。C エラー: 3 行目に 1 フィールドが予期されていましたが、2 が表示されました

これは機能しません。
後でわかりましたが、それが .xlsx ドキュメントを .csv に直接変更した理由でした

ModuleNotFoundError: 「例外」という名前のモジュールがありません

このテキストを参照してください

pydocx で段落を走査するが、一部の部分がスキップされることについて

以下の図のトレーニング提案のアドバイス フィールドは論理的に置き換える必要があります。
ここに画像の説明を挿入

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

問題を見つけるために、トラバーサル プロセスを出力します。特定のコンテンツを出力するには run_g.text メソッドを使用する必要があることに注意してください。それ以外の場合は、オブジェクト アドレスを出力するだけです。出力後、最後の処理が行われたことがわかります
。得られるのはアドバイスです。つまり、アドバイスが分離されています。最終的な置換では、対応するキーワードが見つかりませんでした。解決策は、アドバイスと
キーワードをテンプレートに入力してプログラムを再度実行することです。わかりません。なぜこの問題があるのでしょうか? ? ? 形而上学?? ?
ここに画像の説明を挿入
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/weixin_54594861/article/details/123955868