简体   繁体   中英

binding a signal to QListWidget items

How do I make sure that clicking on a QListWidget item opens the corresponding widgets in the QFrame and that the data entered in these widgets is saved between switching list items?

class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):

        vbox = QVBoxLayout()
        tab_widget = QTabWidget()
        tab_widget.setStyleSheet('background-color:gainsboro')
        tab_widget.addTab(Setup(), "setup")
        vbox.addWidget(tab_widget)
        self.setLayout(vbox)

class Setup(QWidget):

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):

        hbox = QHBoxLayout()
        splitter = QSplitter(Qt.Horizontal)
        self.list = QListWidget()
        self.list.setStyleSheet("background-color:white")
        QListWidgetItem("vertices", self.list)
        QListWidgetItem("blocks", self.list)
        self.list.itemClicked.connect(self.conv_met)
        splitter.addWidget(self.list)

        self.frame = QFrame()
        self.frame.setFrameShape(QFrame.StyledPanel)
        self.frame.setLineWidth(0.6)

        splitter.addWidget(self.frame)
        hbox.addWidget(splitter)
        self.setLayout(hbox)
        self.show()

    def conv_met(self, item):
        if item.text() == "vertices":
            convertToMeters_layout = QHBoxLayout()
            convertToMeters_lbl = QLabel("convertToMeters")
            convertToMeters_val = QLineEdit("0.1")
            convertToMeters_layout.addWidget(convertToMeters_lbl)
            convertToMeters_layout.addWidget(convertToMeters_val)
            self.frame.setLayout(convertToMeters_layout)
        if item.text() == "blocks":
            block_grad_layout = QGridLayout()
            hexx = QComboBox(self)
            hexx.addItems(["hex"])
            ver_labels = QLineEdit("0 1 2 3 4 5 6 7")

            block_grad_layout.addWidget(hexx, 0, 0)
            block_grad_layout.addWidget(ver_labels, 0, 1)
            self.frame.setLayout(block_grad_layout)

if __name__ == '__main__':

    app = QApplication(sys.argv)
    main_win = Window()
    main_win.show()
    sys.exit(app.exec_())

在此处输入图像描述

在此处输入图像描述

In order to keep data for an item, you can use setData(role, value) to store the previous entered data and before changing to the new current item.

Note that you should not use setLayout() more than once; in fact, your example doesn't work as expected for this reason, and you could see the error message if you run it from a shell or command prompt:

QWidget::setLayout: Attempting to set QLayout "" on QFrame "", which already has a layout

To achieve what you want, the solution is to use QStackedWidget , which works almost like a QTabWidget, but doesn't have a tab bar to switch between "pages", as they can only be changed programmatically using setCurrentIndex() or setCurrentWidget() .

class Setup(QWidget):

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):

        hbox = QHBoxLayout()
        splitter = QSplitter(Qt.Horizontal)
        self.list = QListWidget()
        self.list.setStyleSheet("background-color:white")
        self.verticesItem = QListWidgetItem("vertices", self.list)
        self.blocksItem = QListWidgetItem("blocks", self.list)
        self.list.itemClicked.connect(self.conv_met)
        splitter.addWidget(self.list)

        self.frame = QFrame()
        self.frame.setFrameShape(QFrame.StyledPanel)
        self.frame.setLineWidth(0.6)

        frameLayout = QVBoxLayout(self.frame)
        self.stackedWidget = QStackedWidget()
        frameLayout.addWidget(self.stackedWidget)

        self.convertToMeters_widget = QWidget()
        self.stackedWidget.addWidget(self.convertToMeters_widget)
        convertToMeters_layout = QHBoxLayout(self.convertToMeters_widget)
        convertToMeters_lbl = QLabel("convertToMeters")
        self.convertToMeters_val = QLineEdit("0.1")
        convertToMeters_layout.addWidget(convertToMeters_lbl)
        convertToMeters_layout.addWidget(self.convertToMeters_val)

        self.block_grad_widget = QWidget()
        self.stackedWidget.addWidget(self.block_grad_widget)
        block_grad_layout = QGridLayout(self.block_grad_widget)
        hexx = QComboBox()
        hexx.addItems(["hex"])
        self.ver_labels = QLineEdit("0 1 2 3 4 5 6 7")

        block_grad_layout.addWidget(hexx, 0, 0)
        block_grad_layout.addWidget(self.ver_labels, 0, 1)

        splitter.addWidget(self.frame)
        hbox.addWidget(splitter)
        self.setLayout(hbox)

        self.currentItem = None

    def conv_met(self, item):
        if self.currentItem:
            if self.currentItem == self.verticesItem:
                self.currentItem.setData(Qt.UserRole, self.convertToMeters_val.text())
            else:
                self.currentItem.setData(Qt.UserRole, self.ver_labels.text())
        if item == self.currentItem:
            return
        self.currentItem = item
        if item == self.verticesItem:
            self.stackedWidget.setCurrentWidget(self.convertToMeters_widget)
            self.convertToMeters_val.setText(item.data(Qt.UserRole) or '0.1')
        elif item == self.blocksItem:
            self.stackedWidget.setCurrentWidget(self.block_grad_widget)
            self.ver_labels.setText(item.data(Qt.UserRole) or '0 1 2 3 4 5 6 7')

Note that if you want to store numeric values for the "vertices", you might prefer to use a QSpinBox (or QDoubleSpinBox for floating numbers). Similarly, if you need only hexadecimal values, it's better to set an inputMask or add a validator to ensure that the entered values are valid.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM