我想链接两个QListWidget,但我不知道如何处理代码。这是我做的: 我们可以看到两个QListWidget。使用左侧QListWidget,我添加(通过示例:“Bonjour”,“Hello”,“Tag”)三个QListWidgetItem。我希望如果我点击左侧QListWidget的三个QListWidgetItem中的一个,我可以使用正确的QListWidget添加QListWidgetItem(例如,对于“Bonjour”:“Tu”,“Vas”,“Bien”)。如果我没有点击三个QListWidgetItem中的一个,我就无法使用正确的QListWidget添加QListWidgetItem。如果我为“Bonjour”做了:“Tu”,“Vas”,“Bien”,我点击“Hello”(显然,“Hello”不包含任何内容),右边的QListWidget中没有任何内容。这只是我想要做的一个例子。下面,如果它有用,我会编写我的代码:
- secondwindow.cpp -
#include "secondwindow.h"
#include "ui_secondwindow.h"
#include "thirdwindow.h"
#include "ui_thirdwindow.h"
SecondWindow::SecondWindow(QWidget *parent) :
QWidget(parent),
ui(new Ui::SecondWindow)
{
ui->setupUi(this);
ui->button_1->setIcon(QIcon(":/Images/Images/Haut.png"));
ui->button_2->setIcon(QIcon(":/Images/Images/Bas.png"));
ui->button_5->setIcon(QIcon(":/Images/Images/Haut.png"));
ui->button_6->setIcon(QIcon(":/Images/Images/Bas.png"));
connect(ui->button_1, SIGNAL(clicked()), this, SLOT(UpForLeft()));
connect(ui->button_2, SIGNAL(clicked()), this, SLOT(DownForLeft()));
connect(ui->button_3, SIGNAL(clicked()), this, SLOT(DeleteForLeft()));
connect(ui->button_4, SIGNAL(clicked()), this, SLOT(AddForLeft()));
connect(ui->button_9, SIGNAL(clicked()), this, SLOT(ShowThirdWindow()));
connect(ui->button_10, SIGNAL(clicked()), this, SLOT(close()));
connect(ui->table_1, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
this, SLOT(EditForLeft(QListWidgetItem *)));
}
SecondWindow::~SecondWindow()
{
delete ui;
}
void SecondWindow::ShowThirdWindow()
{
ThirdWindow *window = new ThirdWindow;
window->setWindowTitle("B");
window->setWindowIcon(QIcon(":/Images/Images/Bouclier.png"));
window->setFixedSize(820, 440);
window->show();
}
void SecondWindow::UpForLeft()
{
QListWidgetItem *item;
int i;
i = ui->table_1->currentRow();
item = ui->table_1->takeItem(i);
ui->table_1->insertItem(i - 1, item);
ui->table_1->setCurrentRow(i - 1);
}
void SecondWindow::DownForLeft()
{
QListWidgetItem *item;
int i;
i = ui->table_1->currentRow();
item = ui->table_1->takeItem(i);
ui->table_1->insertItem(i + 1, item);
ui->table_1->setCurrentRow(i + 1);
}
void SecondWindow::UpForRight()
{
QListWidgetItem *item;
int i;
i = ui->table_2->currentRow();
item = ui->table_2->takeItem(i);
ui->table_1->insertItem(i - 1, item);
ui->table_1->setCurrentRow(i - 1);
}
void SecondWindow::DownForRight()
{
QListWidgetItem *item;
int i;
i = ui->table_2->currentRow();
item = ui->table_2->takeItem(i);
ui->table_1->insertItem(i + 1, item);
ui->table_1->setCurrentRow(i + 1);
}
void SecondWindow::AddForLeft()
{
QString string;
string = ui->line_1->text();
ui->table_1->addItem(string);
ui->line_1->clear();
}
void SecondWindow::DeleteForLeft()
{
QListWidgetItem *item;
int i;
i = ui->table_1->currentRow();
item = ui->table_1->takeItem(i);
delete item;
}
void SecondWindow::EditForLeft(QListWidgetItem *item)
{
item->setFlags(item->flags() | Qt::ItemIsEditable);
item = ui->table_1->currentItem();
ui->table_1->editItem(item);
}
- secondwindow.h -
#ifndef SECONDWINDOW_H
#define SECONDWINDOW_H
#include <QListWidgetItem>
#include <QWidget>
#include <QString>
#include <QIcon>
#include "thirdwindow.h"
#include "ui_thirdwindow.h"
namespace Ui {
class SecondWindow;
}
class SecondWindow : public QWidget
{
Q_OBJECT
public:
explicit SecondWindow(QWidget *parent = 0);
~SecondWindow();
public slots:
void ShowThirdWindow();
void UpForLeft();
void DownForLeft();
void UpForRight();
void DownForRight();
void AddForLeft();
void DeleteForLeft();
void EditForLeft(QListWidgetItem *item);
private:
Ui::SecondWindow *ui;
ThirdWindow *window;
};
#endif // SECONDWINDOW_H
感谢您的帮助。
答案 0 :(得分:0)
QListWidget
是一个方便的小部件,它将模型与视图混合在一起。这使得事情变得有点困难,因为您需要使用来自代表树结构数据的顶级模型的数据来补充模型。
相反,您可以使用QStandardItemModel
,并通过QListView
公开它。视图仅显示树的给定级别的一列,没有任何子级。要查看子项,请选择适当的根索引。
QStandardItemModel
的关键缺失功能是moveRows
,需要上下移动项目。这很容易通过支持在同一父项中移动单个项目的有限实现来补救。因此,通过使用moveRow
,视图可以完全与模型无关。我们将首先实施moveRows
:
// https://github.com/KubaO/stackoverflown/tree/master/questions/list-widgets-40403640
#include <QtWidgets>
class StandardItemModel : public QStandardItemModel {
bool moveRows(const QModelIndex &srcParent, int srcRow, int count,
const QModelIndex &dstParent, int dstRow) override {
if (count == 0) return true;
if (count != 1 || srcParent != dstParent) return false;
if (srcRow == dstRow) return true;
if (abs(srcRow - dstRow) != 1) return false;
auto root = srcParent.isValid() ? itemFromIndex(srcParent) : invisibleRootItem();
if (!root) return false;
auto srcItem = root->takeChild(srcRow);
auto dstItem = root->takeChild(dstRow);
if (!srcItem || !dstItem) return false;
root->setChild(srcRow, dstItem);
root->setChild(dstRow, srcItem);
return true;
}
public:
using QStandardItemModel::QStandardItemModel;
};
随后,ListUi
窗口小部件实现了视图,而不知道模型的工作方式。出于此示例的目的,新项目就地编辑,而不是使用单独的控件。
class ListUi : public QWidget {
Q_OBJECT
QGridLayout m_layout{this};
QVBoxLayout m_column;
QPushButton m_up{"⬆"}, m_down{"⬇"}, m_remove{"−"}, m_add{"+"};
QLabel m_caption;
QListView m_list;
inline QAbstractItemModel * model() const { return m_list.model(); }
inline QModelIndex root() const { return m_list.rootIndex(); }
inline QModelIndex index(int row) const { return model()->index(row, 0, root()); }
public:
ListUi(const QString & caption, QWidget * parent = nullptr) :
QWidget{parent},
m_caption{caption}
{
m_layout.addWidget(&m_up, 0, 0);
m_layout.addWidget(&m_down, 1, 0, 1, 1, Qt::AlignTop);
m_layout.addLayout(&m_column, 0, 1, 3, 1);
m_column.addWidget(&m_caption);
m_column.addWidget(&m_list);
m_layout.addWidget(&m_remove, 0, 2);
m_layout.addWidget(&m_add, 2, 2);
m_caption.setAlignment(Qt::AlignCenter);
connect(&m_add, &QPushButton::clicked, [this]{
int row = model()->rowCount(root());
if (model()->columnCount(root()) == 0)
model()->insertColumn(0, root());
if (model()->insertRow(row, root())) {
m_list.setCurrentIndex(index(row));
m_list.edit(index(row));
}
});
connect(&m_remove, &QPushButton::clicked, [this]{
if (m_list.currentIndex().isValid())
model()->removeRow(m_list.currentIndex().row(), root());
});
connect(&m_up, &QPushButton::clicked, [this]{
auto row = m_list.currentIndex().row();
if (row > 0 && model()->moveRow(root(), row, root(), row - 1))
m_list.setCurrentIndex(index(row-1));
});
connect(&m_down, &QPushButton::clicked, [this]{
auto row = m_list.currentIndex().row();
if (row >= 0 && row < (model()->rowCount(root()) - 1) &&
model()->moveRow(root(), row, root(), row + 1))
m_list.setCurrentIndex(index(row+1));
});
}
void setModel(QAbstractItemModel * model) {
m_list.setModel(model);
connect(m_list.selectionModel(), &QItemSelectionModel::currentChanged, this, &ListUi::currentIndexChanged);
}
void setRootIndex(const QModelIndex & index) {
m_list.setRootIndex(index);
}
Q_SIGNAL void currentIndexChanged(const QModelIndex &);
};
一个简单的测试工具实例化两个ListUi
,一个StandardItemModel
,从JSON源填充模型,并链接它们以获得所需的功能。
class Window : public QWidget {
Q_OBJECT
QGridLayout m_layout{this};
ListUi m_programs{"Liste des programmes"};
ListUi m_sessions{"Liste des sessions"};
QPushButton m_generate{"Générer les données"};
StandardItemModel m_model;
public:
explicit Window(QWidget * parent = nullptr) : QWidget{parent}
{
m_layout.addWidget(&m_programs, 0, 0);
m_layout.addWidget(&m_sessions, 0, 1);
m_layout.addWidget(&m_generate, 1, 1, 1, 1, Qt::AlignRight);
m_programs.setModel(&m_model);
m_sessions.setModel(&m_model);
m_sessions.setDisabled(true);
connect(&m_programs, &ListUi::currentIndexChanged, [this](const QModelIndex & root){
m_sessions.setEnabled(true);
m_sessions.setRootIndex(root);
});
connect(&m_generate, &QPushButton::clicked, this, &Window::generateData);
}
Q_SIGNAL void generateData();
void setJson(const QJsonDocument & doc) {
m_model.clear();
auto object = doc.object();
for (auto it = object.begin(); it != object.end(); ++it) {
if (!m_model.columnCount()) m_model.appendColumn({});
auto root = new QStandardItem(it.key());
m_model.appendRow(root);
if (it.value().isArray()) {
auto array = it.value().toArray();
for (auto const & value : array) {
if (!root->columnCount()) root->appendColumn({});
root->appendRow(new QStandardItem{value.toString()});
}
}
}
}
};
int main(int argc, char ** argv) {
QApplication app{argc, argv};
auto json = R"--({
"Foo":["Foo-1", "Foo-2", "Foo-3"],
"Bar":["Bar-1", "Bar-2"]
})--";
Window ui;
ui.connect(&ui, &Window::generateData, [&]{ ui.setJson(QJsonDocument::fromJson(json)); });
ui.show();
return app.exec();
}
#include "main.moc"
迭代标准项模型以重新生成JSON表示是一件简单的事情。
示例结束。