我不确定我是否 100% 理解您在这里的要求(主要是因为您没有提供最小的可编译示例),这就是我的理解:
- 您有两个小部件,
-
class ColorWidget : public MainWidget 类型之一
-
class BWWidget : public MainWidget 之一
- 与
class MainWidget : public QOpenGLWidget
- 这两个小部件是并排可见的。
- 当您的两个小部件中的任何一个收到
mouseMoveEvent() 时,都应该显示一些内容。
如果你有这些,这些是你的选择:
- 首先,您应该移动功能以从鼠标移动事件处理程序中创建一个矩形(例如,移动到函数
MainWidget::DrawMouseMoveRectangle(QPoint pos).
- (可能:)让两个小部件相互了解(例如,通过
QPointer<MainWidget> pOther)。
- 覆盖
mouseMoveEvent() 并为this 和pOther 调用DrawMouseMoveRectangle(QPoint pos)。
- (更好:)既然您已经在使用 Qt,请创建一个信号
MainWidget::SignalMouseMove(QPoint p) 和插槽 MainWidget::MouseMovedSlot(QPoint p)。
- 在公共父窗口小部件的初始化中,您将两个窗口小部件的插槽连接到每个窗口小部件的信号(见下文)。
- 在MainWidget的
mouseMoveEvent()做emit SignalMouseMove(evt->pos)*
- 现在这两个函数的调用独立于接收事件的小部件。
如何建立连接:
bool ok = true;
ok = ok && connect(w1, &MainWidget::SignalMouseMove, w1, &MainWidget::MouseMovedSlot);
ok = ok && connect(w1, &MainWidget::SignalMouseMove, w2, &MainWidget::MouseMovedSlot);
ok = ok && connect(w2, &MainWidget::SignalMouseMove, w1, &MainWidget::MouseMovedSlot);
ok = ok && connect(w2, &MainWidget::SignalMouseMove, w2, &MainWidget::MouseMovedSlot);
Q_ASSERT(ok);
编辑
回答您的评论:
我想要的是我应该能够绘制 1 个矩形并将其传递给每个其他小部件以显示它(使用适当的几何图形),因为它使我能够移动和调整大小将反映在所有小部件上。
在两个不同的父窗口小部件中显示同一个窗口小部件实例可能是可能的,但绝对感觉像一个杂物,而不是 Qt 的设计方式。
你应该看看Qt's model-view-programming,因为这本质上是你想要实现的:
- 在两个视图中显示一个模型。
- 根据模型的任何更改更新两个视图。
因为实现QAbstractItemModel 有点矫枉过正,这里有一些替代方案:
- 使用Qt's Graphics View Framework:在两个
QGraphicsViews 中显示相同的QGraphicsScene,并将一些QGraphicsRectItem 放入场景中。
- 使用 Qt 的参数支持进行半自动数据绑定。
- 自己动手,并不难:
- 基本上,您必须将 view 逻辑与 model 逻辑分开,例如
RectangleView 和 RectangleModel。
- 然后使两者可连接,例如通过模型中的信号和视图中的插槽。
- 在您的两个小部件中创建一个视图。
- 为每个小部件提供一个指向模型的共享指针。
- 将模型与两个视图连接起来。
- 结果:无论何时更改模型(从哪个小部件都无关紧要),都会更新两个视图。
编辑 2:非常使用共享 QGraphicsRectItem 的简单示例
// this is a minimal compilable example of two views sharing the same model, with automatic update on mouse events
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QMouseEvent>
#include <QHBoxLayout>
class TestWidget : public QWidget
{
//Q_OBJECT // Not neccessary here because we don't use and don't need moc for this example. -> Don't try this at home!
public:
TestWidget() : QWidget(Q_NULLPTR),
lt(new QHBoxLayout(this)),
v1(new QGraphicsView(this)),
v2(new QGraphicsView(this)),
s(new QGraphicsScene(this)),
r(Q_NULLPTR)
{
// initialization
r = s->addRect(0, 0, 10, 10, QPen(Qt::red), Qt::yellow);
lt->addWidget(v1);
lt->addWidget(v2);
// sharing the same model:
v1->setScene(s);
v2->setScene(s);
// in reality, you need to share QGraphicsRectItem *r, too.
// (it would actually be sufficient to share *r only)
// very simple mouse interaction:
v1->viewport()->installEventFilter(this);
v1->viewport()->setMouseTracking(true);
v2->viewport()->installEventFilter(this);
v2->viewport()->setMouseTracking(true);
}
bool eventFilter(QObject *o, QEvent *evt) Q_DECL_OVERRIDE
{
QGraphicsView *gv = Q_NULLPTR;
if(o == v1->viewport())
{
gv = v1;
}
else if(o == v2->viewport())
{
gv = v2;
}
if(gv != Q_NULLPTR)
{
QPointF p;
switch(evt->type())
{
case QEvent::MouseMove:
p = static_cast<QMouseEvent*>(evt)->pos();
evt->accept();
break;
default:
break;
}
if(p != QPoint())
{
// do something different depending on interacting view - just for demonstration
if(gv == v1)
{
r->setRect(QRectF(p, r->rect().bottomRight()));
}
else
{
r->setRect(QRectF(r->rect().topLeft(), p));
}
}
}
return QWidget::eventFilter(o, evt);
}
private:
QHBoxLayout *lt;
QGraphicsView *v1;
QGraphicsView *v2;
QGraphicsScene *s;
QGraphicsRectItem *r;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TestWidget w;
w.show();
return a.exec();
}