Как установить пользовательский виджет на QMainWindow в PyQt5

Я пытаюсь, чтобы пользовательский виджет отображался в главном окне pyQT, но по какой-то причине я получаю два окна вместо пользовательского виджета, определенного в функциях лет, то есть поле со списком, которое можно установить в диалоговом окне Dialog_01 (главное окно). Ниже мой код. Оцените, если у кого-то есть какие-либо указания или документы, в которых я могу найти

import sys
from PyQt5 import QtGui, QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu, QVBoxLayout, QSizePolicy, QMessageBox, QWidget, QPushButton
from PyQt5 import QtWidgets
class CheckableComboBox(QtWidgets.QComboBox):
    closedPopup = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(CheckableComboBox, self).__init__(parent)
        self.setView(QtWidgets.QListView(self))
        self.view().pressed.connect(self.handleItemPressed)
        self.setModel(QtGui.QStandardItemModel(self))

        firstItem = QtGui.QStandardItem("Select Years")
        firstItem.setBackground(QtGui.QBrush(QtGui.QColor(200, 200, 200)))
        firstItem.setSelectable(False)
        self.model().appendRow(firstItem)

    @QtCore.pyqtSlot(QtCore.QModelIndex)
    def handleItemPressed(self, index):
        item = self.model().itemFromIndex(index)
        if item.checkState() == QtCore.Qt.Checked:
            item.setCheckState(QtCore.Qt.Unchecked)
        else:
            item.setCheckState(QtCore.Qt.Checked)

    def checkedItems(self):
        l = []
        for i in range(self.model().rowCount()):
            it = self.model().item(i)
            if it.checkState() == QtCore.Qt.Checked:
                l.append(it.text())
        return l

    def hidePopup(self):
        self.closedPopup.emit()
        super(CheckableComboBox, self).hidePopup()
        QtCore.QTimer.singleShot(0, lambda: self.setCurrentIndex(0))
class Dialog_01(QMainWindow):
    def __init__(self):
        super().__init__()
        self.title = "Title"  
        self.top = 100        
        self.left = 100        
        self.width = 800      
        self.height = 500
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.top, self.left, self.width, self.height)
        self.years()
        self.location()
        self.MaxYears()

        self.layout = QtWidgets.QVBoxLayout(self)
        self.listWidget = self.comboBoxv
        self.layout.addWidget(self.listWidget)
        self.listWidget.show()
    def years(self):
        label0 = QLabel('Years', self)
        label0.move(50,50)
        label0.setGeometry(50,50,500,20)

        years = ["2017", "2018", "2019", "2020", "2021", "2022"]
        self.comboBoxv = CheckableComboBox()
        for i, area in enumerate(years):
            item = QtGui.QStandardItem(area)
            item.setCheckable(True)
            item.setCheckState(QtCore.Qt.Unchecked)
            self.comboBoxv.model().appendRow(item)        
        self.layout = QtWidgets.QVBoxLayout(self)
        self.setLayout(self.layout)
        self.listWidget = self.comboBoxv
        self.layout.addWidget(self.listWidget)
        self.listWidget.move(300, 50)


    @QtCore.pyqtSlot()
    def on_closedPopup(self):
        print(len(self.comboBoxv.checkedItems()))


    def location(self):  
        label1 = QLabel('Location', self)
        label1.move(50,150)
        label1.setGeometry(50,150,500,20)
        comboBox1 = QComboBox(self)
        for i in range(1,15):
            comboBox1.addItem("LOCATION %i" % i)
        comboBox1.move(300, 150)
        self.locationDrop=comboBox1
    def MaxYears(self):
        label2 = QLabel('Maximum Years', self)
        label2.move(50,250)
        label2.setGeometry(50,250,500,20)
        comboBox2 = QComboBox(self)
        for i in range(1, 10):
            comboBox2.addItem(str(i))
        comboBox2.move(300, 250)
        self.maxyearsDrop=comboBox2

