Добавить / удалить макет, содержащий несколько виджетов pyqt - PullRequest
0 голосов
/ 04 сентября 2018

Я пытаюсь сделать графический интерфейс, который позволяет добавлять / удалять несколько QtWidgets. Пользователь выбирает файл и имеет возможность отключить добавление комментария в строке рядом с ним. Быстрый поиск на этом сайте дал мне следующий код, который позволяет мне добавлять строки виджетов.

import os
import sys

from PyQt5 import QtGui, QtCore, QtWidgets


class Additional(QtWidgets.QMainWindow):

    def __init__(self):
        super(Additional, self).__init__()

        self.addButton     = QtWidgets.QPushButton('  +   ')
        self.delButton     = QtWidgets.QPushButton('  -   ')
        self.acceptButton  = QtWidgets.QPushButton('Accept')
        self.cancelButton  = QtWidgets.QPushButton('Cancel')

        self.addButton.clicked.connect(self.addWidget)
        self.delButton.clicked.connect(self.delWidget)
        self.acceptButton.clicked.connect(self.acceptValues)
        self.cancelButton.clicked.connect(self.cancel)

        self.scrollLayout  = QtWidgets.QFormLayout()

        self.scrollWidget  = QtWidgets.QWidget()
        self.scrollWidget.setLayout(self.scrollLayout)

        self.scrollArea    = QtWidgets.QScrollArea()
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setWidget(self.scrollWidget)

        self.button_layout = QtWidgets.QVBoxLayout()
        self.mainLayout    = QtWidgets.QHBoxLayout()

        self.button_layout.addWidget(self.addButton)
        self.button_layout.addWidget(self.delButton)
        self.button_layout.addWidget(self.acceptButton)
        self.button_layout.addWidget(self.cancelButton)

        self.mainLayout.addLayout(self.button_layout)
        self.mainLayout.addWidget(self.scrollArea)

        self.centralWidget = QtWidgets.QWidget()
        self.centralWidget.setLayout(self.mainLayout)

        self.setCentralWidget(self.centralWidget)

        self.resize(800, 200)
        self.setFixedSize(self.size())
        self.show()

    def addWidget(self):
        self.scrollLayout.addRow(AddRow())

    def delWidget(self):
        # Would this call another class to remove the row? If so, how?
        pass

    def acceptValues(self):
        # Would I count the widgets in the 'scroll' area and get the data from that?
        pass

    def cancel(self):
        QtCore.QCoreApplication.instance().quit()
        # BTW, is this the right way to close the window/instance?



class AddRow(QtWidgets.QWidget):
    def __init__( self, parent=None):
        super(AddRow, self).__init__(parent)
        self.button   = QtWidgets.QPushButton('Select file')
        self.label    = QtWidgets.QLabel('Selection will go here')
        self.lineedit = QtWidgets.QLineEdit()
        self.lineedit.setPlaceholderText("Rename (optional)...")
        # Would I add the button callback here?


        layout = QtWidgets.QHBoxLayout()
        layout.addWidget(self.button)
        layout.addWidget(self.label)
        layout.addWidget(self.lineedit)

        self.setLayout(layout)


app = QtWidgets.QApplication(sys.argv)
myApp = Additional()
app.exec_()

Я пытаюсь выяснить:

  • Как удалить последнюю добавленную строку.
  • Как назначить действие кнопке (это можно сделать в «AddRow» класс как self.buttton.clicked.callback(self.selectfile)
  • Как собрать данные из строк (т. Е. После того, как 'accept' был
    щелкнул)

Любые идеи приветствуются!

1 Ответ

0 голосов
/ 05 сентября 2018

Прежде чем указывать на решение, я просто собираюсь изменить имя класса AddRow на RowWidget, потому что класс не должен указывать действие.

class RowWidget(QtWidgets.QWidget):
    def __init__( self, parent=None):
        super(RowWidget, self).__init__(parent)
        ...

Как удалить последнюю добавленную строку?

Так как вы используете QFormLayout и предполагаете, что используете версию PyQt5> = 5.8, вы можете использовать метод removeRow () :

@QtCore.pyqtSlot()
def delWidget(self):
    if self.scrollLayout.rowCount() > 0:
        self.scrollLayout.removeRow(self.scrollLayout.rowCount()-1)

Как назначить действие кнопке (это можно сделать в классе AddRow likeself.buttton.clicked.callback (self.selectfile)?

Каждая часть вашего приложения должна быть независимой, поэтому выбранный вами слот должен быть частью только RowWidget, и RowWidget должен иметь метод, который возвращает это значение:

class RowWidget(QtWidgets.QWidget):
    def __init__( self, parent=None):
        super(RowWidget, self).__init__(parent)
        self.button   = QtWidgets.QPushButton('Select file')
        self.label    = QtWidgets.QLabel('Selection will go here')
        self.lineedit = QtWidgets.QLineEdit()
        self.lineedit.setPlaceholderText("Rename (optional)...")

        self.button.clicked.connect(self.on_select_file)

        layout = QtWidgets.QHBoxLayout(self)
        layout.addWidget(self.button)
        layout.addWidget(self.label)
        layout.addWidget(self.lineedit)

    @QtCore.pyqtSlot()
    def on_select_file(self):
        filename, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open File")
        if filename:
            self.lineedit.setText(filename)

    def get_filename(self):
        return self.lineedit.text()

Как собрать данные из строк (т. Е. После нажатия кнопки «Принять»)?

Виджеты, прикрепленные к макету, являются дочерними элементами виджета, в который был добавлен макет, этот виджет можно получить с помощью parentWidget () , имея этого родителя, мы можем получить их потомков с помощью findChildren. () : * * тысяча двадцать-два

@QtCore.pyqtSlot()
def acceptValues(self):
    l_values = []
    for w in self.scrollLayout.parentWidget().findChildren(RowWidget):
        l_values.append(w.get_filename())
    print(l_values)

Предыдущий метод может завершиться ошибкой, если у parentWidget() есть другие дочерние элементы, принадлежащие RowWidget.

Еще один вариант, который не перестает работать, - это перебирать QLayoutItem s:

@QtCore.pyqtSlot()
def acceptValues(self):
    l_values = []
    for i in range(self.scrollLayout.rowCount()):
        layout_item = self.scrollLayout.itemAt(i)
        if isinstance(layout_item.widget(), RowWidget):
            l_values.append(layout_item.widget().get_filename())
    print(l_values)
...