将参数传递给qt5 c ++中的插槽

时间:2016-08-30 18:29:26

标签: c++ ios macos qt

我正在c ++ qt中创建一个ToDo列表应用。当按下加号按钮时,它会将包含QLabel和QToolButton的QHBoxLayout添加到我gui中的垂直布局中,因此我会在其中添加带有“ToDos”的新框,并在其旁边删除它们。我在插槽中设置了各种小部件,单击添加按钮时会调用这些小部件。但是,我需要将它们作为参数传递给插槽,当按下删除按钮时调用该插槽。我已经研究过了,我发现的只有QSignalMapper。但是,我找不到任何足够接近我复制的案例,我读过它只适用于某些参数,而不是我需要的三个(QHBoxLayout,QLineEdit和QToolButton)。 按下“添加”按钮时调用的插槽的一些代码是:

//Creates a read only LineEdit which the user will add
   QLineEdit *toDoBox = new QLineEdit(this);
   toDoBox->setText(ui->lineEdit->text());
   toDoBox->setReadOnly(true);

   //Creates a new X button for removal of ToDo's
    QToolButton *removeButton = new QToolButton;
    removeButton->setText("X");

    //Adds a horizontal layout with the ToDo and the remove button in it, to keep them together
    QHBoxLayout *toDoLayout = new QHBoxLayout;
    toDoLayout->addWidget(toDoBox);
    toDoLayout->addWidget(removeButton);

    //Removes a ToDo when the remove button is clicked
    connect(removeButton, SIGNAL(clicked()), this, SLOT(on_removeButton_clicked()));

如果您想查看整个项目,我的代码将托管在GitHub上: https://github.com/DanWilkes02/ToDoList

感谢与我的关系 - 我在努力解释我头脑中那么清楚的事情!

2 个答案:

答案 0 :(得分:2)

如果我理解你的问题,你想获得代表 todo 的已分配对象,以便释放它们并更新你的视图。

您可以通过简单地将QLineEdit,QToolButton和QHBoxLayout对象包装到类中来实现此目的,并在ToDoList类中使用容器(例如向量)。这样,你就可以推送你的" todo 对象"每次按on_toolButton_clicked方法。

然后,您只需使用索引触发on_delete_todo插槽的信号,该插槽将删除" todo 对象"从你的矢量并更新视图。

另外,请看一下这个Qt Model-View Programming

这是一个样本(在QT5下测试和工作):

你的Todo Widget

#ifndef TODOVIEW_H
#define TODOVIEW_H

#include <QString>

class QLineEdit;
class QToolButton;
class QHBoxLayout;

#include <QWidget>

class TodoView : public QWidget
{
    Q_OBJECT

private:
    QLineEdit*      frame;
    QToolButton*    removeButton;
    QHBoxLayout*    toDoLayout;
    int             index;

public:
    TodoView(const QString& what, int index, QWidget* parent);
    ~TodoView();

    inline void setIndex(int i) { index = i; }
    inline int getIndex(){ return index; }

private slots:
    void emitIndex();

signals:
    void selectedIndex(int);

};

#endif // TODOVIEW_H
#include "todoview.h"

#include <QLineEdit>
#include <QToolButton>
#include <QHBoxLayout>

TodoView::TodoView(const QString& what, int index, QWidget* parent) : QWidget(parent), index(index)
{
    frame = new QLineEdit(this);
    frame->setText(what);
    frame->setReadOnly(true);

    removeButton = new QToolButton(this);
    removeButton->setText("X");

    toDoLayout = new QHBoxLayout(this);
    toDoLayout->addWidget(frame);
    toDoLayout->addWidget(removeButton);

    connect(removeButton, SIGNAL(clicked()), this, SLOT(emitIndex()));
}

TodoView::~TodoView() {}

void TodoView::emitIndex()
{
    emit selectedIndex(getIndex());
}

您的MainWindow

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include <vector>

class TodoView;
class QVBoxLayout;

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void addTodo();
    void delTodo(int);

private:
    Ui::MainWindow*         ui;

    QVBoxLayout*            vBoxLayout;

    std::vector<TodoView*>  todoView;
    int                     max = -1;
};

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "todoview.h"

#include <QVBoxLayout>
#include <QAction>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    vBoxLayout = new QVBoxLayout(centralWidget());

    QAction* add = new QAction(ui->mainToolBar);
    ui->mainToolBar->addAction(add);

    connect(add, SIGNAL(triggered()), this, SLOT(addTodo()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::addTodo()
{
    if(max > 9)
    {
        // Error msg.
    }
    else
    {
        TodoView* tdV = new TodoView("Yolo", max, centralWidget());
        connect(tdV, SIGNAL(selectedIndex(int)), this, SLOT(delTodo(int)));

        vBoxLayout->addWidget(tdV);
        todoView.push_back(tdV);
        ++max;
    }
}


void MainWindow::delTodo(int i)
{
    // check if i < todoView.size().
    delete todoView.at(i);
    // update vector indexes !!!
    --max;
}

我已经快速编辑了这段代码,我可能犯了几个错误,但你知道至少有一个解决方案。

也可以使用固定大小的矢量(更好的解决方案)。在向量中将TodoView已删除对象设置为nullptr,并在要添加新Todo视图组件时搜索nullptr:

在MainWindow构造函数

todoView.reserve(10);
for(std::size_t i = 0; i < 10; ++i)
{
    todoView[i] = nullptr;
}

在addTodo Slot

// Do not use push back.
// retrieve the max index.
// if < 10
for(std::size_t i = 0; i < todoView.size(); ++i)
{
    if(todoView[i] == nullptr)
    {
        // allocate TodoView and affect it to the i° element
    }
}

在delTodo广告位

delete todoView[i];
todoView[i] = nullptr;

也可以使用pair的向量(一对int TodoView)。

答案 1 :(得分:1)

我可以想到你可以采用的两种方法。

  1. 使用QObject::sender()
  2. 使用QSignalMapper
  3. QObject::sender()

    此静态方法返回发出信号的发送方对象的QObject *。在这种情况下QToolButton,您可以使用此引用来查找其父级(即QHBoxLayout)及其兄弟(即QLineEdit)。

    QSingalMapper

    首先定义一个列表,用于保存对所有行的引用,然后为每一行分配唯一的标识符(例如行号),然后根据official documentation's example使用此标识符作为每个按钮的QSignalMapper键。现在,如果用户单击一个按钮,您将在插槽中获得相同的标识符,使用它并查找行列表中的整行。