- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在另一个问题中,您告诉我使用 QStateMachine。
我是 Qt 的新手,这是我第一次使用对象,所以我犯了很多逻辑错误,所以使用 QStateMachine 是个大问题......
这是唯一的方法吗?我试着解释我的程序:
我想创建一个卡片游戏,在以前的版本中,我使用了一个带有以下命令序列的旧图形库:
-> print cards on the scene
-> wait for a mouse input (with a do-while)
-> if(isMouseClick(WM_LBUTTONDOWN))
-> if(mouse position is on the first card)
-> select that card. So i wish to do the same thing with QGraphics.
通过这种方式我告诉程序:
-> print cards
-> wait for a mouse event
-> print the card that I've selected with that event.
现在我想改变程序图形,我引入了QGraphics。我已经创建了一个场景并在上面打印了所有对象“卡片”,所以现在我想告诉程序:
-> print the object and wait the mouse input
-> if a card is to selected with the left clik
-> print that card in scene, wait 1/2 second and go ahead with the program
问题是我使用 for
1 到 20(我必须在一场比赛中运行 20 次)。我试图通过随机 G1 和 COM 播放启动程序,但应用程序卡住,直到最后一次执行 for
并且我只在现场打印最后一次配置的卡片。这是因为之前我说过我希望程序停止...
可以不用 QStateMachine 吗?简单地告诉他:“暂停”,打印这种情况,等待鼠标继续?
最佳答案
下面是一个完整的例子,长 71 行,出现在 literate programming style 中。 .它也可以在 github 上找到.该示例包含一个 qmake .pro
文件(未显示)和 main.cpp
,如下所示。该示例具有以下结构:
首先,让我们设置场景:
int main(int argc, char ** argv) {
QApplication app{argc, argv};
QGraphicsScene scene;
QGraphicsView view{&scene};
scene.addItem(new CardItem(0, 0, "A"));
scene.addItem(new CardItem(20, 0, "B"));
状态机有三种状态:
QStateMachine machine;
QState s_idle{&machine}; // idle - no card selected
QState s_selected{&machine}; // card selected, waiting 1/2 second
QState s_ready{&machine}; // ready with card selected
machine.setInitialState(&s_idle);
我们将使用辅助函数以声明方式向机器添加行为。这不是唯一可能的模式,但它有效并且很容易应用。首先,当任何项目被选中时,状态从 s_idle
变为 s_selected
:
on_selected(&s_idle, &scene, true, &s_selected);
然后,超时后,状态变为s_ready
:
on_delay(&s_selected, 500, &s_ready);
如果项目被取消选择,我们回到s_idle
:
on_selected(&s_selected, &scene, false, &s_idle);
on_selected(&s_ready, &scene, false, &s_idle);
因为我们没有更好的事情要做,所以我们可以在进入 s_ready
状态后简单地取消选择所有项目。这清楚地表明已进入该状态。当然,由于选择被清除,它会立即离开,我们在上面指出 s_idle
是没有选择任何项目时的状态。
QObject::connect(&s_ready, &QState::entered, &scene, &QGraphicsScene::clearSelection);
我们现在可以启动机器并运行我们的应用程序:
machine.start();
view.show();
return app.exec();
}
注意最少使用显式动态内存分配,并且没有任何手动内存管理。
CardItem
类是一个简单的卡片图形项。该项目是可选择的。它也可以是可移动的。交互由图形 View 框架自动处理:您不必手动处理解释鼠标按下/拖动/释放 - 至少现在不需要。
class CardItem : public QGraphicsObject {
Q_OBJECT
const QRect cardRect { 0, 0, 80, 120 };
QString m_text;
QRectF boundingRect() const Q_DECL_OVERRIDE { return cardRect; }
void paint(QPainter * p, const QStyleOptionGraphicsItem*, QWidget*) {
p->setRenderHint(QPainter::Antialiasing);
p->setPen(Qt::black);
p->setBrush(isSelected() ? Qt::gray : Qt::white);
p->drawRoundRect(cardRect.adjusted(0, 0, -1, -1), 10, 10);
p->setFont(QFont("Helvetica", 20));
p->drawText(cardRect.adjusted(3,3,-3,-3), m_text);
}
public:
CardItem(qreal x, qreal y, const QString & text) : m_text(text) {
moveBy(x, y);
setFlags(QGraphicsItem::ItemIsSelectable);
}
};
将状态机行为分解为可用于声明给定状态下的行为的函数很有帮助。
首先,延迟 - 一旦进入 src
状态,并且经过了给定的毫秒数,机器就会转换到目标状态:
void on_delay(QState * src, int ms, QAbstractState * dst) {
auto timer = new QTimer(src);
timer->setSingleShot(true);
timer->setInterval(ms);
QObject::connect(src, &QState::entered, timer, static_cast<void (QTimer::*)()>(&QTimer::start));
QObject::connect(src, &QState::exited, timer, &QTimer::stop);
src->addTransition(timer, SIGNAL(timeout()), dst);
}
要拦截选择信号,我们需要一个发出通用信号的辅助类:
class SignalSource : public QObject {
Q_OBJECT
public:
Q_SIGNAL void sig();
SignalSource(QObject * parent = Q_NULLPTR) : QObject(parent) {}
};
然后,我们利用这种通用信号源来描述当给定场景有选择且前提条件 selected
为真时,或没有选择且前提条件 iff selected
为假:
void on_selected(QState * src, QGraphicsScene * scene, bool selected, QAbstractState * dst) {
auto signalSource = new SignalSource(src);
QObject::connect(scene, &QGraphicsScene::selectionChanged, signalSource, [=] {
if (scene->selectedItems().isEmpty() == !selected) emit signalSource->sig();
});
src->addTransition(signalSource, SIGNAL(sig()), dst);
}
该示例以以下 header 开头:
// https://github.com/KubaO/stackoverflown/tree/master/questions/sm-cards-37656060
#include <QtWidgets>
它以以下页脚结束,包含 moc 生成的信号实现和 SignalSource
类的对象元数据。
#include "main.moc"
关于c++ - QStateMachine - QMouseEvent,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37656060/
我对带有 ParallelState 的 QStateMachine 很着迷。 我有一个包含第一个状态的主状态(顺序), 包含一组并行状态的第二个状态,以及另一个连续的状态。 第一个状态代表创建 N
我对如何测试 QStateMachine 有点困惑。我有一个组织良好的项目,一侧是源代码,另一侧是测试代码。 标题 class Foo { signals: void sigG
我创建了 4 个不同的 QState,我想在每个状态转换中隐藏一个对象。 这是代码: QStateMachine partita; QState *inizio_mano = new QState()
我已经创建了一个 QStateMachine,我必须获取导致状态转换的事件。难道没有任何机会进入我的插槽 EnterStateInit() 导致此调用的信号。这是我的示例代码: CreateState
在另一个问题中,您告诉我使用 QStateMachine。 我是 Qt 的新手,这是我第一次使用对象,所以我犯了很多逻辑错误,所以使用 QStateMachine 是个大问题...... 这是唯一的方
我的程序中有一个 QStateMachine 实例。我在它的构造函数中配置它的状态、转换和初始状态。当然,我在构造函数中启动它。 this->stateA = new StateA(this); th
为了根据转换设置对象属性,我需要两个可以立即进一步转换的中间状态: A initial state Ta Tb different transitions Aa Ab
我想用 QStateMachine 创建一个无限循环,其中我还需要动画。 QColor leastTransparent, mostTransparent = color(); leastTransp
我正在考虑使用 QStateMachine 在游戏的菜单屏幕之间进行转换。但是,我不确定如何在发生状态转换时启动一些代码(例如 show() a QWidget)。我可以使用普通的旧信号很容易地做到这
以下代码由于内存损坏而导致崩溃。我假设这是因为 delete pTestStateMachine 试图删除未在堆中分配的内存。对吗? 如果是这样,是否意味着 QStateMachine::addSta
我正在尝试弄清楚如何将我自己的自定义信号与 QStateMachine 结合使用。我从 here 中的一个简单示例开始。现在我正在尝试创建一个新信号 mysignal 并触发它的转换。但我不知道如何构
我有这个 Projekt,它使用 QStatemachine 来管理 UI,我想在其中添加自定义列表。 UI 应该只由关键事件操作。据我了解,我需要在 qml 端有一个 ListView。 ListV
我的问题如下:我需要创建包含 QStateMachine 实例的类。此类应该有插槽,您可以通过这些插槽“请求”状态机转换到另一个状态。如果转换成功,我的类(class)应该发出有关它的信号。我将如何实
我目前正在移植 small application从 PyGTK 到位于系统托盘中的 PySide,它会定期检查服务器的更新。 当我最初写这篇文章时,我使用了一个自定义状态模型来表示它的行为: ini
我正在构建一个主要采用顺序流程但也有一些替代路径的程序。我认为状态机可能是最简单的实现方式,因为 Qt 提供了这样一个类:QStateMachine (另见 API)。 不过,我的状态好像挺多的(20
我正在尝试在 Qt (C++) 中实现状态机。如何检查 QStateMachine 的当前状态?我在文档中找不到方法。 谢谢 最佳答案 你试过QStateMachine::configuration(
有一个状态机(称为外部)。这台机器有两个状态——第一个和最后一个。第一个状态是自定义实现的。在第一个状态中创建了另一个状态机(称为内部状态机),在本例中它什么也不做。 具有两个状态的外部状态机:
我正在制作一个应用程序的原型(prototype),我想从应用程序的 C++ 端的 QStateMachine 控制 QML UI 转换。为了使事情更简单,我们可以说 QML UI 由多个页面组成,这
所以我试图了解 Qt 的 QStateMachine 的一个问题,我希望有人能帮助解释为什么会这样。我对 QStateMachine 的基本理解非常感兴趣,而不仅仅是修复。 首先考虑具有状态 A、B
我是一名优秀的程序员,十分优秀!