On Tuesday, September 26, 2017 at 2:23:22 PM UTC+5:30, Thomas Jollans wrote: > On 2017-09-26 08:16, Veek M wrote: > > On Tuesday, September 26, 2017 at 11:18:54 AM UTC+5:30, Veek M wrote: > >> Summary: Could someone explain widget and dialog parenting - the text book > >> is not making sense. > >> ###################### > >> I'm trying to understand widget parenting, from the book: Rapid GUI > >> Programming, pg 118, and thereabouts - he says: > >> > >> A. All PyQt classes that derive from QObjectand this includes all the > >> widgets, > >> since QWidget is a QObject subclasscan have a “parent”. > >> > >> B. PyQt automatically repar- > >> ents the widgets that are laid out. So although we did not give our > >> widgets a > >> parent of self (the Form instance),when we call setLayout() the layout > >> manager > >> gives ownership of the widgets and of itself to the form,and takes > >> ownership of > >> any nested layouts itself. This means that none of the widgets that are > >> laid out > >> is a top-level window, and all of them have parents, which is what we > >> want. So > >> when the form is deleted, all its child widgets and layouts will be > >> deleted with > >> ----------------------------- > >> 1. In A, does he mean, you are ALLOWED to set a parent on a widget ONLY > >> because its Base Class is QObject? > >> > >> With DockWidgets, you have to explicitly parent them - why? > >> > >> 2. If I create two widgets and wdget.show() them, and app.exec_() - which > >> one becomes the main-window and which one is the memory leak? I have not > >> used a layout manager so, one widget with no parent auto-becomes the > >> main-window (as per B), which would result in a leak with the other? > >> > >> #!/usr/bin/python > >> > >> import sys, os, re > >> > >> > >> from PyQt4.QtCore import * > >> from PyQt4.QtGui import * > >> > >> app = QApplication(sys.argv) > >> > >> lbl = QLabel('<font size=11 color=red><b>Hello World</b></font>') > >> lbl.setWindowFlags(Qt.SplashScreen) > >> lbl.show() > >> txtBrw = QTextBrowser() > >> txtBrw.show() > >> > >> QTimer.singleShot(3000, app.quit) > >> app.exec_() > >> > >> 3. QObject --> QWidget --> QDialog --> Form --> Form_Layout_Manager --> > >> Nested_Layout_Manager > >> > >> B, says that the layout manager parents the widgets under it and makes > >> 'Form' the parent. If the Form Layout Manager is taking charge of the > >> Nested Layout Manager, who is the parent of the widgets under the Nested > >> Layout Mangaer? > >> > >> 4. In the Chapter on 'Dialogs', I am trying to create a QMainWindow Style > >> application with one label as the central widget and one button to invoke > >> a dialog. It doesn't work and I get: > >> > >> QWidget::setLayout: Attempting to set QLayout "" on Parent "", which > >> already has a layout > >> > >> I tried this link and it made no sense: > >> https://stackoverflow.com/questions/25450598/qlayout-attempting-to-add-qlayout-to-qwidget-which-already-has-a-layout > >> > >> How does parenting work in PyQt? What is autoparented, what needs to be > >> explicitly parented and who is scrwing whom? Additionally, why is my > >> button, hiding? > >> > >> > >> #!/usr/bin/python > >> > >> import sys, os, re > >> > >> > >> from PyQt4.QtCore import * > >> from PyQt4.QtGui import * > >> > >> app = QApplication(sys.argv) > >> > >> class Dialog(QDialog): > >> def __init__(self, parent = None): > >> super(Dialog, self).__init__(parent) > >> > >> self.lbl = QLabel('Width: ') > >> self.spn = QSpinBox() > >> self.spn.setRange(0, 100) > >> self.lbl.setBuddy(self.spn) > >> > >> self.chk = QCheckBox('&Beveled Edges') > >> > >> self.lbl_styl = QLabel('Style') > >> self.lst = QComboBox() > >> self.lst.addItems(['dashed', 'dotted', 'star']) > >> self.lbl_styl.setBuddy(self.lst) > >> > >> self.ok_btn = QPushButton('&Ok') > >> self.cncl_btn = QPushButton('&Cancel') > >> > >> self.layout([(self.lbl, 0, 0), (self.spn, 0, 1), (self.chk, 0, 2), > >> (self.lbl_styl, 1, 0), (self.lst, 1, 1), > >> (self.ok_btn, 2, 0), (self.cncl_btn, 2, 1)]) > >> > >> def layout(self, wgts = []): > >> self.lyt = QGridLayout() > >> for wgt, row, col in wgts: > >> self.lyt.addWidget(wgt, row, col) > >> > >> self.setLayout(self.lyt) > >> > >> > >> class Parent(QMainWindow): > >> def __init__(self, parent = None): > >> super(Parent, self).__init__(parent) > >> > >> lbl = QLabel('HELLO WORLD') > >> btn = QPushButton('&Start Dialog') > >> lbl.setBuddy(btn) > >> > >> lyt = QHBoxLayout() > >> lyt.addWidget(lbl) > >> lyt.addWidget(btn) > >> > >> self.setLayout(lyt) > >> self.connect(btn, SIGNAL('clicked()'), self.popup_dialog) > >> > >> def popup_dialog(self): > >> x = Dialog(self) > >> if x.exec_(): > >> print(x.spn.value()) > >> > >> p = Parent() > >> p.show() > >> > >> app.exec_() > > > > I fixed some of it by deleting the: > > Parent > > self.setLayout(lyt) > > > > I don't understand why that works - aren't we supposed to attach a layout > > to the Parent/MainWindow object? Why not? > > > > Also, I made the: > > Parent > > self.setCentralWidget(btn) > > IIRC, QMainWindow is a bit weird, since it provides things like menu and > status bars. Everything normally goes into a "central widget". > > The (or: a) thing to do is (I suspect): > > class Parent(QMainWindow): > def __init__(self, parent=None): > # This is the future. super() is smart now. > super().__init__(parent) > > lbl = QLabel('HELLO WORLD') > btn = QPushButton('&Start Dialog') > lbl.setBuddy(btn) > > lyt = QHBoxLayout() > lyt.addWidget(lbl) > lyt.addWidget(btn) > > central_widget = QWidget() > central_widget.setLayout(lyt) > self.setCentralWidget(central_widget) > > # Use new-style signals and slots! They're nicer! > btn.clicked.connect(self.popup_dialog) > > def popup_dialog(self): > x = Dialog(self) > if x.exec_(): > print(x.spn.value()) > > I normally like to explicitly parent my widgets on construction, but > that's not necessary and I'm probably doing it wrong anyway. > > Aside: I notice you're using PyQt4. That's great, I do too (for now), > but I suggest you consider moving to PyQt5. PyQt4 is slowly > disappearing. Anaconda (on Windows at least) has annoying dependency > structures that force you to use old versions of the scientific python > stack if you want to use qt4. I'm going to have to upgrade soon. > > The differences between PyQt4 and PyQt5 aren't massive, but they've > moved around some classes (QtGui has been split into two packages, which > is going to be annoying to migrate) and support for old-style signal and > slot syntax has been dropped (good riddance). > > Also, if you're using Python 2: don't. Just don't. It's not 2012 any > more. (I don't know what you're using, but /usr/bin/python is normally > Python 2) > > > > > so the button is the central widget. To use the Label, I think I would have > > to create a composite widget which is too complicated for me, currently. > > > > Now. it works so I tested some more and added: > > def popup_dialog(self): > > x = Dialog(self) > > y = Dialog(self) > > y.show() > > if x.exec_(): > > print(x.spn.value()) > > AND > > > > class Dialog(QDialog): > > self.connect(self.cncl_btn, SIGNAL('clicked()'), self.close) > > > > So my dialog pops up and because exec_ is being called on 'x', I have to > > first close that widget before I can interact with my button and 'y'. > > However, let's say I close the 'x' dialog - then I can click on 'Button' > > and I get two more dialogs which don't lock anything - why?? > > > > > -- > Thomas Jollans
Thanks - i'm on debian stretch so python 2.7 is what I use. Right now, my book deals with PyQt4 so I thought I'd stick with that, till I get a hang of things. The book I'm using is good but not great - he's over complicated things with really verbose examples of simple stuff, instead of conveying a central idea eg: dump, smart and standard dialogs are mostly the same thing and the central idea could be conveyed in a few lines but he's got some huge examples spread over pages, that's mostly unnecessary. I found the PyQt docs to be very clear but right now, I dare not stray. There's a russian book on PyQt5 that looks nice but there's no way to translate it: Python 3 and pyqt 5 application development - prokhorenok n.a -- https://mail.python.org/mailman/listinfo/python-list