Search code examples
pythonpyqtpyqt5pyqtgraphcustom-widgets

PyQt5 - Custom widgets open in separate windows rather than in same window


I'm new at PyQt, and I'm trying to create a main window containing two custom widgets, the first being a data grapher, the second being a QGridLayout containing QLabels. Problem is: the two widgets open in separate windows and have no content.

I've found multiple posts with a similar problem:

But I haven't been able to figure out why my code doesn't work. My aim is to obtain a result as shown below on the left, but instead I'm getting a result as shown on the right:

enter image description here

My code is the following (can be copied and run as it is):

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget, QGridLayout
from PyQt5.QtGui import QFont
import sys
import pyqtgraph as pg


class CustomWidget_1(QWidget):
   def __init__(self):
      super(CustomWidget_1, self).__init__()
      self.channels = [1, 2, 3, 4, 5, 6, 7, 8]
      self.win = pg.GraphicsLayoutWidget(title='Plot', size=(800, 600))
      self.plots = list()
      self.curves = list()
      for i in range(len(self.channels)):
         p = self.win.addPlot(row=i, col=0)
         p.showAxis('left', False)
         p.setMenuEnabled('left', False)
         p.showAxis('bottom', False)
         p.setMenuEnabled('bottom', False)
         self.plots.append(p)
         curve = p.plot()
         self.curves.append(curve)
      self.win.show()
      print('CustomWidget_1 initialized.')

class CustomWidget_2(QWidget):
   def __init__(self, labelnames):
      super(CustomWidget_2, self).__init__()
      self.grid = QGridLayout()
      self.labelnames = labelnames
      self.qlabels = []
      for label in self.labelnames:
         labelBox = QLabel(label)
         labelBox.setFont(QFont('Arial', 16))
         labelBox.setStyleSheet('border: 2px solid black;')
         labelBox.setAlignment(Qt.AlignCenter)
         self.qlabels.append(labelBox)
         index = self.labelnames.index(label)
         q, r = divmod(index, 6)
         self.grid.addWidget(labelBox, q, r)
      print('CustomWidget_2 initialized.')


class MainWindow(QWidget):
   def __init__(self):
      super(MainWindow, self).__init__()

      self.labelnames = ['label 1', 'label 2', 'label 3']
      
      self.CustomWidget_1 = CustomWidget_1()
      self.CustomWidget_1.setParent(self)
      self.CustomWidget_1.show()

      self.CustomWidget_2 = CustomWidget_2(self.labelnames)
      self.CustomWidget_2.setParent(self)
      self.CustomWidget_2.show()

      self.mainLayout = QVBoxLayout()
      self.mainLayout.addWidget(self.CustomWidget_1)
      self.mainLayout.addWidget(self.CustomWidget_2)
      self.setLayout(self.mainLayout)

      self.show()


if __name__ == '__main__':
   app = QApplication(sys.argv)
   predictVisualizer = MainWindow()
   sys.exit(app.exec())

Could anyone tell me what I'm doing wrong and how I could fix it? Any pointers towards tutorials and/or templates would be greatly appreciated as well! Thanks!


Solution

  • you should write fewer lines of code and debug slowly, if you are new to pyqt5 you should read carefully the basic Layout creation, like you are creating a website interface, link: https://www.pythonguis.com/tutorials/pyqt-layouts/

    This is the code I have edited, you can can refer:

    import sys
    from PyQt5.QtCore import QSize,Qt
    from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget,QGridLayout,QVBoxLayout,QLabel,QHBoxLayout
    from PyQt5.QtGui import QPalette, QColor
    
    class CustomWidget_1(QWidget):
        def __init__(self,color):
            super(CustomWidget_1, self).__init__()
            
            self.setAutoFillBackground(True)
            layout = QGridLayout()
            self.setLayout(layout)
            self.setFixedSize(QSize(400,300))
            
            palette = self.palette()
            palette.setColor(QPalette.Window, QColor(color))
            self.setPalette(palette)        
    
    class CustomWidget_2(QWidget):
        def __init__(self,color):
            super(CustomWidget_2, self).__init__()
            
            self.setAutoFillBackground(True)
            layout = QHBoxLayout()
            self.setLayout(layout)
            self.setFixedSize(QSize(400,134))
            layout.setContentsMargins(70,0,0,0)
            
            palette = self.palette()
            palette.setColor(QPalette.Window, QColor(color))
            self.setPalette(palette)
            
            Label1 = QLabel()
            Label1.setText('abc')
            Label2 = QLabel()
            Label2.setText('sad')
            Label3 = QLabel()
            Label3.setText('qv')        
            layout.addWidget(Label1)
            layout.addWidget(Label2)
            layout.addWidget(Label3)
      
    class MainWindow(QMainWindow):
    
        def __init__(self):
            super(MainWindow, self).__init__()
    
            self.setWindowTitle("My App")
    
            layout = QVBoxLayout()
            
            layout.addWidget(CustomWidget_1("blue"))
            layout.addWidget(CustomWidget_2("red"))
    
            widget = QWidget()
            widget.setLayout(layout)
            self.setCentralWidget(widget)
    
    app = QApplication(sys.argv)
    
    window = MainWindow()
    window.show()
    
    app.exec()