How to avoid the child QMainWindow disappearing? - pyqt

When I click the button, "ChildWindow" will flash and disappear. Then If I add the function exec_(), it will report an "AttributeError" because "QMainWindow" don't have this attribute.
How to modify the function "showChildWindow" so that it can work well? Thank you.
import sys
from PyQt4 import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowTitle("MainWindow Window!")
self.setGeometry(400, 400, 100, 100)
self.centerWidget = QtGui.QWidget()
self.setCentralWidget(self.centerWidget)
self.pushButton = QtGui.QPushButton("&Button")
layout = QtGui.QVBoxLayout()
layout.addWidget(self.pushButton)
self.centerWidget.setLayout(layout)
class ChildWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowTitle("Child Window!")
def showChildWindow():
mw = MainWindow()
child_win = ChildWindow(mw)
child_win.show()
#child_win.exec_() #AttributeError: 'ChildWindow' object has no attribute 'exec_'
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MainWindow()
myapp.show()
QtCore.QObject.connect(myapp.pushButton,QtCore.SIGNAL("clicked()"),showChildWindow)
sys.exit(app.exec_())
This program can work well.
import sys
from PyQt4 import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowTitle("MainWindow Window!")
self.setGeometry(400, 400, 100, 100)
self.centerWidget = QtGui.QWidget()
self.setCentralWidget(self.centerWidget)
pushButton = QtGui.QPushButton("&Button")
layout = QtGui.QVBoxLayout()
layout.addWidget(pushButton)
self.centerWidget.setLayout(layout)
QtCore.QObject.connect(pushButton,QtCore.SIGNAL("clicked()"),self.showChildWindow)
def showChildWindow(self):
self.child_win = ChildWindow(self)
self.child_win.show()
class ChildWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowTitle("Child Window!")
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MainWindow()
myapp.show()
sys.exit(app.exec_())

The real question appears to be: how do I access the main-window from other modules in my application?
My preferred general solution to this problem is to sub-class QApplication and add a simple accessor method, like this:
class Application(QtGui.QApplication):
def __init__(self):
QtGui.QApplication.__init__(self, sys.argv)
self._window = None
def window(self):
if self._window is None:
self._window = MainWindow()
return self._window
if __name__ == "__main__":
app = QtGui.qApp = Application()
app.window().show()
sys.exit(app.exec_())
With that in place, you can easily get access the methods of the main-window in other modules like this:
from PyQt4 import QtGui
QtGui.qApp.window().showChildWindow()

I had the same problem. The child QMainWindow would randomly disappear while interacting with the parent window.
This is the bad source code that causes this problem:
def showChildWindow(self):
child_win = ChildWindow()
child_win.show()
This is the good source code that fixes the problem:
def showChildWindow(self):
child_win = ChildWindow(self)
child_win.show()
When you instantiate the child window, make sure you pass the parent self.

Related

pyqt signal from a window not changing the main window widgets

I can pass values between two windows using signal,
and I want the plain text change, while I press a button from another window.
but the insertPlainText and even text.show() are not working
I've tried sending the signal to the init part of the Mainwindow,
tried update, repaint, but none of them works.
appreciate for any of your help, thanks!
the search_send method in class SearchWindow to MainWindow method test_
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.tag_box.hide()
def test_(self, i): # -------problem here------------------
print(i) // <- value here were right
self.ui.tag_box.insertPlainText(i) # -------Plain Text does not change-------
self.ui.tag_box.show()# -------Plain Text does not show either--------------
class SearchWindow(QtWidgets.QMainWindow):
signal=pyqtSignal(str)
def __init__(self, endpoint=None, user=None, password=None, points_link=None):
super(SearchWindow, self).__init__()
self.ui = Ui_Search()
self.ui.setupUi(self)
self.ui.pushButton_2.clicked.connect(self.search_send)
def search_send(self): # -------problem here------------------
tag_list = [tag1,tag2, tag3]
otherClass = MainWindow()
self.signal.connect(otherClass.test_)
for k in tag_list:
self.signal.emit(k)
if __name__ == '__main__':
app = QtWidgets.QApplication([])
window = MainWindow()
window.show()
sys.exit(app.exec_())
As we're unclear what Ui_Dialog contains, I can't tell what's wrong exactly, but can show you how Signal should be used.
This is example of Signal that's transferring text to Slot. Name may differ in PyQt5 - change accordingly.
from PySide2.QtWidgets import QWidget, QApplication, QPlainTextEdit, QTextEdit, QVBoxLayout
from PySide2.QtCore import Signal, Slot
import sys
class MainWindow(QWidget):
sig = Signal(str)
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle("Main")
self.layout = QVBoxLayout()
self.text = QTextEdit()
self.layout.addWidget(self.text)
self.setLayout(self.layout)
self.text.textChanged.connect(self.onChange)
def onChange(self):
self.sig.emit(self.text.toPlainText())
class SubWindow(QWidget):
def __init__(self, connect_target: MainWindow):
super(SubWindow, self).__init__()
self.setWindowTitle("Sub")
self.layout = QVBoxLayout()
self.text = QPlainTextEdit()
self.layout.addWidget(self.text)
self.setLayout(self.layout)
connect_target.sig.connect(self.onSignal)
#Slot(str)
def onSignal(self, text):
self.text.insertPlainText(text + '\r\n')
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
window_sub = SubWindow(window)
window_sub.show()
sys.exit(app.exec_())
Anything inside Main will be inserted to QPlainTextEdit as you wanted.

Show sub window in main window

