QListView 能否检测到特定的 QString 并因此自动触发插槽?

Can a QListView detect a specific QString and therefore automatically trigger a slot?

我在 QLineEdit 上有一个特定的字符串,这个字符串通过 QPushButton 传递给 QListView。这些字符串是 QComboBox 的选择,它们非常具体:

1) "[INFO] 最小距离:5",

2)“[信息]最小距离:10”和

3) "[INFO] 最小距离:15"

Here 一个完美工作的最小可验证示例,如果您需要测试它。

目前我可以 更改 QGraphicsView 的颜色,但是通过单击或双击 QListView 中输入的 QString

问题:我如何检测QListView中的特定QString内容,以便更改 QGraphicsView 的背景颜色? 我的意思是我不想单击或双击 QListView 的条目,但我希望 QListView 看到有一个字符串“[INFO] Minimum Distance: 5”因此无需我单击或双击 QListView 条目即可自动更改 QGraphicsView 的颜色。

在我"Go to slot"之后我的选择如下:

下面的MVE工作代码,你可以复制/粘贴到你的机器上,它会工作:

mainwindow.h

#include <QMainWindow>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsTextItem>
#include <QStringListModel>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    void changeColorDetection();
    void updateListView();
    void updateListView(const QString & message);

private slots:
    void on_pushButton_clicked();
    void on_listView_entered(const QModelIndex &index);
    void on_listView_activated(const QModelIndex &index);

private:
    Ui::MainWindow *ui;
    QGraphicsView *mView;
    QGraphicsScene *mScene;
    QGraphicsTextItem *mText;
    StringList *newString;
    QStringListModel *model;

};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    mView = new QGraphicsView();
    mScene = new QGraphicsScene();
    ui->graphicsView->setScene(mScene);

    QFont font;
    font.setPixelSize(10);
    font.setBold(false);
    font.setFamily("Calibri");

    mText = new QGraphicsTextItem;
    mText->setPos(150,70);
    mScene->addText(tr("Boat outside alarm area"))->setDefaultTextColor(Qt::black);

    model = new QStringListModel();
    ui->listView->setModel(model);
    ui->listView->setEditTriggers(QAbstractItemView::NoEditTriggers);

    emptyIndex();

    connect(ui->listView, SIGNAL(loggingUpdated()), this, SLOT(updateListView(const QString &)));
    connect(ui->graphicsView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(on_listView_activated(const QModelIndex &index)));
}

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


void MainWindow::updateListView(const QString & message)
{
    if(model->insertRow(model->rowCount())) {
        QModelIndex index = model->index(model->rowCount() - 1, 0);
        model->setData(index, message);
        ui->listView->scrollTo(index);
    }
}

void MainWindow::on_pushButton_clicked()
{
    QString str = ui->lineEdit->text();
    model->insertRow(model->rowCount());
    QModelIndex index = model->index(model->rowCount()-1);
    model->setData(index, str);
    ui->listView->scrollToBottom();
}

void MainWindow::on_comboBox_currentIndexChanged(const QString &arg1)
{
    QString list = ui->comboBox->currentText();
    ui->lineEdit->setText(list);
    Q_UNUSED(arg1)
}

void MainWindow::on_listView_activated(const QModelIndex &index)
{
    QStringList allStrings = model->stringList();
    QString last = allStrings.last();
    if(last.startsWith("[ INFO] Minimum Distance: 5"))
    {
        ui->graphicsView->setBackgroundBrush(QColor(Qt::red));
    }
    else if(last.startsWith("[ INFO] Minimum Distance: 10"))
    {
        ui->graphicsView->setBackgroundBrush(QColor(Qt::yellow));
    }
    else if(last.startsWith("[ INFO] Minimum Distance: 15"))
    {
        ui->graphicsView->setBackgroundBrush(QColor(Qt::green));
    }
    Q_UNUSED(index)
}

编辑 2

mainwindow.h

#include <QMainWindow>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsTextItem>
#include <QStringListModel>
#include "listview.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE


class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

public slots:
    void setGraphicViewColor(QColor c);

