我正在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
感谢与我的关系 - 我在努力解释我头脑中那么清楚的事情!
答案 0 :(得分:2)
如果我理解你的问题,你想获得代表 todo 的已分配对象,以便释放它们并更新你的视图。
您可以通过简单地将QLineEdit,QToolButton和QHBoxLayout对象包装到类中来实现此目的,并在ToDoList类中使用容器(例如向量)。这样,你就可以推送你的" todo 对象"每次按on_toolButton_clicked方法。
然后,您只需使用索引触发on_delete_todo插槽的信号,该插槽将删除" todo 对象"从你的矢量并更新视图。
另外,请看一下这个Qt Model-View Programming
这是一个样本(在QT5下测试和工作):
#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());
}
#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:
todoView.reserve(10);
for(std::size_t i = 0; i < 10; ++i)
{
todoView[i] = nullptr;
}
// 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
}
}
delete todoView[i];
todoView[i] = nullptr;
也可以使用pair的向量(一对int TodoView)。
答案 1 :(得分:1)
我可以想到你可以采用的两种方法。
QObject::sender()
。QSignalMapper
。QObject::sender()
此静态方法返回发出信号的发送方对象的QObject *
。在这种情况下QToolButton
,您可以使用此引用来查找其父级(即QHBoxLayout
)及其兄弟(即QLineEdit
)。
QSingalMapper
首先定义一个列表,用于保存对所有行的引用,然后为每一行分配唯一的标识符(例如行号),然后根据official documentation's example使用此标识符作为每个按钮的QSignalMapper
键。现在,如果用户单击一个按钮,您将在插槽中获得相同的标识符,使用它并查找行列表中的整行。