Как обратиться к переменной другого класса?

Работаю с PyQt5 на Python.
Есть классы MyWidget(QMainWindow) и ThreadClassCheck(QtCore.QThread).

В MyWidget открывается интерфейс с 2 полями ввода и 1 кнопкой. После нажатия на кнопку из первого (верхнего) поля ввода это слово переносится во второе поле ввода (при этом в первом это слово также остается).

Как можно в классе ThreadClassCheck(QtCore.QThread) обратиться к значению этих двух полей из класса MyWidget?

Дизайн t.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>491</width>
    <height>276</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QPushButton" name="pushButton">
    <property name="geometry">
     <rect>
      <x>210</x>
      <y>190</y>
      <width>93</width>
      <height>31</height>
     </rect>
    </property>
    <property name="text">
     <string>кнопка</string>
    </property>
   </widget>
   <widget class="QLineEdit" name="lineEditInput">
    <property name="geometry">
     <rect>
      <x>130</x>
      <y>40</y>
      <width>321</width>
      <height>31</height>
     </rect>
    </property>
   </widget>
   <widget class="QLabel" name="label">
    <property name="geometry">
     <rect>
      <x>50</x>
      <y>40</y>
      <width>51</width>
      <height>31</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 12pt &quot;MS Shell Dlg 2&quot;;</string>
    </property>
    <property name="text">
     <string>Ввод</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_2">
    <property name="geometry">
     <rect>
      <x>50</x>
      <y>120</y>
      <width>71</width>
      <height>31</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">font: 12pt &quot;MS Shell Dlg 2&quot;;</string>
    </property>
    <property name="text">
     <string>Вывод</string>
    </property>
   </widget>
   <widget class="QLineEdit" name="lineEdit_2Output">
    <property name="geometry">
     <rect>
      <x>130</x>
      <y>120</y>
      <width>321</width>
      <height>31</height>
     </rect>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>491</width>
     <height>26</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

main.py:

from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5 import QtCore
from PyQt5 import uic

import sys
import time


class ThreadClassCheck(QtCore.QThread):
    signal = QtCore.pyqtSignal(str)

    def __init__(self, checkword, parent=None):
        super(ThreadClassCheck, self).__init__(parent)
        self.is_going = True
        self.checkword = checkword

    def display(self):
        print('ниже выведем первое поле')
        print(self.lineEditInput.text())

    def run(self):
        while True:
            # как здесь получить переменную значение из двух полей ввода?
            # self.text1 = self.lineEditInput.text()
            # self.text2 = self.lineEdit_2Output.text()
            # в интерфейсе, но не в классе ThreadClass

            ex = MyWidget()  # экземпляр интерфейса
            ThreadClassCheck.display(ex)  # такой вызов тоже не работает, пустая строка

            time.sleep(3)
            sms = "check"
            self.signal.emit(sms)

    def stop(self):
        self.is_going = False
        self.terminate()


class MyWidget(QMainWindow):
    def __init__(self):
        super().__init__()
        uic.loadUi('t.ui', self)
        self.pushButton.clicked.connect(self.btn)

        self.text2 = self.lineEdit_2Output.text()
        self.text1 = self.lineEditInput.text()

    def btn(self):
        print('кнопка нажата, данные из первой строки:', self.text1)
        print('кнопка нажата, данные из второй строки:', self.text2)
        self.lineEdit_2Output.setText(self.text1)  # из первого поля ввода переносим во второй


def except_hook(cls, exception, traceback):
    sys.__excepthook__(cls, exception, traceback)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MyWidget()
    ex.show()
    sys.excepthook = except_hook
    sys.exit(app.exec_())

Попробовал через экземпляр, но почему-то выводит пустую строку.


Ответы (1 шт):

Автор решения: S. Nick
  1. Нельзя взаимодействовать в дополнительном потоке с виджетами. В Qt вы должны использовать сигналы и слоты.

  2. Дополнительные потоки нужны если у вас есть какие-то длительны задачи или вычисления.

  3. В том что вы описываете нет длительных вычислений и поэтому вам не нужен дополнительный поток, а достаточно QTimer:


import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import QTimer
from PyQt5 import uic


class MyWidget(QMainWindow):
    def __init__(self):
        super().__init__()
        uic.loadUi('t.ui', self)
        
        self.lineEditInput.setFocus()
        self.pushButton.clicked.connect(self.btn)
        
        self.timer = QTimer()
        self.timer.timeout.connect(self.btn)
        self.timer.start(3000)

    def btn(self):
        print(f'Ввод : {self.lineEditInput.text()}')

        # из первого поля ввода переносим во второй
        self.lineEdit_2Output.setText(self.lineEditInput.text())
        print(f'Выврд: {self.lineEdit_2Output.text()}')
        self.lineEditInput.setFocus()
        

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MyWidget()
    ex.show()
    sys.exit(app.exec_())
  1. Если вы хотите понять работу с дополнительными потоками - тогда так:

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import QTimer, QThread, pyqtSignal 
from PyQt5 import uic


class ThreadClassCheck(QThread):
    signal = pyqtSignal(str)                              

    def __init__(self, word, parent=None):
        super(ThreadClassCheck, self).__init__(parent)
        self.is_going = True
        self.word = word

    def run(self):
        while self.is_going:
            self.signal.emit(self.word)
            self.msleep(3000)

    def stop(self):
        self.is_going = False
        

class MyWidget(QMainWindow):
    def __init__(self):
        super().__init__()
        uic.loadUi('t.ui', self)
        
        self.lineEditInput.setFocus()
        self.lineEditInput.textChanged.connect(self.text_changed)
        
        self.pushButton.setText('Start')
        self.pushButton.clicked.connect(self.btn)
        
        self.thread = ThreadClassCheck(self.lineEditInput.text())
        self.thread.signal.connect(self.thread_check)
        
    def text_changed(self, text):
        self.thread.word = text
    
    def thread_check(self, text):
        self.lineEdit_2Output.setText(text)
        
    def btn(self):
        if self.pushButton.text() == 'Start':
            self.thread.start()
            self.thread.is_going = True
            self.pushButton.setText('Stop')
            self.lineEditInput.setFocus()
        else:
            self.thread.stop()
            self.pushButton.setText('Start')        


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MyWidget()
    ex.show()
    sys.exit(app.exec_())

введите сюда описание изображения

→ Ссылка