вызов функции класса внутри другого класса в python

Недавно я начал изучать Python + PyQt5. Пожалуйста, помогите мне понять, как вызов функции класса внутри другого класса в python.

У меня есть следующий код

from PyQt5 import QtGui, QtWidgets, QtCore, uic
from PyQt5.Qt import *

class mywindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        QtWidgets.QMainWindow.__init__(self)
        self.ui = uic.loadUi('test.ui', self)
        self.resize(820, 300)
        self.setFixedSize(self.size())
        self.pushButton.clicked.connect(self.getValue)
        self.thread = {}
        self.pushButtonStart.clicked.connect(self.start_worker_1)
        self.pushButtonStop.clicked.connect(self.stop_worker_1)

    def getValue(self):
        self.value = self.spinBox.value()
        i = 1
        while i <= self.value:
            os.system('test1.py')
            i += 1
        else:
            print('End, i =', i)

    def start_worker_1(self):
        self.thread[1] = ThreadClass(parent=None, index=1)
        self.thread[1].start()
        self.pushButtonStart.setEnabled(False)
        self.pushButtonStop.setEnabled(True)

    def stop_worker_1(self):
        self.thread[1].stop()
        self.pushButtonStart.setEnabled(True)
        self.pushButtonStop.setEnabled(False)

class ThreadClass(QtCore.QThread):
    any_signal = QtCore.pyqtSignal(int)

    def __init__(self, parent=None, index=0):
        super(ThreadClass, self).__init__(parent)
        self.index = index
        self.is_running = True


    def run(self):
        print('Start...', self.index)
        a = mywindow()
        a.getValue()

    def stop(self):
        self.is_running = False
        print('Stop...', self.index)
        self.terminate()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    application = mywindow()
    application.show()

    sys.exit(app.exec())

Мне нужно, чтобы файл test.py выполнялся столько раз, сколько указано в spinBox

Start... 1
End, i = 1

Если я делаю пока while i <= 4: то работает. Но не работает, если я передаю self.value из SpinBox. Что я делаю не так?


person user15868446    schedule 13.05.2021    source источник
comment
Чего вы пытаетесь достичь? Учтите, что ваш подход не будет работать по двум причинам: 1. вы создаете новый экземпляр mywindow вместо того, чтобы использовать существующий; 2. доступ к объектам пользовательского интерфейса запрещен из внешних потоков, поэтому вместо этого следует использовать сигналы: даже если бы вы могли вызвать метод текущего экземпляра, это, вероятно, привело бы к сбою вашей программы.   -  person musicamante    schedule 13.05.2021
comment
Я не создаю новый экземпляр mywindow. Я просто запускаю другой скрипт, test1.py, который находится в том же каталоге. На нем нет ничего, кроме печати (тест)   -  person user15868446    schedule 13.05.2021
comment
Да, вы создаете новый экземпляр в run(): a = mywindow().   -  person musicamante    schedule 13.05.2021
comment
Вы создаете разные виджеты (кажется, что не заметили): a = mywindow() в каждом потоке. Кроме того, это запрещено в Qt   -  person eyllanesc    schedule 13.05.2021


Ответы (1)


Вы излишне усложняете свое приложение, кроме того, что у вас есть ошибка, что вы создаете объект окна в каждом потоке, что нелогично, кроме того, что запрещено создавать виджеты в другом потоке.

В этом случае лучше использовать QProcess и сигналы, чтобы узнать, когда скрипт завершит выполнение.

Примечание: поскольку .ui не предоставляется, я покажу тривиальный пример:

test.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>180</width>
    <height>98</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QHBoxLayout" name="horizontalLayout">
    <item>
     <widget class="QSpinBox" name="spinBox"/>
    </item>
    <item>
     <widget class="QPushButton" name="pushButton">
      <property name="text">
       <string>Start</string>
      </property>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>180</width>
     <height>28</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

main.py

import os
import sys
from functools import cached_property
from pathlib import Path

from PyQt5 import QtGui, QtWidgets, QtCore, uic

CURRENT_DIRECTORY = Path(__file__).resolve().parent


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui = uic.loadUi(os.fspath(CURRENT_DIRECTORY / "test.ui"), self)

        self.ui.pushButton.clicked.connect(self.handle_clicked)

    @cached_property
    def manager(self):
        return Manager()

    def handle_clicked(self):
        number_of_processes = self.ui.spinBox.value()
        script = os.fspath(CURRENT_DIRECTORY / "test1.py")
        for i in range(number_of_processes):
            self.manager.execute(script, dict(i=i))


class Manager(QtCore.QObject):
    @cached_property
    def processes(self):
        return list()

    def execute(self, script, metadata=None):
        process = QtCore.QProcess()
        process.setProperty("metadata", metadata or dict())
        process.finished.connect(self.handle_finished)
        process.setProgram(sys.executable)
        process.setArguments([script])
        process.start()
        self.processes.append(process)

    def handle_finished(self):
        process = self.sender()
        self.processes.remove(process)
        metadata = process.property("metadata")
        print(f"{metadata} finished")


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)

    w = MainWindow()
    w.show()

    sys.exit(app.exec())
person eyllanesc    schedule 13.05.2021
comment
Спасибо за ваше решение, это то, что мне нужно. Подскажите, пожалуйста, как в этом случае использовать Qprocess, чтобы следующий процесс запускался в конце первого. В вашем примере они идут параллельно - person user15868446; 14.05.2021
comment
@user15868446 см. stackoverflow.com/questions/53461496/ и stackoverflow.com/questions/51364552/ - person eyllanesc; 14.05.2021
comment
Не могли бы вы рассказать мне на моем примере, я действительно старался. Но у меня не получилось :( - person user15868446; 14.05.2021