Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » GUI
  • » PyQt4 | Как передать сигнал из дочернего окна в родительское? [RSS Feed]

#1 Март 2, 2017 15:24:22

Kyrym
Зарегистрирован: 2016-12-28
Сообщения: 225
Репутация: +  3  -
Профиль   Отправить e-mail  

PyQt4 | Как передать сигнал из дочернего окна в родительское?

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))

Отредактировано Kyrym (Март 2, 2017 15:25:42)

Офлайн

#2 Март 7, 2017 21:51:43

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

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:
            #передаем в качестве второго параметра  метод 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 тогда можно даже без кнопки обойтись и текст набраный в дочернем окне сразу будет появляться в родительсклм. но писать сейчас времени нету…



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Отредактировано PEHDOM (Март 8, 2017 10:05:03)

Офлайн

#3 Март 9, 2017 09:42:39

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2683
Репутация: +  182  -
Профиль   Отправить e-mail  

PyQt4 | Как передать сигнал из дочернего окна в родительское?

> через калбекфункцию
> используя сигналы и слоты
> получить родителя воспользовавшить ф-цей parent
> использовать eventFilter

Ну надо-же четыре варианта и не одного правильного. Это даже забавно…



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#4 Март 9, 2017 10:36:31

MrViktor
Зарегистрирован: 2017-03-09
Сообщения: 83
Репутация: +  8  -
Профиль   Отправить e-mail  

PyQt4 | Как передать сигнал из дочернего окна в родительское?

Rodegast
Ну надо-же четыре варианта и не одного правильного. Это даже забавно…
Можно узнать правильный? а то что-то мне подсказывает, что все должно быть намного проще.

Офлайн

#5 Март 9, 2017 11:32:12

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

PyQt4 | Как передать сигнал из дочернего окна в родительское?

Rodegast
Ну надо-же четыре варианта и не одного правильного. Это даже забавно…
Чтото я не виду вашего, “правильного”, варианта. Поделитесь? А то как то нехорошо получаеться, заинтриговать заинтриговали, а суть интриги не раскрыли.



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Офлайн

#6 Март 9, 2017 13:54:42

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2683
Репутация: +  182  -
Профиль   Отправить e-mail  

PyQt4 | Как передать сигнал из дочернего окна в родительское?

Может быть вы и обратили внимание что я уже мало что пишу в эту ветку. А всё потому что я много раз писал что основное окно должно наследоваться от QMainWindow, а диалоговое от QDialog, что нельзя выносить часть конструктора в отдельный метод, что надо учится пользоваться дизайнером, а не пытаться “писать руками”. Но всем на это плевать. По этому если хотите правильный ответ, то читайте документацию про QDialog (особо внимательно нужно читать про методы exec_, reject и accept).



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Отредактировано Rodegast (Март 9, 2017 15:22:35)

Офлайн

#7 Март 9, 2017 14:08:56

MrViktor
Зарегистрирован: 2017-03-09
Сообщения: 83
Репутация: +  8  -
Профиль   Отправить e-mail  

PyQt4 | Как передать сигнал из дочернего окна в родительское?

Rodegast
я много раз писал что основное окно должно наследоваться от QMainWindow, а диалоговое от QDialog
То есть, топик стартер на основе QWidget создает просто диалог? ну да, такой подход не понятен.
Для себя, я почерпнул информацию.

Офлайн

#8 Март 9, 2017 15:18:32

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2683
Репутация: +  182  -
Профиль   Отправить e-mail  

PyQt4 | Как передать сигнал из дочернего окна в родительское?

> топик стартер на основе QWidget создает просто диалог

Нет. Он создаёт просто окно и пытается использовать его как диалог.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#9 Март 9, 2017 15:40:51

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

PyQt4 | Как передать сигнал из дочернего окна в родительское?

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

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



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Отредактировано PEHDOM (Март 9, 2017 15:53:59)

Офлайн

#10 Март 9, 2017 16:15:52

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2683
Репутация: +  182  -
Профиль   Отправить e-mail  

PyQt4 | Как передать сигнал из дочернего окна в родительское?

> А у топикстартера оно не должно закрываться после нажатия кнопки “Жми”

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

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

Правильное решение не делать кнопку “Apply” т.к. она добавляет не однозначность, а польза от неё весьма сомнительна. Но если очень сильно хочется странного, то никто не мешает переопределить метод accept, но тогда в ручную придётся вызывать QDialog.accept(self) при закрытиии окна.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Отредактировано Rodegast (Март 9, 2017 16:25:26)

Офлайн

  • Начало
  • » GUI
  • » PyQt4 | Как передать сигнал из дочернего окна в родительское? [RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version