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プログラムでドキュメントをプレビュヌする

Source: https://habr.com/ru/post/J336478/


All Articles