我使用qt quick 2.0。 gridview绑定到c ++模型,如here中所述。在gridview的委托中,我使用图像来显示图标。我尝试使用state属性来更改图像源并将状态绑定到模型。
预期结果将在发布时所选的屏幕图像应更改为正在运行的图标。
图像的实际结果不会改变。如果我在ScreenManager :: setScreenState中使用setName而不是setState,它会正确显示更改的屏幕名称。
有没有更好的解决方案?
Screen.h
class Screen
{
public:
Screen(QString name, int gridId, bool active = false);
QString name() const;
int gridId() const;
bool active() const;
QString state() const;
void setName(QString n);
void setActive(bool a);
void setState(QString s);
private:
QString m_name;
int m_gridId;
bool m_active;
QString m_state;
};
ScreenManager.h
class ScreenManager : public QAbstractListModel
{
Q_OBJECT
public:
enum ScreenRoles {
NameRole = Qt::UserRole + 1,
GridIDRole,
ActiveRole,
StateRole
};
ScreenManager();
void addScreen(const Screen& screen);
int rowCount(const QModelIndex& parent = QModelIndex()) const;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
QModelIndex getIndex(int row, int column = 0,
const QModelIndex &parent = QModelIndex()) const;
Q_INVOKABLE int getScreenGridId(int index);
Q_INVOKABLE bool getScreenActive(int index);
Q_INVOKABLE void swapScreens(int index1, int index2);
Q_INVOKABLE void setScreenState(int index, QString s);
Q_INVOKABLE QString getScreenState(int index);
protected:
QHash<int, QByteArray> roleNames() const;
private:
QList<Screen> m_screens;
};
ScreenManager.cpp
#include "ScreenManager.h"
#include "Screen.h"
ScreenManager::ScreenManager()
{
int index = 0;
for (;index < 15; index++) {
addScreen(Screen(QString ("Screen%1").arg(index), index, false));
}
m_screens[2].setActive(true);
m_screens[6].setActive(true);
m_screens[7].setActive(true);
m_screens[8].setActive(true);
m_screens[12].setActive(true);
}
void ScreenManager::addScreen(const Screen& screen)
{
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_screens.append(screen);
endInsertRows();
}
int ScreenManager::rowCount(const QModelIndex& parent) const {
Q_UNUSED(parent);
return m_screens.count();
}
QVariant ScreenManager::data(const QModelIndex& index, int role) const
{
if (index.row() < 0 || index.row() >= m_screens.count())
return QVariant();
const Screen& screen = m_screens[index.row()];
if (role == NameRole)
return screen.name();
else if (role == GridIDRole)
return screen.gridId();
else if (role == ActiveRole)
return screen.active();
else if (role == StateRole)
return screen.state();
return QVariant();
}
QModelIndex ScreenManager::getIndex(int row, int column,
const QModelIndex &parent) const
{
return hasIndex(row, column, parent) ?
createIndex(row, column, (void*)&m_screens[row])
: QModelIndex();
}
QHash<int, QByteArray> ScreenManager::roleNames() const
{
QHash<int, QByteArray> roles;
roles[NameRole] = "name";
roles[GridIDRole] = "gridId";
roles[ActiveRole] = "active";
roles[StateRole] = "state";
return roles;
}
int ScreenManager::getScreenGridId(int index)
{
return m_screens.at(index).gridId();
}
bool ScreenManager::getScreenActive(int index)
{
return m_screens.at(index).active();
}
void ScreenManager::swapScreens(int index1, int index2)
{
int min = index1 < index2 ? index1 : index2;
int max = index1 > index2 ? index1 : index2;
m_screens.swap(index1, index2);
beginMoveRows(QModelIndex(), max, max, QModelIndex(), min);
endMoveRows();
if (max - min > 1) {
beginMoveRows(QModelIndex(), min + 1, min + 1, QModelIndex(), max + 1);
endMoveRows();
}
}
void ScreenManager::setScreenState(int index, QString s)
{
// if use setName, the grid view can show the changed screen name
m_screens[index].setState(s);
dataChanged(getIndex(0), getIndex(rowCount() - 1));
}
QString ScreenManager::getScreenState(int index)
{
return m_screens[index].state();
}
QML
GridView {
id: gridView
x: 82
y: 113
width: cellWidth * 5
height: cellHeight * 3
clip: true
anchors.bottom: parent.bottom
anchors.bottomMargin: 70
anchors.topMargin: 100
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
flickableDirection: Flickable.HorizontalAndVerticalFlick
cellWidth: 90; cellHeight: 90;
property bool ignoreMovementAnimation: true
MouseArea {
id: gridViewMouseArea
hoverEnabled: true
preventStealing : true
property int currentGridId: -1
property int preIndex
property int index: gridView.indexAt(mouseX, mouseY)
anchors.fill: parent
onPressAndHold: {
currentGridId = screenManager.getScreenGridId(index)
preIndex = index
gridView.ignoreMovementAnimation = false
}
onReleased: {
currentGridId = -1
screenManager.setScreenState(index, "running");
}
onPositionChanged: {
if (currentGridId != -1 && index != -1 && index != preIndex) {
if (screenManager.getScreenActive(index)) {
screenManager.swapScreens(preIndex, index)
preIndex = index
}
}
}
}
model: screenManager
delegate: Component {
Item {
id: gridViewDelegate
width: gridView.cellWidth; height: gridView.cellHeight
state: state
states: [
State {
name: "running"
PropertyChanges {
target: itemImage
source: "qrc:/res/image/screen_icon_running.png"
}
},
State {
name: "idle"
PropertyChanges {
target: itemImage
source: "qrc:/res/image/screen_icon_idle.png"
}
}
]
Image {
id: itemImage
parent: gridView
x: gridViewDelegate.x + 5
y: gridViewDelegate.y + 5
width: gridViewDelegate.width - 10
height: gridViewDelegate.height - 10;
fillMode: Image.PreserveAspectFit
smooth: true
source: "qrc:/res/image/screen_icon.png"
visible: active
Text {
text: name
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
anchors.fill: parent;
border.color: "grey"
border.width: 6
color: "transparent"; radius: 5
visible: itemImage.state === "active"
}
// specify the movement's animation for non-active screen icons
Behavior on x {
enabled: !gridView.ignoreMovementAnimation && itemImage.state !== "active"
NumberAnimation { duration: 400; easing.type: Easing.OutBack }
}
Behavior on y {
enabled: !gridView.ignoreMovementAnimation && itemImage.state !== "active"
NumberAnimation { duration: 400; easing.type: Easing.OutBack }
}
// specify the shaking animation for non-active screen icons when hold one icon
SequentialAnimation on rotation {
NumberAnimation { to: 2; duration: 60 }
NumberAnimation { to: -2; duration: 120 }
NumberAnimation { to: 0; duration: 60 }
running: gridViewMouseArea.currentGridId != -1 && itemImage.state !== "active"
loops: Animation.Infinite
alwaysRunToEnd: true
}
// specify the active screen's new position and size
states: State {
name: "active"
when: gridViewMouseArea.currentGridId == gridId
PropertyChanges {
target: itemImage
x: gridViewMouseArea.mouseX - width/2
y: gridViewMouseArea.mouseY - height/2
scale: 0.5
z: 10
}
}
// specify the scale speed for the active screen icon
transitions: Transition {
NumberAnimation { property: "scale"; duration: 200}
}
}
}
}
}
答案 0 :(得分:1)
您有一个命名问题,因为状态也知道您的项目委托中的州属性。
我换了之后:
document.getElementById('ID_OF_YOUR_DIV').appendChild(image);
你在c ++中
和:
roles[StateRole] = "statetest";
你的qml中的, 它有效。
或者简单地说:
state: statetest
你的qml中的
答案 1 :(得分:0)
我通过将图像源绑定到Screen,stateIamge中的另一个属性来解决问题,而不是直接将其绑定到状态。
但我仍然有兴趣了解为什么绑定到州不起作用。