使用键盘停止具有无限循环的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)

触发“退出”的条件是什么?
尼克,2015年

1
有很多方法可以在qgis中实现无阻塞过程。您无需离开Qt事件循环即可获得控件。我建议您探索:1)创建事件驱动的体系结构或2)以python子流程或简单方式管理您的流程)创建Processing Toolbox脚本,并在必要时与选择2集成
Luigi Pirelli

3
伙计们,也许我说错了。让我用一个新场景来重新说明这个问题:在QGIS中打开Python控制台,键入:而1:打印“ a”,然后按Enter。然后它将永远打印“ a”。在不退出QGIS的情况下如何停止它?这就是问题和真正的问题
Stelios M

这可能更像是一个通用的Python问题,所以您最好在StackOverflow上得到答案。
马丁

@马丁会的。但这是一个非常直截了当的问题,让我感到惊讶的是,QGIS主管开发人员还没有想到他们的python控制台中的无限循环方案。如果您在机器上以1:print'a'的方式执行时,是否可以使用键盘将其停止,或者这是我的系统故障?
Stelios M

Answers:


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:
    ...
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.