Fermare lo script PyQGIS che ha un ciclo infinito, usando la tastiera?


12

Quindi ho scritto una sceneggiatura che fa ciò che voglio più e più volte usando un "while True:" in un certo intervallo di tempo (ogni 5 secondi usando time.sleep (5)). Fin qui tutto bene, MA quando voglio fermarlo non posso proprio.

Ho provato Control + C, Control + Break, Escape e praticamente ignora la mia tastiera. L'unico modo per fermarlo è chiudere QGIS. Qualche idea? Inoltre, quando lo script colpisce time.sleep (5) QGIS fa un po 'di ritardo e si blocca per 5 secondi e non posso, ad esempio, eseguire una panoramica del livello, ma presumo che sia normale.

Ecco la mia sceneggiatura:

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)

Quali sono le condizioni che dovrebbero innescare un'uscita?
Nicks

1
ci sono molti modi per implementare un processo senza blocco in qgis. Stai ottenendo il controllo senza lasciarlo al ciclo degli eventi Qt. Suggerisco di esplorare: 1) creare un'architettura guidata dagli eventi o 2) gestire il processo in un sottoprocesso di Python o il modo semplice) creare uno script Toolbox di elaborazione e, se necessario, integrarsi con la scelta 2
Luigi Pirelli

3
Ragazzi forse l'ho detto nel modo sbagliato. Vorrei riformulare la domanda con un nuovo scenario: apri Python Console in QGIS, scrivi: mentre 1: stampa "a" e premi invio. Quindi stampa 'a' per sempre. COME LO FERMI SENZA USCIRE DA QGIS? Questa è la domanda e il vero problema
Stelios M

Questa potrebbe essere una domanda più generale di Python, quindi potresti avere più fortuna a ottenere una risposta su StackOverflow.
Martin

@Martin Lo farà. Ma è una domanda piuttosto semplice e mi stupisce che gli sviluppatori capo di QGIS non abbiano mai pensato allo scenario di loop infinito nella loro console Python. Se esegui mentre 1: stampa 'a' sul tuo computer, riesci a fermarlo con la tastiera o è colpa del mio sistema?
Stelios M

Risposte:


2

QGIS ti offre tutta la potenza di Python. Questo apre incredibili possibilità ma presenta anche potenziali insidie. Ciò potrebbe rendere QGIS non rispondente, bloccarlo o addirittura bloccarlo. Usalo saggiamente!

Nel tuo caso, invece di mandare in sospensione il thread principale per 5 secondi, è meglio lasciare che QGIS faccia qualcos'altro (come ascoltare i tasti premuti o premere i pulsanti) e pubblicare un evento timer nel loop degli eventi principali che restituirà il controllo a la tua sceneggiatura 5 secondi dopo.

Puoi usare l'esempio di questa risposta come un buon punto di partenza. Per interromperlo, basta connettere qualche evento allo stop()slot del timer.

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

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

someButton.clicked.connect(timer.stop)

O semplicemente chiamalo manualmente dalla console quando pensi che sia il momento di fermarlo

timer.stop()

Puoi anche installare un eventFilter () nella finestra principale per intercettare la pressione dei tasti se ne hai bisogno.


0

Come soluzione, puoi utilizzare un widget QT con un pulsante Annulla.

È un po 'approssimativo, ma ecco lo script widget che ho usato:

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

Questo può essere importato nel tuo script pyQgis (dovrai aggiungere la directory a sys.path) e quindi puoi usare la variabile in esecuzione per interrompere il tuo ciclo while:

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

import cancel_widget

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

while btn.running:
    ...
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.