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
的最后一项以您的特定字符串开头,您想更改 graphicsView
的 backgroundBrush
。
要检测到这一点,您可以子类化 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);
}
我在 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
的最后一项以您的特定字符串开头,您想更改 graphicsView
的 backgroundBrush
。
要检测到这一点,您可以子类化 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);
}