Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Insert widget inside an other widget



  • I need insert widget inside an other widget (see picture):

    1.jpg

    This implementation has graphic bugs (see picture, the right side of the widget).

    There is a main element of QListWidget. A QVBoxLayout has been assigned to it. 3 elements are inserted into QVBoxLayout: QHBoxLayout, Spacer and another QHBoxLayout. In the upper QHBoxLayout on the left is a Spacer, and on the right is QLineEdit (see picture). The lower QHBoxLayout is about the same, but instead of the QLineEdit there is a button with a "+".

    Source:

    def _setupViewWidget(self, obj):
            self.list_layout = QtWidgets.QVBoxLayout(obj)
            self.upper_spacer = QtWidgets.QSpacerItem(
                10, 10,
                QtWidgets.QSizePolicy.Minimum,
                QtWidgets.QSizePolicy.Expanding)
     
            self.list_layout.addItem(self.upper_spacer)
            self.bottom_layout = QtWidgets.QHBoxLayout()
     
            self.list_layout.addLayout(self.bottom_layout)
            self.add_button = QtWidgets.QPushButton("+")
     
            self.horizont_spacer = QtWidgets.QSpacerItem(
                10, 10,
                QtWidgets.QSizePolicy.Expanding,
                QtWidgets.QSizePolicy.Minimum)
            self.bottom_layout.addItem(self.horizont_spacer)
            self.bottom_layout.addWidget(self.add_button)
     
            self.top_layout = QtWidgets.QHBoxLayout()
            self.search_line = QtWidgets.QLineEdit('Поиск')
            self.horizont_spacer_2 = QtWidgets.QSpacerItem(
                10, 10,
                QtWidgets.QSizePolicy.Expanding,
                QtWidgets.QSizePolicy.Minimum)
            self.top_layout.addItem(self.horizont_spacer_2)
            self.top_layout.addWidget(self.search_line)
            self.top_layout.setStretch(0, 2)
            self.top_layout.setStretch(1, 1)
     
            self.list_layout.insertLayout(0, self.top_layout)
    

    Is it "correctly" implemented? And how to get rid of bugs?


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Why are you putting a layout on a QListWidget ?



  • @SGaist i want to insert a QLineEdit and a button into QListWidget. Button is needed to add items to the QListWidget. QLineEdit is needed to search for items in QListWidget.


  • Lifetime Qt Champion

    It would be cleaner to put the line edit on top of the QListWidget and the add button under its bottom.

    QListWidget is typically a widget used within a layout and not with a layout on it.



  • @SGaist Your suggestion is logical, but I need the same design as in the picture.


  • Lifetime Qt Champion

    I that case you are likely better off by positioning them manually rather than in a widget. Use the resize event of your QTableWidget to position them correctly with regard to the size of it.



  • @SGaist I do not understand what you mean. Can you please give some example?


  • Lifetime Qt Champion

    Do not use a layout and position the widgets by hand using its geometry.



  • @SGaist well, i did it (i removed the layout), but this implementation also has graphic bugs.

    class QList(QtWidgets.QListWidget):
        def __init__(self, *args, **args2):
            super(QList, self).__init__(*args, **args2)
            self.button = QtWidgets.QPushButton('Test', parent=self)
    
        def resizeEvent(self, event):
            self.button.move(100, 100)
    
    

    Снимок экрана 2020-04-05 в 0.56.12.png


  • Lifetime Qt Champion

    Don't forget to call the base class implementation of the methods you overload.


  • Banned

    @SangreSan when adding a widget into a QListWidget it is easiest to subclass this complex Widget and than add that complex Widget as a single item into the QListWidget -- this works fine as I have done it and I have taught a few others how to do this if you need more details on this just ask



  • @Denni-0 It seems that I did such an implementation. but if it’s not difficult for you, show your implementation.

    I also found another way using qgraphicsview:

    from PyQt5.QtWidgets import (qApp,QMainWindow, QApplication,
    QGraphicsScene,QGraphicsView, QListWidget, QLineEdit, QPushButton)
    from PyQt5.QtCore import Qt,QRectF
     
     
    class View(QMainWindow):
        def __init__(self):
            super().__init__()
            self.scene = QGraphicsScene()
            self.view = QGraphicsView(self.scene)
            self.setCentralWidget(self.view)
            lst = QListWidget()
            lst.addItems([str(i) for i in range(100,200)])
            lst.setAlternatingRowColors(True)
            line = QLineEdit()
            btn = QPushButton('+')
            self.proxyList = self.scene.addWidget(lst)   
            self.proxyLine = self.scene.addWidget(line)
            self.proxyBtn = self.scene.addWidget(btn)
        
        def resizeEvent(self,e):
            w,h = self.view.width(),self.view.height()
            self.view.setSceneRect(0,0,w,h)
            self.proxyList.setGeometry(QRectF(0,0,w,h))   
            self.proxyLine.setGeometry(QRectF(w - 210,10,200,20)) 
            self.proxyBtn.setGeometry(QRectF(w - 50,h - 30,20,20))
     
        def closeEvent(self,e):
            qApp.quit()
            
    if __name__ == '__main__':
        import sys
        app = QApplication([])
        w = View()
        w.resize(800,600)
        w.show()
        sys.exit(app.exec_())
    

    This implementation has a boundary line around the button:
    Снимок экрана 2020-04-05 в 22.44.36.png



  • @SangreSan I solved the problem with displaying the button through setstylesheet:

    QPushButton#addButton {
        background-color: rgba(134, 134, 134, 0.3);
        border-style: outset;
        border-width: 2px;
        border-color: rgba(20, 20, 20, 0.3);
        color: white;
    }
     
    QPushButton::pressed#addButton {
        background-color: rgba(0, 0, 0, 0.3);
        border-style: outset;
        border-width: 2px;
        border-color: rgba(20, 20, 20, 0.3);
        color: white;
    }
    

Log in to reply