キーボードを使用して、無限ループのあるPyQGISスクリプトを停止しますか?


12

そのため、特定の時間間隔(time.sleep(5)を使用して5秒ごと)で "while True:"を使用して何度も何度もやりたいスクリプトを作成しました。これまでのところ、しかし、私はそれを止めたいとき、私はちょうどできません。

Control + C、Control + Break、Escapeを試しましたが、キーボードはほとんど無視されます。それを止める唯一の方法は、QGISを閉じることです。何か案は?さらに、スクリプトがtime.sleep(5)に達すると、QGISの種類が5秒間遅れてフリーズし、たとえばレイヤーをパンすることはできませんが、これは正常だと思います。

これが私のスクリプトです。

from PyQt4.QtGui import *
from PyQt4.QtCore import *
from qgis.core import *
from qgis.utils import iface
import time


while True: 

    def change_color():
        active_layer = iface.activeLayer()
        pipeline=[]
        txt=open('C:/users/stelios/desktop/project/Sensor.txt','r')
        for line in txt.readlines():
            pipeline.append(line.split())
        print pipeline 
        pipeline2=[]
        for label,color in pipeline:
            if "0" in color:
                pipeline2.append([label,"green"])
            else:
                pipeline2.append([label,"red"])

        print pipeline2
        elatomatikoi=""
        categories=[]

        for label,color in pipeline2:
            if 'red' in color:
                elatomatikoi=elatomatikoi + label+","
            symbol = QgsSymbolV2.defaultSymbol(active_layer.geometryType())
            symbol.setColor(QColor(color))
            category = QgsRendererCategoryV2(int(label), symbol, label)
            categories.append(category)

        expression = 'id' 
        renderer = QgsCategorizedSymbolRendererV2(expression, categories)
        active_layer.setRendererV2(renderer)
        active_layer.setCacheImage(None)
        iface.mapCanvas().refresh()
        iface.legendInterface().refreshLayerSymbology(active_layer)
        elatomatikoi= elatomatikoi[:-1]

        for label,color in pipeline2:
            if 'red' in color:
                QMessageBox.critical(None,"Warning",("Leakage at pipe(s):%s\nCheck Pipeline status " %elatomatikoi))
                break
        txt.close()

    change_color()
    time.sleep(5)

「終了」をトリガーする条件は何ですか?
ニックス

1
qgisでブロックしないプロセスを実装する方法はたくさんあります。Qtイベントループに任せずにコントロールを取得しています。私は探検することをお勧め:1)をイベント駆動型アーキテクチャまたは2を作成する)Pythonのサブプロセスまたは最も単純な方法で、あなたのプロセスを管理)Processing Toolboxのスクリプトを作成し、必要に応じて選択肢2との統合
ルイジピレリ

3
多分私はそれを間違った方法で言った。QGISでPythonコンソールを開いて、次のように入力します。1:「a」と印刷してEnterキーを押します。その後、「a」が永遠に印刷されます。QGISを終了せずにどのように停止しますか?それは問題であり、本当の問題
ステリオスM

これはより一般的なPythonの質問かもしれないので、StackOverflowで答えを得るのは幸運かもしれません。
マーティン

@マーティンはやる。しかし、これは非常に簡単な質問であり、QGISのヘッド開発者がPythonコンソールの無限ループシナリオを考えていなかったことに驚かされます。マシンで1:print 'a'を実行中に実行すると、キーボードで停止できますか、それともシステムの障害ですか?
ステリオスM

回答:


2

QGISはpythonの全機能を提供します。これは驚くべき可能性を開きますが、潜在的な落とし穴も伴います。QGISが応答しなくなったり、フリーズしたり、クラッシュしたりする可能性があります。賢く使ってください!

あなたの場合、メインスレッドを5秒間スリープさせる代わりに、QGISに何か他のこと(キーストロークやボタンの押下を聞くなど)をさせ、タイマーイベントをメインイベントループにポストして、コントロールを制御に戻します。 5秒後にスクリプトを作成します。

この回答からの例を良い出発点として使用できます。停止するには、イベントをstop()タイマーのスロットに接続するだけです。

def change_color():
    print('I am now red')

timer = QTimer()
timer.timeout.connect(change_color)
timer.start(5000)

someButton.clicked.connect(timer.stop)

または、停止する必要があると思われるときにコンソールから手動で呼び出します

timer.stop()

メインウィンドウeventFilter()をインストールして、必要に応じてキーの押下をインターセプトすることもできます。


0

回避策として、キャンセルボタン付きのQTウィジェットを使用できます。

少し荒いですが、私が使用したウィジェットスクリプトは次のとおりです。

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_Form(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.setupUi(self)
        self.running = True
    def setupUi(self, Form):
        Form.setObjectName(_fromUtf8("Form"))
        Form.resize(100, 100)
        self.horizontalLayout_3 = QtGui.QHBoxLayout(Form)
        self.horizontalLayout_3.setObjectName(_fromUtf8("horizontalLayout_3"))
        self.horizontalLayout = QtGui.QHBoxLayout()
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
        self.Cancel_btn = QtGui.QPushButton(Form)
        self.Cancel_btn.setMinimumSize(QtCore.QSize(0, 0))
        self.Cancel_btn.setMaximumSize(QtCore.QSize(425, 27))
        self.Cancel_btn.setObjectName(_fromUtf8("Cancel_btn"))
        self.horizontalLayout.addWidget(self.Cancel_btn)
        self.horizontalLayout_3.addLayout(self.horizontalLayout)
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        Form.setWindowTitle(_translate("Form", "Cancel", None))
        self.Cancel_btn.setText(_translate("Form", "Cancel", None))
        self.Cancel_btn.clicked.connect(self.Cancel)


    def Cancel(self):
        self.running = False

これをpyQgisスクリプトにインポートして(ディレクトリをsys.pathに追加する必要があります)、実行中の変数を使用してwhileループを停止できます。

import sys
sys.path.append("path/to/cancel_widget")

import cancel_widget

btn = cancel_widget.Ui_Form()
btn.show()

while btn.running:
    ...
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.