Can't work out how to embed a window in a main window using classes:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
Qt4 tutorial using classes
This example will be built
on over time.
"""
import sys
from PyQt4 import QtGui, QtCore
class Form(QtGui.QWidget):
def __init__(self, MainWindow):
super(Form, self).__init__()
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__()
self.setGeometry(50, 50, 1600, 900)
new_window = Form(self)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
main_window = MainWindow()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
This is supposed to be the single most basic bit of code using classes. How do I get the second window to show please.
As ekhumoro already pointed out, your widget needs to be a child of your mainWindow. However, I do not think that you need to call show for the widget, since it anyways gets called as soon as its parent (MainWindow) calls show. As mata pointed out correctly, the proper way to add a Widget to a MainWindow instance is to use setCentralWidget. Here is a working example for clarification:
import sys
from PyQt4 import QtGui, QtCore
class Form(QtGui.QWidget):
def __init__(self, parent):
super(Form, self).__init__(parent)
self.lbl = QtGui.QLabel("Test", self)
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__()
self.setGeometry(50, 50, 1600, 900)
new_window = Form(self)
self.setCentralWidget(new_window)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
main_window = MainWindow()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

TypeError: 'QLabel' object is not callable

When I run the demo program as below, the mainwindow will call the childwindow, then the childwindow will call a widget. I want to get some attribute of this widget such as "messageLabel",but it will report an error that TypeError: 'QLabel' object is not callable. Then how to modify this error? Thank you,
import sys
from PyQt4 import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__()
self.setWindowTitle("MainWindow Window!")
self.setGeometry(400, 400, 100, 100)
self.centerWidget = QtGui.QWidget()
self.setCentralWidget(self.centerWidget)
self.pushButton = QtGui.QPushButton("&Button")
layout = QtGui.QVBoxLayout()
layout.addWidget(self.pushButton)
self.centerWidget.setLayout(layout)
class ChildWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(ChildWindow, self).__init__(parent)
#QtGui.QMainWindow.__init__(self, parent)
self.setWindowTitle("Child Window!")
self.centerWidget = Widget(parent)
self.setCentralWidget(self.centerWidget)
class Widget(QtGui.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__()
self.messageLabel = QtGui.QLabel()
self.messageLabel.setText("How to get this message label?")
layout = QtGui.QVBoxLayout()
layout.addWidget(self.messageLabel)
self.setLayout(layout)
app = QtGui.QApplication(sys.argv)
myapp = MainWindow()
def showChildWindow():
child_win = ChildWindow(myapp)
child_win.show()
childLabel = child_win.centerWidget.messageLabel().text().__str__().__str__() #how to call the messageLabel?
print childLabel
myapp.show()
QtCore.QObject.connect(myapp.pushButton,QtCore.SIGNAL("clicked()"),showChildWindow)
sys.exit(app.exec_())

PyQt keyPressEvent not triggered from QDialog

I have a simple example of of a dialog window that has the keyPressEvent method. However, no matter what is typed when the sub window has focus, the event is not triggered.
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import PyQt4.Qt
class KpeWindow(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
main = QVBoxLayout(self)
label = QLabel(self)
label.setText('Test the keyPressEvent')
self.adjustSize()
self.setLayout(main)
def keyPressEvent(self, event):
QMessageBox.warning(self, 'MDI', 'keyPressEvent')
super().keyPressEvent(event)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('KeyPressEvent Test')
child = KpeWindow()
self.setCentralWidget(child)
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())
The following code works:
class KpeWindow(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self,parent)
main = QVBoxLayout(self)
label = QLabel(self)
label.setText('Test the keyPressEvent')
main.addWidget(label)
self.adjustSize()
self.setLayout(main)
def keyPressEvent(self, event):
QMessageBox.warning(self, 'MDI', 'keyPressEvent')
self.parent().keyPressEvent(event)
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setWindowTitle('KeyPressEvent Test')
main = QVBoxLayout(self)
child = KpeWindow(self)
child.setFocusPolicy(Qt.StrongFocus)
self.setFocusProxy(child)
main.addWidget(child)
child.setFocus(True)
self.adjustSize()
self.setLayout(main)
I am not sure which of my changes work, I suspect setFocusProxy. In general I would recommend using QWidget as the child, and putting things into layouts even when there are no siblings.
The keyPressEvent is sensitive to the focus policy. In your example, the event is going to the QMainWindow (if you move the keyPressEvent to there, it does receive key events).
Is there any reason to have a dialog within a window? If you launch the dialog in the usual way, using child.show(), child.exec_() instead of setCentralWidget, it shows in a separate window and captures the key event.

How can I by default have all text selected in my lineEdit?

I'd like to be able to have all text highlighted in my lineEdit. However, the default selectAll() doesn't seem to do so.
import sys
from PyQt4 import QtCore, QtGui
from gui import Ui_Form
class MyForm(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
self.ui.lineEdit.setText("Type something here!")
self.ui.lineEdit.selectAll()
QtCore.QObject.connect(self.ui.pushButton, QtCore.SIGNAL("clicked()"), self.ui.textEdit.clear)
QtCore.QObject.connect(self.ui.lineEdit, QtCore.SIGNAL("returnPressed()"), self.add_entry)
def add_entry(self):
self.ui.lineEdit.selectAll()
self.ui.lineEdit.cut()
self.ui.textEdit.append("")
self.ui.textEdit.paste()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
I want to select the text on the lineEdit in the default constructor; however, it doesn't. Any reason for this? What should I be doing instead to accomplish this?

Resources