Зупинення сценарію PyQGIS, який має нескінченний цикл, використовуючи клавіатуру?


12

Тому я написав сценарій, який виконує те, що я хочу знову і знову, використовуючи "в той час як True:" через певний проміжок часу (кожні 5 секунд, використовуючи time.sleep (5)). Поки що добре, АЛЕ коли я хочу це зупинити, я просто не можу.

Я спробував 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 або способом simples) створити скрипт Toolbox Tooling і, якщо потрібно, інтегрувати з вибором 2
Луїджі Піреллі

3
Хлопці, можливо, я сказав це неправильно. Дозвольте перефразувати питання з новим сценарієм: Ви відкриваєте консоль Python в QGIS, ви вводите: while 1: print "a" і натискаєте клавішу enter. Потім він друкує "a" на віки віків. ЯК ВИ ЗАПУСКУЄТЕ ЇЇ БЕЗ ВІДХОДЖЕННЯ QGIS? Це питання і справжнє питання
Stelios M

Це може бути більше загальним питанням Python, тож вам може бути більше удачі отримати відповідь на StackOverflow.
Мартін

@Martin Зробить. Але це досить просте питання, і це мене дивує, що розробники QGIS не думали про нескінченний сценарій циклу в консолі python. Якщо ви виконуєте під час 1: надрукуйте "a" у вашій машині, чи можете ви зупинити це за допомогою клавіатури чи це помилка моєї системи?
Stelios M

Відповіді:


2

QGIS пропонує вам всю потужність пітона. Це відкриває дивовижні можливості, але також має потенційні підводні камені. Що може змусити 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:
    ...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.