if __name__ == '__main__':

    if not QApplication.instance():
        App = QApplication(sys.argv)
    else:
        App = QApplication.instance()
    ui = Dialog_01()
    ui.show()
    sys.exit(App.exec_())

1 ответ

Решение

Вы должны понимать, что программирование не помещает бессмысленный код, например: что вы пытались сделать self.listWidget = self.comboBoxv ? Как и выше, есть несколько несоответствий.


С другой стороны, QMainWindow - это специальный виджет, поскольку он уже имеет макет:

Таким образом, вы должны создать центральный виджет, где вы устанавливаете макет.


Если вы собираетесь использовать макеты, вам больше не следует использовать методы геометрии, перемещения или изменения размера, поскольку макет будет обрабатывать эти свойства.


С другой стороны, я думаю, что вы хотите создать формулу, в которой есть описание и редактор, в этом случае Qt предоставляет QFormLayout.


import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class CheckableComboBox(QtWidgets.QComboBox):
    closedPopup = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(CheckableComboBox, self).__init__(parent)
        self.setView(QtWidgets.QListView(self))
        self.view().pressed.connect(self.handleItemPressed)
        self.setModel(QtGui.QStandardItemModel(self))

        firstItem = QtGui.QStandardItem("Select Years")
        firstItem.setBackground(QtGui.QBrush(QtGui.QColor(200, 200, 200)))
        firstItem.setSelectable(False)
        self.model().appendRow(firstItem)

    @QtCore.pyqtSlot(QtCore.QModelIndex)
    def handleItemPressed(self, index):
        item = self.model().itemFromIndex(index)
        if item.checkState() == QtCore.Qt.Checked:
            item.setCheckState(QtCore.Qt.Unchecked)
        else:
            item.setCheckState(QtCore.Qt.Checked)

    def checkedItems(self):
        l = []
        for i in range(self.model().rowCount()):
            it = self.model().item(i)
            if it.checkState() == QtCore.Qt.Checked:
                l.append(it.text())
        return l

    def hidePopup(self):
        self.closedPopup.emit()
        super(CheckableComboBox, self).hidePopup()
        QtCore.QTimer.singleShot(0, lambda: self.setCurrentIndex(0))

class Dialog_01(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.title = "Title"  
        self.top, self.left, self.width, self.height = 100, 100, 800, 500
        self.initUI()

    def initUI(self):
        central_widget = QtWidgets.QWidget()
        self.flayout = QtWidgets.QFormLayout(central_widget)
        self.setCentralWidget(central_widget)

        self.setWindowTitle(self.title)
        self.setGeometry(self.top, self.left, self.width, self.height)
        self.years()
        self.location()
        self.MaxYears()

    def years(self):
        label = QtWidgets.QLabel('Years')

        years = ["2017", "2018", "2019", "2020", "2021", "2022"]
        self.comboBoxv = CheckableComboBox()
        for i, area in enumerate(years):
            item = QtGui.QStandardItem(area)
            item.setCheckable(True)
            item.setCheckState(QtCore.Qt.Unchecked)
            self.comboBoxv.model().appendRow(item)
        self.flayout.addRow(label, self.comboBoxv)

    @QtCore.pyqtSlot()
    def on_closedPopup(self):
        print(len(self.comboBoxv.checkedItems()))

    def location(self):  
        label = QtWidgets.QLabel('Location')
        combobox = QtWidgets.QComboBox()
        for i in range(1,15):
            combobox.addItem("LOCATION %i" % i)
        self.flayout.addRow(label, combobox)

    def MaxYears(self):
        label = QtWidgets.QLabel('Maximum Years')
        combobox = QtWidgets.QComboBox()
        for i in range(1, 10):
            combobox.addItem(str(i))
        self.flayout.addRow(label, combobox)

if __name__ == '__main__':
    App = QtWidgets.QApplication.instance()
    if App is None:
        App = QtWidgets.QApplication(sys.argv)
    ui = Dialog_01()
    ui.show()
    sys.exit(App.exec_())
Другие вопросы по тегам