PyQtでツールを研ぎます

ツールが必要でした。 シャープ、実用的、多用途。 必要に応じてすべての要件を満たし、拡張可能です。



画像



しかし、シンプルで便利です。 主な仕事では開発者ではないため、作業中のコンピューターに永続的なプログラミング環境はなく、必要に応じて、MSOfficeのbat、JScript、VBA(はい、これはWindows、企業システム、いいえbashとperl「そのまま」)、異なるソフトウェアのマクロなど。 これらはすべて現在の問題の解決に役立ちますが、レベルと機能は私が望んでいるものではありません。



要するに、ファイルの解析と変換、データベースへの登り、レポートの受信、Webサービスの呼び出し、dirでのリクエストの生成などが可能な、組み込みプログラミング言語を備えた統合環境が必要です。



あなたは今、すべての味と色のためのツールがあると言うでしょう、ただ選択してください。 Oracleの別名TOADカエル、バスのSoapUI、その他すべてのGNUおよびApache製品。

しかし問題は、それらはすべて1つのアクティビティに特化されているが、一方で、あまりにも普遍的であるということです。 機会が製品にない場合、追加することはできません。 製品が閉じているか、プラグインを開発/購入するか、ソースをダウンロードして理解する必要があります。 しかし、単純なアクションを単純に実行するツールが必要でしたが、複雑なアクションに少し時間を費やし、すべてが簡単になりました。



したがって、必要なモジュールを起動する最も単純なシェルを自分で構築することにしました。 シェルは拡張可能であり、モジュールはシンプルで、シェルから可能な限り独立しています。







プログラミング言語として、特定のタスクのために簡単に再構築できるように、コンパイルを必要としない、または最小限のコストで何かを取る必要があります。



Javascriptは小さなスクリプトに適していて適切ですが、ウィンドウインターフェイスはありません。また、Windows向けにNodeJSをローカルで作成し、ブラウザと戦うことは私にとって興味のないことです。

Perl、PHPも同じ問題です。



Visual BasicとVBScript-まあ、それはWindowsの下にあります。 はい、私が仕事をする名誉のあるエンタープライズITシステムのほとんどはWindowsです。 そしてそれぞれにOfficeがあり、したがってVBAがあります。 しかし、常に使いたいことをするなら、クロスプラットフォームです。



選択肢はPython + PyQt5にありました。 PythonがプリインストールされているRaspberry Raspberry Piから、(もちろんHabrに加えて)言語の存在について学びました。 ペンの内訳はTelegramのボットで、フレーズの同義語を探していました( pymorphy2とYARNで、興味があれば説明します)。 そして、私はすでにQtを知っていました。



pip3 install pyqt5
      
      





最初に、データベースを照会するための汎用モジュールを作成します。 そして、リクエストとそのパラメーターがモジュールの外側、iniファイルで定義され、モジュールがインターフェースとのすべての作業、データベースとの作業、データの表示に従事するように。



PyQtを接続します。 Qtの命名規則は厳密であるため、すべてを連続してインポートしますが、干渉しません。



 from PyQt5.QtCore import * from PyQt5.QtWidgets import * from PyQt5.QtSql import *
      
      





Qtのエラーメッセージと警告が失われないように、 ここで提案するように、モジュールをメッセージハンドラーに接続します。



 import meshandler
      
      





ここで詰まらないように、別のモジュールでデータベースに接続します



 import dbpool
      
      





QDialogに基づいてクラスを作成しましょう(QWidgetも適していますが、デフォルトではボタンは機能しません)



 class PyExecutor(QDialog): def __init__(self, iniFile, parent=None): super(PyExecutor, self).__init__(parent) self.setWindowFlags(self.windowFlags() | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint )
      
      





ウィンドウを上から下に埋める



 self.topLay = QVBoxLayout(self) self.topLay.setContentsMargins(6,6,6,6)
      
      





パラメータとボタンを入力するためのスペースのあるレイアウト



 self.lay = QFormLayout() self.topLay.addLayout(self.lay)
      
      





出力の場所



 self.resultLay = QVBoxLayout() self.topLay.addLayout(self.resultLay)
      
      





そしてステータスバーは



 self.bar = QStatusBar(self) self.topLay.addWidget(self.bar)
      
      





