Reputation: 119
I'm trying to make a gui that allows the addition/removal of multiple QtWidgets. The user selects a file and has the option off adding a comment in the lineedit next to it. A quick search on this site has so far given me the following code which allows me to add rows widgets.
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_()
I'm trying to figure out:
self.buttton.clicked.callback(self.selectfile)
Any ideas would be welcome!
Upvotes: 3
Views: 1324
Reputation: 244282
Before pointing to the solution, I'm just going to change the name of the AddRow class to RowWidget because a class should not indicate action.
class RowWidget(QtWidgets.QWidget):
def __init__( self, parent=None):
super(RowWidget, self).__init__(parent)
...
Since you are using QFormLayout and assuming that you are using a version PyQt5>=5.8 you can use the removeRow() method:
@QtCore.pyqtSlot()
def delWidget(self):
if self.scrollLayout.rowCount() > 0:
self.scrollLayout.removeRow(self.scrollLayout.rowCount()-1)
Each part of your application must be independent so the slot that you select the file must be part only of RowWidget, and RowWidget must have a method that returns that value:
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()
The widgets attached to a layout are children of the widget where the layout has been added, that widget can be obtained through parentWidget(), having that parent we can obtain their children through 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)
The previous method may fail if the parentWidget()
has other children that belong to RowWidget
.
Another option, and that does not fail is to iterate through the 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)
Upvotes: 3