![](/img/trans.png)
[英]How to get the ID from a newly inserted row with QSqlQuery and SQLite?
[英]QML Connections not working in newly inserted row?
作為示例,我以Qt文檔中的官方示例為例,並添加了幾行代碼來演示該問題:
model.h:
#include <QAbstractListModel>
#include <QStringList>
//![0]
class Animal
{
public:
Animal(const QString &type, const QString &size);
//![0]
QString type() const;
QString size() const;
private:
QString m_type;
QString m_size;
//![1]
};
class AnimalModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(int myProperty READ myProperty NOTIFY myPropertyChanged)
signals:
void myPropertyChanged();
public:
enum AnimalRoles {
TypeRole = Qt::UserRole + 1,
SizeRole
};
AnimalModel(QObject *parent = 0);
//![1]
void addAnimal(const Animal &animal);
int rowCount(const QModelIndex & parent = QModelIndex()) const;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
// my code starts
virtual bool insertRows(int position, int rows,
const QModelIndex &index = QModelIndex()) override;
virtual Qt::ItemFlags flags(const QModelIndex &index) const override {
return QAbstractListModel::flags(index) | Qt::ItemIsEditable;
}
int myProperty() const {
return m_myProperty;
}
int m_myProperty;
public slots:
void addAnimal();
// my code ends
protected:
QHash<int, QByteArray> roleNames() const;
private:
QList<Animal> m_animals;
//![2]
};
//![2]
model.cpp:
#include "model.h"
Animal::Animal(const QString &type, const QString &size)
: m_type(type), m_size(size)
{
}
QString Animal::type() const
{
return m_type;
}
QString Animal::size() const
{
return m_size;
}
AnimalModel::AnimalModel(QObject *parent)
: QAbstractListModel(parent)
, m_myProperty(0)
{
}
void AnimalModel::addAnimal(const Animal &animal)
{
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_animals << animal;
endInsertRows();
}
int AnimalModel::rowCount(const QModelIndex & parent) const {
Q_UNUSED(parent);
return m_animals.count();
}
QVariant AnimalModel::data(const QModelIndex & index, int role) const {
if (index.row() < 0 || index.row() >= m_animals.count())
return QVariant();
const Animal &animal = m_animals[index.row()];
if (role == TypeRole)
return animal.type();
else if (role == SizeRole)
return animal.size();
return QVariant();
}
bool AnimalModel::insertRows(int position, int rows, const QModelIndex &index)
{
beginInsertRows(index, position, position + rows - 1);
for (int row = 0; row < rows; ++row) {
m_animals.insert(position, Animal("new type", "new animal"));
}
endInsertRows();
return true;
}
void AnimalModel::addAnimal()
{
insertRow(0);
m_myProperty = m_animals.count();
emit myPropertyChanged();
}
//![0]
QHash<int, QByteArray> AnimalModel::roleNames() const {
QHash<int, QByteArray> roles;
roles[TypeRole] = "type";
roles[SizeRole] = "size";
return roles;
}
//![0]
最后是view.qml:
import QtQuick 2.0
import QtQuick.Controls 2.2
//![0]
Column {
ListView {
id: list
width: 200; height: 250
model: myModel
delegate: Text {
text: index + ": Animal: " + type + ", " + size + ", " + list.model.myProperty
Connections {
target: myModel
onMyPropertyChanged: {
console.log(index + ", " + list.model.myProperty)
}
}
}
}
Button {
onClicked: {
myModel.addAnimal()
}
}
}
//![0]
很簡單 按下按鈕並調用addAnimal()
我希望看到如下控制台輸出:
qml: 0, 4
qml: 1, 4
qml: 2, 4
qml: 3, 4
但是我看到的是:
qml: 1, 4
qml: 2, 4
qml: 3, 4
但是,由於UI不僅顯示了具有更新的動物列表大小的新添加的項目,而且其他所有行均已更新,因此肯定會發出(並接收到)信號。 那么,為什么新行沒有收到onMyPropertyChanged
?
這是Qt錯誤嗎? 我正在使用Qt 5.9.5。
當您使用insertRow(0)
您將插入位置0,因此,先前的0元素現在將成為具有連接並接收信號的元素。
因此,在單擊click時最后插入的元素將沒有連接,因此不會被通知。
為了說明,我將逐步解釋它:
在第一個插入物中沒有元素,因此沒有人接收信號。
在第二次插入中,前一個0元素將是當前元素1,並且具有連接,因此將被通知。
在第三個插入中,前一個0元素將是當前1,而前一個0將是當前2,因此1、2具有連接並將被通知。
總之,在myPropertyChanged
信號發出之后,委托的創建,因此將不通知插入的委托,其他人將得到通知,並且由於您的插入始終位於第一個位置,因此它將永遠不會打印qml: 0, n
為了以圖形方式理解,假設有委托,並且由於委托已經存在,他們將收到通知:
0 0 (+)
0 (+) 1 (+) 1 (+)
1 (+) 2 (+) 2 (+)
2 (+) 3 (+) 3 (+)
... --> clicked --> myPropertyChanged --> ... --> 4 (+)
n (+) n+1 (+) n+1 (+)
(+):表示有連接
更多說明:
需要明確的是,事件循環的規則如下:優先執行順序任務,如果信號不緊急,則等待信號調用。
讓我們更詳細地分析您的代碼:
前幾行是按順序執行的,因此在第一步結束時,模型中已經有一個新元素,但是視圖尚未更新,因為為此,代碼必須返回到事件循環,並且必須完成執行步驟3。
在完成第3步之后,便執行了信號任務,因此您要做的就是創建委托和連接,因此現在您將myPropertyChanged
信號賦予優先級,並調用現有連接減去最后一個連接,因為該連接在以下情況不存在:信號發出了。
總而言之,只有在信號發射時存在的插槽才會被調用,在信號發射后立即創建的新連接將一直被調用,直到調用插槽為止。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.