iniファイルをダウンロードします。 必要に応じて後でブロックできるように、別の方法で負荷を取り除きます。



 self.loadIni(iniFile) def loadIni(self, iniFile):
      
      





iniファイルを操作するには、その方法を知っているという理由だけでQtツールを使用します。 Pythonにもおそらく方法がありますが、私は掘りませんでした。 ロシア語に関する将来の問題を回避するために、すべてのファイルでUTF-8で作業します。



 ini = QSettings(iniFile, QSettings.IniFormat) ini.setIniCodec("utf-8")
      
      





入力セクションからリクエストパラメーターをロードします



 ini.beginGroup("Input") for key in sorted(ini.childKeys()):
      
      





パラメーターは、「Name = Label:default value」という行で定義されます

名前はコロンと一緒に省略でき、インターフェースは名前になります。



 v = ini.value(key).split(':') if len(v)>1: paramTitle = v[0] paramValue = v[1] else: paramTitle = key paramValue = v[0]
      
      





パラメーターごとに、入力行を作成し、貯金箱に入れて、インターフェイスにラベルとともに挿入します



 self.params.append([key, paramTitle, paramValue]) if paramTitle != '': le = QLineEdit() self.inputs[key] = le le.setText(paramValue) le.paramTitle = paramTitle self.lay.addRow(paramTitle, le) ini.endGroup()
      
      





DBセクションからデータベース接続パラメーターを読み取ります



 ini.beginGroup("DB") self.dbini = ini.value("DBConnect") if self.dbini == "this": self.dbini = iniFile ini.endGroup()
      
      





最後に、SQLクエリのテキストを読みます。



「実行」セクションには、クエリテキスト自体を含む「SQL」キー(引用符で囲む方が良い)があるか、クエリを含むsqlファイルが書き込まれる「SQLScript」キーがあります。これにより、複数行のクエリを作成できます。 さらに、ファイル内のリクエストは、Colorerハイライトを使用してFARで編集する方が便利です。



iniのように、sqlファイルはUTF-8でエンコードされていると信じています。トランスコーディングの場合のみ、 'utf-8-sig'を使用してファイルの先頭のBOMを取り除きます。



 ini.beginGroup("Run") if ini.contains("SQL"): self.sql = ini.value("SQL") else: f = QFile(ini.value("SQLScript")) f.open(QIODevice.ReadOnly) self.sql = str(f.readAll(),'utf-8-sig') ini.endGroup()
      
      





最後の仕上げ-開始ボタンを追加し、うまく配置します。



 self.runBtn = QPushButton("Run") self.runBtn.setDefault(True) self.btnLay = QHBoxLayout() self.btnLay.addStretch() self.btnLay.addWidget(self.runBtn) self.lay.addRow(self.btnLay)
      
      





ボタンには、実行要求を実行するメソッドが割り当てられます



 self.runBtn.clicked.connect(self.run)
      
      





実際に起動する方法



 def run(self): self.runBtn.setEnabled(False) # ,        self.clearResult() #  ,  
      
      





データベースを操作してみましょう。



QSqlDatabaseオブジェクトを取得します。これは有効で開かれている必要があります。 そしてそうでない場合-おっと、それから何も起こりません。



 self.db = dbpool.openDatabase(self.dbini) if self.db == None or not self.db.isValid() or not self.db.isOpen(): print("No opened DB", self.dbini) self.endRun() return
      
      





Qtでは、基本的にデータベースクエリを操作する1つの方法はQSqlQueryです



 self.query = QSqlQuery(self.db)
      
      





Parsim sql-query、パラメーターを入力行からの値で埋めます



 self.query.prepare(self.sql) for p in self.params: key = p[0] if key in self.inputs: le = self.inputs[key] par = ':'+key self.query.bindValue(par, le.text())
      
      





リクエストが実行されるまで待たないために、その実行を別のスレッドに配置します。



 self.tr = QueryRunner(self.query) self.tr.finished.connect(self.showQueryResult) self.tr.start();
      
      





スレッドが完了すると、このメソッドが実行されます



 def showQueryResult(self):
      
      





必要に応じてQTableViewラベルを作成しましょう



 w = self.createTableView()
      
      





ただし、クエリ結果を含むモデルをすぐに表示するのではなく、プロキシを介して渡します。これにより、列をクリックしてプレートをソートし、必要に応じて検索を行うことができます。



 w.sqlModel = QSqlQueryModel(w) w.sqlModel.setQuery(self.query) w.proxyModel = QSortFilterProxyModel(w) w.proxyModel.setSourceModel(w.sqlModel) w.setModel(w.proxyModel) self.resultLay.addWidget(w) self.endRun()
      
      





