Найти - Пользователи
Полная версия: PyQt4 | Как передать сигнал из дочернего окна в родительское?
Начало » GUI » PyQt4 | Как передать сигнал из дочернего окна в родительское?
1 2 3 4 5
Kyrym
Python 3. PyQt4
Как передать данные из текстового поля дочернего окна при нажатии на кнопку в текстовое поле родительского окна?
Дочернее окно - это отдельный модуль.
Суть в том, что дочернее окно не видит полей родителя.
Вот код:
Родитель:
 import sys
from PyQt4 import QtGui, QtCore
import mod 
 
class MainWindow(QtGui.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.secondWin = None
        self.build()
 
    def build(self):
        self.resize(300, 200)
         
        self.lab = QtGui.QLabel('simple text', self)
        
        self.pole = QtGui.QTextEdit()
 
        self.but1 = QtGui.QPushButton('open window', self)
        self.but1.clicked.connect(self.openWin)
        
        # Блок разметки
        self.mainLayout = QtGui.QVBoxLayout()
        
        self.mainLayout.addWidget(self.lab)
        self.mainLayout.addWidget(self.pole)
        self.mainLayout.addWidget(self.but1)
        
        self.setLayout(self.mainLayout)
 
    def openWin(self):
        if not self.secondWin:
            self.secondWin = mod.SecondWindow(self)
        self.secondWin.show() 
 
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
Модуль с именем “mod.py”:
 import sys 
from PyQt4 import QtGui, QtCore 
 
class SecondWindow(QtGui.QWidget):
    def __init__(self, parent=None):
        # Передаём ссылку на родительский элемент и чтобы виджет
        # отображался как самостоятельное окно указываем тип окна
        super().__init__(parent, QtCore.Qt.Window)
        self.build()
 
    def build(self):
        self.resize(100, 100)
        self.pole_2 = QtGui.QTextEdit()
        self.button_0 = QtGui.QPushButton('Жми')
        # Блок разметки
        self.mainLayout = QtGui.QVBoxLayout()        
        self.mainLayout.addWidget(self.pole_2)
        self.mainLayout.addWidget(self.button_0)
 
        self.setLayout(self.mainLayout)
        self.button_0.clicked.connect(self.on_click_1)
    def on_click_1(self, text):
        q = self.pole_2.toPlainText()
        self.pole.setText(str(q))
PEHDOM
вариант намбер раз: через калбекфункцию, котороую вы передадите дочке.
 import sys
from PyQt4 import QtGui, QtCore
import mod
class MainWindow(QtGui.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.secondWin = None
        self.build()
    def build(self):
        self.resize(300, 200)
        self.lab = QtGui.QLabel('simple text', self)
        self.pole = QtGui.QTextEdit()
        self.but1 = QtGui.QPushButton('open window', self)
        self.but1.clicked.connect(self.openWin)
        # Блок разметки
        self.mainLayout = QtGui.QVBoxLayout()
        self.mainLayout.addWidget(self.lab)
        self.mainLayout.addWidget(self.pole)
        self.mainLayout.addWidget(self.but1)
        self.setLayout(self.mainLayout)
    def openWin(self):
        if not self.secondWin:
            #передаем в качестве второго параметра  метод pasteText
            self.secondWin = mod.SecondWindow(self, self.pasteText) 
        self.secondWin.show()
    def pasteText(self,text):
        self.pole.setText(text)
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

 import sys
from PyQt4 import QtGui, QtCore
class SecondWindow(QtGui.QWidget):
    def __init__(self, parent=None, callback=None):   
        # Передаём ссылку на родительский элемент и чтобы виджет
        # отображался как самостоятельное окно указываем тип окна
        super().__init__(parent, QtCore.Qt.Window)
        self.build()
        self.callbackFunction = callback
    def build(self):
        self.resize(100, 100)
        self.pole_2 = QtGui.QTextEdit()
        self.button_0 = QtGui.QPushButton('Жми')
        # Блок разметки
        self.mainLayout = QtGui.QVBoxLayout()
        self.mainLayout.addWidget(self.pole_2)
        self.mainLayout.addWidget(self.button_0)
        self.setLayout(self.mainLayout)
        self.button_0.clicked.connect(self.on_click_1)
    def on_click_1(self, text):
        q = self.pole_2.toPlainText()
        #self.pole.setText(str(q))
        if self.callbackFunction:    # если передали калбек функцию вызываем ее..
            self.callbackFunction(q)

Вариант намбер ту: используя сигналы и слоты
 import sys
from PyQt4 import QtGui, QtCore
import mod
class MainWindow(QtGui.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.secondWin = None
        self.build()
    def build(self):
        self.resize(300, 200)
        self.lab = QtGui.QLabel('simple text', self)
        self.pole = QtGui.QTextEdit()
        self.but1 = QtGui.QPushButton('open window', self)
        self.but1.clicked.connect(self.openWin)
        # Блок разметки
        self.mainLayout = QtGui.QVBoxLayout()
        self.mainLayout.addWidget(self.lab)
        self.mainLayout.addWidget(self.pole)
        self.mainLayout.addWidget(self.but1)
        self.setLayout(self.mainLayout)
    def openWin(self):
        if not self.secondWin:
            self.secondWin = mod.SecondWindow(self)
            # соединяем сигнал sendText от дочернего окна с методом pasteText
            self.secondWin.sendText.connect(self.pasteText)
        self.secondWin.show()
    def pasteText(self,text):
        self.pole.setText(text)
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

 import sys
from PyQt4 import QtGui, QtCore
class SecondWindow(QtGui.QWidget):
    sendText = QtCore.pyqtSignal(str)  # сигнал
    def __init__(self, parent=None):
        # Передаём ссылку на родительский элемент и чтобы виджет
        # отображался как самостоятельное окно указываем тип окна
        super().__init__(parent, QtCore.Qt.Window)
        self.build()
    def build(self):
        self.resize(100, 100)
        self.pole_2 = QtGui.QTextEdit()
        self.button_0 = QtGui.QPushButton('Жми')
        # Блок разметки
        self.mainLayout = QtGui.QVBoxLayout()
        self.mainLayout.addWidget(self.pole_2)
        self.mainLayout.addWidget(self.button_0)
        self.setLayout(self.mainLayout)
        self.button_0.clicked.connect(self.on_click_1)
    def on_click_1(self, text):
        q = self.pole_2.toPlainText()
        #self.pole.setText(str(q))
        self.sendText.emit(q) #посылаем сигнал по клику

Варианет намбер три, получить родителя воспользовавшить ф-цей parent. Хотя это и не кошерно, так как подразумевает что дочернее окно должно знать методы родительского.
 import sys
from PyQt4 import QtGui, QtCore
class SecondWindow(QtGui.QWidget):
    def __init__(self, parent=None):
        # Передаём ссылку на родительский элемент и чтобы виджет
        # отображался как самостоятельное окно указываем тип окна
        super().__init__(parent, QtCore.Qt.Window)
        self.build()
        # так получаем сыылку на родительское окно
        self.parrent = self.parent()  
        # или можно даже так
        #self.parrent = parent
    def build(self):
        self.resize(100, 100)
        self.pole_2 = QtGui.QTextEdit()
        self.button_0 = QtGui.QPushButton('Жми')
        # Блок разметки
        self.mainLayout = QtGui.QVBoxLayout()
        self.mainLayout.addWidget(self.pole_2)
        self.mainLayout.addWidget(self.button_0)
        self.setLayout(self.mainLayout)
        self.button_0.clicked.connect(self.on_click_1)
    def on_click_1(self, text):
        q = self.pole_2.toPlainText()
        self.parrent.pole.setText(str(q)) # вызываем метод родительского окна
Вариант намбер четыре: использовать eventFilter тогда можно даже без кнопки обойтись и текст набраный в дочернем окне сразу будет появляться в родительсклм. но писать сейчас времени нету…
Rodegast
> через калбекфункцию
> используя сигналы и слоты
> получить родителя воспользовавшить ф-цей parent
> использовать eventFilter

Ну надо-же четыре варианта и не одного правильного. Это даже забавно…
MrViktor
Rodegast
Ну надо-же четыре варианта и не одного правильного. Это даже забавно…
Можно узнать правильный? а то что-то мне подсказывает, что все должно быть намного проще.
PEHDOM
Rodegast
Ну надо-же четыре варианта и не одного правильного. Это даже забавно…
Чтото я не виду вашего, “правильного”, варианта. Поделитесь? А то как то нехорошо получаеться, заинтриговать заинтриговали, а суть интриги не раскрыли.
Rodegast
Может быть вы и обратили внимание что я уже мало что пишу в эту ветку. А всё потому что я много раз писал что основное окно должно наследоваться от QMainWindow, а диалоговое от QDialog, что нельзя выносить часть конструктора в отдельный метод, что надо учится пользоваться дизайнером, а не пытаться “писать руками”. Но всем на это плевать. По этому если хотите правильный ответ, то читайте документацию про QDialog (особо внимательно нужно читать про методы exec_, reject и accept).
MrViktor
Rodegast
я много раз писал что основное окно должно наследоваться от QMainWindow, а диалоговое от QDialog
То есть, топик стартер на основе QWidget создает просто диалог? ну да, такой подход не понятен.
Для себя, я почерпнул информацию.
Rodegast
> топик стартер на основе QWidget создает просто диалог

Нет. Он создаёт просто окно и пытается использовать его как диалог.
PEHDOM
Rodegast
основное окно должно наследоваться от QMainWindow, а диалоговое от QDialog
это конечно правильно, но вопрос то , как я понял из примера в другом. Нужно было передать данные из дочернего окна в родительское, не закрывая дочернее(исходя из текста примера).

Rodegast
По этому если хотите правильный ответ, то читайте документацию про QDialog (особо внимательно нужно читать про методы exec_, reject b accept).
Угу, читали, вот только, reject() и accept() закрыввают дилоговое окно. Да и exec_ ничего кроме Accepted и Rejected возвращать не умеет.
А у топикстартера оно не должно закрываться после нажатия кнопки “Жми”. По крайней так можно подумать посмотрев его пример. Собственно если бы окно закрывалось проблем бы не было.
Соответвенно если вам нужно добавить в диалоговое окно кнопку “Apply” котороая передает главному окну новые данные, но не закрывает диалоговое окно, то какое “правильное” решение?
Rodegast
> А у топикстартера оно не должно закрываться после нажатия кнопки “Жми”

Должно. Он просто это не сделал.

> Соответвенно если вам нужно добавить в диалоговое окно кнопку “Apply” котороая передает главному окну новые данные но не закрывает диалоговое окно то какое “правильное” решение?

Правильное решение не делать кнопку “Apply” т.к. она добавляет не однозначность, а польза от неё весьма сомнительна. Но если очень сильно хочется странного, то никто не мешает переопределить метод accept, но тогда в ручную придётся вызывать QDialog.accept(self) при закрытиии окна.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB