我在一段时间后再次使用Qt(第5.3节)。作为一个学习练习,我使用QGraphicView对模块进行原型设计,以便更好地理解如何使用它。
功能很简单:我有几个QGraphicObjects,其功能类似于具有状态和行为的按钮:
启动时,所有按钮都处于OFF状态
一切都是数据驱动的,并在运行时动态创建。
这是我的小小学习练习。我要解决的是一种有效的消息传递机制来处理“单选按钮有时”的独占行为,并向一组对象发送消息而不强烈耦合它们。
我使这比需要的更复杂但正如我所说,这是一个习惯再次习惯Qt的学习练习。
所以我的问题(最后):是否有一种我忽略的方法或其中一种更好的方法(例如最灵活,可维护,可扩展)。不是寻找代码本身,而是了解如何使用Qt框架编写类似的代码。
这是事物的图像:
答案 0 :(得分:0)
子类QGraphicsScene
重新实现mousePressEvent并按下鼠标左键。
如果是这样,则通过pos()方法获取鼠标的位置,并通过itemAt()方法获取箭头下的当前图形对象。
尝试将其投射到您需要的对象中,如果成功,则更改背景和其他对象。
将图形对象存储在矢量中,在这种情况下,您可以检查每个对象并确定应关闭哪个对象。
完全正常的例子:
头:
#ifndef GRAPHICSSCENE_H
#define GRAPHICSSCENE_H
#include <QGraphicsScene>
#include <QPoint>
#include <QMouseEvent>
class GraphicsScene : public QGraphicsScene
{
Q_OBJECT
public:
explicit GraphicsScene(QObject *parent = 0);
signals:
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
public slots:
private:
QVector<QGraphicsEllipseItem * > vec;
};
#endif // GRAPHICSSCENE_H
CPP:
#include "graphicsscene.h"
#include <QDebug>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsItem>
GraphicsScene::GraphicsScene(QObject *parent) :
QGraphicsScene(parent)
{
//set circles in different positions.
vec.push_back(addEllipse(0,0,50,50,QPen(Qt::red),QBrush(Qt::blue)));
vec.push_back(addEllipse(0+100,0+100,50,50,QPen(Qt::red),QBrush(Qt::blue)));
vec.push_back(addEllipse(0+150,0+150,50,50,QPen(Qt::red),QBrush(Qt::blue)));
}
void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
//qDebug() << "in";
if (mouseEvent->button() == Qt::LeftButton)
{
QGraphicsItem *item = itemAt(mouseEvent->scenePos(), QTransform());
QGraphicsEllipseItem *ell = qgraphicsitem_cast<QGraphicsEllipseItem *>(item);
if(ell)
{
for(int i = 0; i < vec.size(); i++)
{
if(vec.at(i) != ell)
{
vec.at(i)->setBrush(QBrush(Qt::blue));//disable all other bettons
}
}
ell->setBrush(QBrush(Qt::black));//to chosen circle
qDebug() << "good";
}
else
qDebug() << "not ell" << mouseEvent->scenePos();
}
}
用法:
GraphicsScene *scene = new GraphicsScene(this);
ui->graphicsView->setScene(scene);
在这种情况下,您的圈子将类似于radioButtons。如果您想要保存所有按钮的状态,可以使用:
for(int i = 0; i < vec.size(); i++)
vec.at(i)->setData(0,false);
以
获取状态if(!ell->data(0).toBool())
//do
答案 1 :(得分:0)
信号和插槽是我在这里使用的方法。但是,您可以创建一个中间的Controller类,而不是将每个按钮连接到其他每个按钮。
Controller类可以聚合,也可以是所有按钮的父级。
创建按钮时,它会将信号连接到控制器以通知其被按下。然后,Controller类中的接收槽负责关闭任何其他按钮。
骨架代码: -
class ButtonController : public QGraphicsObject
{
public slots:
void ButtonPressed();
private:
QList<MyButton*> m_buttonList;
};
void ButtonController::ButtonPressed()
{
foreach(MyButton* pButton, m_buttonList)
{
if(pButton != sender())
{
pButton->Off();
}
}
}
在MyButton的构造函数中,假设控制器是父级: -
MyButton::MyButton(ButtonController* parent)
: QGraphicsObject(parent);
{
connect(this, &MyButton::pressed(), parent, &ButtonController::ButtonPressed());
...
}
或者,控制器可以只保存按钮列表,在这种情况下,您可以执行此操作: -
MyButton::MyButton(QObject* parent, ButtonController* pButtonController)
: QGraphicsObject(parent);
{
connect(this, &MyButton::pressed(), pButtonController, &ButtonController::ButtonPressed());
...
}
如果无法更改按钮的构造函数,控制器可能只有一个AddButton函数,当按钮被添加到其控件下时,它会创建连接。