シェルなしでチェックしたことの実行を始めましょう



 if __name__ == '__main__': #    Windows import os import PyQt5 import sys pyqt = os.path.dirname(PyQt5.__file__) QApplication.addLibraryPath(os.path.join(pyqt, "Qt", "plugins"))
      
      





そして実際に打ち上げ



 app = QApplication(sys.argv) ex = PyExecutor("artists.ini") ex.show() sys.exit(app.exec_())
      
      





Artists.iniファイル



 [Common] Title=  [Input] Name= ():%r% [DB] DBConnect=sqlite.ini [Run] SQL="SELECT * FROM artists where :Name = '' or artist like :Name"
      
      





チェック済み-動作します







次に、起動シェル自体が必要です。



シェルでは、構成されたすべての機能のツリーを表示し、それらを別々のウィンドウで実行します。 そして、ウィンドウがモーダルではないように、すなわち それらを切り替えて新しいものを起動できます。



簡単にするために、Qtにはすべての機能があるため、MDIウィンドウを使用します。 ツリーの読み取りと表示はPyQtの例から完全に取られているので、ここでは詳しく説明しません。



最初の列には関数の名前がツリーの行に表示され、2番目には-関数の説明に、3番目に-モジュールに渡されるiniファイルがあることを確認するだけです。





artists.ini







QMainWindowでメインウィンドウを作成する方法を示します



 class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent)
      
      





MDIウィンドウの主要部分は、特別なQMdiAreaウィジェットです。 起動されたモジュールのウィンドウはその中に存在します。



 self.mdiArea = QMdiArea(self) self.setCentralWidget(self.mdiArea)
      
      





ここまでで、1つのアイテムでメインメニューを作成しましょう。



 self.mainMenu = QMenuBar(self) self.setMenuBar(self.mainMenu) m = self.mainMenu.addMenu("Window") a = m.addAction("Cascade windows") a.triggered.connect(self.mdiArea.cascadeSubWindows)
      
      





ツリーは左側のドックパネルにあります。



 self.treePanel = QDockWidget(" ", self) w = QWidget(self.treePanel) self.treePanel.setWidget(w) lay = QVBoxLayout(w) lay.setSpacing(1) lay.setContentsMargins(1,1,1,1) w.setLayout(lay) self.tree = TreeWidget(self.treePanel) lay.addWidget(self.tree)
      
      





機能の説明が下部に表示されます(後)



 edit = QTextEdit(w) lay.addWidget(edit)
      
      





ツリーをダブルクリックして、ハンドラーを割り当て、パネルをメインウィンドウに配置します。



 self.tree.activated.connect(self.handle_dblclick) self.addDockWidget(Qt.LeftDockWidgetArea, self.treePanel)
      
      





ダブルクリックハンドラーは、ツリーモデルからiniファイルの名前を取得し、モジュールを使用してそこからクラスを作成します。 このクラスはウィジェットであり、MDIウィンドウのクライアント部分に挿入します。



 def handle_dblclick(self, index): proc = index.data(Qt.UserRole) if proc != None: proc = proc.strip() ex = PyExecutor(proc) self.mdiArea.addSubWindow(ex) ex.show()
      
      





私たちはチェックします-それは動作します:







ソースはMITライセンスの下でgithubに投稿されます。 リンクは記事に使用されたソースにつながり、 ルートから最新バージョンを取得できます。



ヒント:

1. PyQtは、Qtと同様に、Oracleへのアクセスに必要なQOCIバイナリドライバーを含みません。 ドライバーは、Qtで提供されるソース(C ++)からアセンブルし、PyQt5 \ Qt \ plugins \ sqldriversに配置する必要があります。 ビルドするには、Oracle Clientのdllが必要です。

2. Pythonへのパスにはキリル文字が含まれないように設定することをお勧めします。 そうしないと、PyQtの屋根が少しスライドし、ファイルが見つかりません。



継続:

-PyQtのツールバーをスカルプトし、データをExcelとHTMLにエクスポートします

-XQueryマークアップでXMLをカットします

-Pythonプログラムでドキュメントをプレビューする



All Articles