PyQt5 - застрял в al oop при попытке закрыть пользовательский интерфейс с помощью macOS - PullRequest
0 голосов
/ 23 марта 2020

Я создал пользовательский интерфейс с PyQt5. Я могу использовать его на Windows, и он отлично работает, но когда я пытаюсь использовать его на MacOS, я застреваю, пытаясь закрыть его (с self.close()). Используя отладчик PyCharm, я обнаружил, что после self.close() он переходит на app.exec_(), и функция, которая была введена для его закрытия, выполняется снова (например, on_later_button_clicked(self)). Я также уже попробовал sys.exit(app.exec_()).

Вот мой код:

import os
import sys

from PyQt5 import QtGui, QtWidgets
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QApplication, QDialog
from PyQt5.uic import loadUi

from Modules.database import addNeverID
from Modules.supportedWebsites import getWebsites


def Start():
    m = askForPartnerUrl()
    # m.setFixedSize(500,500)
    m.show()
    return m


class askForPartnerUrl(QDialog):
    def __init__(self):
        super(askForPartnerUrl, self).__init__()
        loadUi('lib/askForPartnerURL.ui', self)
        self.setWindowTitle('Immobilien-Upload')

        current_id = getFromFile("id.txt")

        self.show_id.setText(current_id)
        self.show_kaste_url.setText(
            '<a href="' + getFromFile("kaste_url.txt") + '">' + getFromFile("kaste_url.txt") + '</a>')
        self.show_kaste_url.setOpenExternalLinks(True)

        id_beginns = ["IT-TOS-01-", "IT-SAR-MTS-", "IT-SAR-AM-", "IT-SAR-IS-", "IT-SAR-OC-", "IT-SAR-DM"]
        website_eq = ["vestaestateagency.eu", "movetosardinia.com", "easysardinia.net",
                      "immobiliaresarda.it", "orizzontecasasardegna.co", "limmobiliare.com"]

        website_guess_str = "Nicht verfügbar!"

        for i in range(len(id_beginns)):
            if id_beginns[i] in current_id:
                website_guess_str = '<a href="http://' + website_eq[i] + '">' + website_eq[i] + '</a>'
                self.website_guess.setOpenExternalLinks(True)
                break

        self.website_guess.setText(website_guess_str)

        self.save_button.clicked.connect(self.on_save_button_clicked)
        self.later_button.clicked.connect(self.on_later_button_clicked)
        self.never_button.clicked.connect(self.on_never_button_clicked)

        try:
            os.remove('temp/currentObject/partner_url.txt')
        except:
            pass

    @pyqtSlot()
    def on_never_button_clicked(self):
        addNeverID(getFromFile("id.txt"))
        saveToFile("Never-ID", "partner_url.txt")
        self.close()

    def on_later_button_clicked(self):
        saveToFile("Later-ID", "partner_url.txt")
        self.close()

    def on_save_button_clicked(self):

        url_is_valid = False

        for i in getWebsites():
            if i in self.partner_url_input.text():
                url_is_valid = True
                break

        if url_is_valid:
            saveToFile(self.partner_url_input.text(), "partner_url.txt")
            self.close()
        else:
            error_dialog = QtWidgets.QErrorMessage(self)
            error_dialog.setWindowTitle("Eingabe nicht verwertbar")
            error_dialog.showMessage('Die eingegebene URL ist nicht verwendbar! Bitte prüfe deine Eingabe.')


def showGUI():
    app = QApplication(sys.argv)
    app.setStyle('Fusion')
    app.setWindowIcon(QtGui.QIcon('lib/icon.png'))
    window = Start()
    app.exec_()


def saveToFile(content, filename):
    file = open("temp/currentObject/" + filename, "w+")
    file.write(content)
    file.close()


def getFromFile(filename):
    file = open("temp/currentObject/" + filename)
    content = file.read()
    file.close()
    return content

Большое спасибо заранее

1 Ответ

1 голос
/ 23 марта 2020

Причина в том, что, поскольку вы используете пользовательский интерфейс c, он автоматически включает функцию автоматического подключения, которая автоматически определяет имена функций на основе имен объектов / сигналов и подключает их, , даже если функции не иметь декораторы слотов Qt .

В результате ваш слот будет фактически называться трижды :

  1. без аргументов (clicked());
  2. с аргументом checked (clicked(bool)): аргумент игнорируется Qt, так как функция не принимает ничего, но функция все равно будет вызываться , так как нет подписи слота для него было указано;
  3. снова с аргументом checked, поскольку вы вручную подключили его в своем коде;

Если вы хотите продолжать использовать автоматическое подключение, используйте уникальный слот-декоратор для , который специфицирует c функцию, в противном случае вручную подключите к функции (возможно, со слотом, если вам нужна спецификационная c подпись), которая не использует автоматическое подключение именования ионов, но не используют оба.

class askForPartnerUrl(QDialog):
    def __init__(self):
        super(askForPartnerUrl, self).__init__()
        loadUi('askForPartnerURL.ui', self)

        # ...

        # remove the following lines:
        # self.save_button.clicked.connect(self.on_save_button_clicked)
        # self.later_button.clicked.connect(self.on_later_button_clicked)
        # self.never_button.clicked.connect(self.on_never_button_clicked)

        # manual connection
        self.later_button.clicked.connect(self.saveLater)

    # using the auto connection; the function doesn't need arguments, so
    # you can ignore the argument type signature
    @pyqtSlot()
    def on_never_button_clicked(self):
        addNeverID(getFromFile("id.txt"))
        # ...

    # with a normal function; in this case no slot decorator is required since
    # you don't have arguments
    def saveLater(self):
        url_is_valid = False
        # ...

PS: причина, по которой он "застревает", вероятно, связана с тем, как Python имеет дело с окончанием программа (которая по умолчанию происходит после закрытия последнего окна в Qt) в MacOS: после первого вызова close() PyQt пытается выйти из QApplication (освободить память и т. д. c ...), но при этом исходное событие щелчка все еще находится в процессе запуска сигналов в оставшийся второй и третий слот, следовательно, «l oop» (но это не фактический l oop, и третий слот никогда не вызывается потому что это второй, который блокирует все).
Обратите внимание, что это упрощение большое , я не эксперт в использовании памяти и низкоуровневом программировании, но это принципиально то, что происходит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...