添加/删除包含多个小部件的布局pyqt

时间:2018-09-04 20:58:30

标签: python pyqt pyqt5 qlayout

我正在尝试制作一个允许添加/删除多个QtWidget的gui。用户选择一个文件,并可以选择在其旁边的行编辑中添加注释。到目前为止,在该站点上的快速搜索为我提供了以下代码,该代码使我可以添加行小部件。

function insertPost(){
if(isset($_POST['sub'])){
    global $con;
    global $user_id;

    $content = htmlentities($_POST['content']);
    $content2 = htmlentities($_POST['content2']);
    $price = htmlentities($_POST['price']);
    $pclass = htmlentities($_POST['pclass']);
    $specificclass = htmlentities($_POST['specificclass']);
    $upload_image = $_FILES['upload_image']['name'];
    $image_tmp = $_FILES['upload_image']['tmp_name'];
    $random_number = rand(1, 100);

    $user_balance = $row_posts['user_balance'];

    if(strlen($content) > 250){
        echo "<script>alert('Utiliza menos de 250 carácteres)</script>";
        echo "<script>window.open('home.php', '_self')</script>";
    }else{
        move_uploaded_file($image_tmp, "imagepost/$upload_image.$random_number");
        $insert = "insert into posts (user_id, post_content, post_content2, post_price, post_class, post_specificclass, upload_image, post_date) values('$user_id', '$content', '$content2', '$price', '$pclass', '$specificclass', '$upload_image.$random_number', NOW())";

        $run = mysqli_query($con, $insert);

        $user_balance = $user_balance - $price;

        if($run){
            echo "<script>window.open('home.php', '_self')</script>";

            $update = "update users set posts='yes' where user_id='$user_id'";
            $update = "update users set user_balance='$user_balance - $price' where user_id='$user_id'";
            $run_update = mysqli_query($con, $update);
        }
        exit();
    }
}

我正在尝试找出:

  • 如何删除已添加的最后一行。
  • 如何将操作分配给按钮(可在“ AddRow”中完成 类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_()
  • 如何从行中收集数据(即在“接受”之后
    点击)

任何想法都会受到欢迎!

1 个答案:

答案 0 :(得分:2)

在指向解决方案之前,我将把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”类中完成,例如self.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)