private:
    Ui::MainWindow *ui;
    QGraphicsView *mView;
    QGraphicsScene *mScene;
    QGraphicsTextItem *mText;
    QStringListModel *model;

    ListView *myListView;

};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    mView = new QGraphicsView();
    mScene = new QGraphicsScene();
    ui->graphicsView->setScene(mScene);

    QFont font;
    font.setPixelSize(10);
    font.setBold(false);
    font.setFamily("Calibri");

    mText = new QGraphicsTextItem;
    mText->setPos(150,70);
    mScene->addText(tr("Boat outside alarm area"))->setDefaultTextColor(Qt::black);

    model = new QStringListModel();
    ui->listView->setModel(model);
    ui->listView->setEditTriggers(QAbstractItemView::NoEditTriggers);


    connect(ui->listView, SIGNAL(changeColor(QColor)), this, SLOT(setGraphicViewColor(QColor)));
}

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


void MainWindow::setGraphicViewColor(QColor c)
{
    qDebug() << "Update your graphicsView backgroundBrush" << c;
    ui->graphicsView->setBackgroundBrush(Qt::green);
}

listview.h

#ifndef LISTVIEW_H
#define LISTVIEW_H

#include <QListView>
#include <QStringListModel>

class ListView : public QListView
{
    Q_OBJECT
public:
    ListView(QWidget *parent = nullptr);

signals:
    void changeColor(QColor c);

protected:
    void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>()) override;

};

#endif // LISTVIEW_H

listview.cpp

#include "listview.h"

ListView::ListView(QWidget *parent)
    : QListView(parent)
{}

void ListView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
{
    QListView::dataChanged(topLeft, bottomRight, roles);
    /**
     * Assuming that you have just one item changed
     * So topLeft == bottomRight
     */
    if (topLeft.row() == model()->rowCount()-1){
        QString last = topLeft.data().toString();
        if(last.startsWith("[ INFO] Minimum Distance: 5")) {
            emit changeColor(Qt::red);
        } else if(last.startsWith("[ INFO] Minimum Distance: 10")) {
            emit changeColor(Qt::yellow);
        } else if(last.startsWith("[ INFO] Minimum Distance: 15")) {
            emit changeColor(Qt::green);
        }
    }
}

下面的错误和未检测到更改事件的ui的屏幕截图:

.ui的输出:

到目前为止我做了什么:

我已经对这个问题做了很多研究,遇到了 this source 这很有用但无法解决问题,但另外它似乎使用了 QModelIndex 并且我是不确定这正是我这个小项目所需要的。

我还阅读了 this source,这对于建立和捕获特定且唯一的字符串很有用,但就更改颜色而言,我无法解决这个问题。

非常感谢您为解决此问题指明了正确的方向。

如果我很清楚,如果 QStringListModel 的最后一项以您的特定字符串开头,您想更改 graphicsViewbackgroundBrush

要检测到这一点,您可以子类化 QListView:
listview.h:

#ifndef LISTVIEW_H
#define LISTVIEW_H

#include <QListView>
#include <QStringListModel>

class ListView : public QListView
{
    Q_OBJECT
public:
    ListView(QWidget *parent = nullptr);

signals:
    void changeColor(QColor c);

protected:
    void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>()) override;

};

#endif // LISTVIEW_H

listview.cpp:

#include "listview.h"

ListView::ListView(QWidget *parent)
    : QListView(parent)
{

}

void ListView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
{
    QListView::dataChanged(topLeft, bottomRight, roles);
    /**
     * Assuming that you have just one item changed
     * So topLeft == bottomRight
     */
    if (topLeft.row() == model()->rowCount()-1){
        QString last = topLeft.data().toString();
        if(last.startsWith("[ INFO] Minimum Distance: 5")) {
            emit changeColor(Qt::red);
        } else if(last.startsWith("[ INFO] Minimum Distance: 10")) {
            emit changeColor(Qt::yellow);
        } else if(last.startsWith("[ INFO] Minimum Distance: 15")) {
            emit changeColor(Qt::green);
        }
    }
}

现在你已经拥有了所有你需要的东西,但是你需要添加一个 slot 来连接你的自定义信号 ListView 和你的 QGraphicsView::brush

// Add this in your mainwindows.h
public slots:
    void setGraphicViewColor(QColor c);

// This in the ctor of your MainWindow:
connect(ui->listView, SIGNAL(changeColor(QColor)), this, SLOT(setGraphicViewColor(QColor)));

// And the implementation of your custom slot in mainwindows.cpp
void MainWindow::setGraphicViewColor(QColor c)
{
    qDebug() << "Update your graphicsView backgroundBrush" << c;
    //ui->graphicsView->setBackgroundBrush(c);
}