从类外部访问小部件

Accessing a widget from outside of its class?

本文关键字:小部 访问 外部      更新时间:2023-10-16

在Qt Creator中,我有几个小部件声明如下:

头文件:

    class MapViewer : public QGraphicsView
{
    Q_OBJECT
public:
    explicit MapViewer(QGraphicsScene *scene, QWidget *parent = 0);
    ~MapViewer();
public slots:
    void mousePressEvent(QMouseEvent *event);
};
// Declaration for the map editor window.
class MapEditor : public QMainWindow
{
    Q_OBJECT
public:
    explicit MapEditor(QWidget *parent = 0);
    ~MapEditor();
public:
    QLayout *editorLayout;
    QPushButton *btn;
    QGraphicsScene *mapScene;
    MapViewer *mapView;
private:
    Ui::MapEditor *ui;
};

CPP 文件:

  MapEditor::MapEditor(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MapEditor)
{
    ui->setupUi(this);
    this->setWindowTitle("2DXY :: Map Editor");
    this->setGeometry(10,10,1170,750);
    editorLayout = new QVBoxLayout; // Create a new layout
    this->setLayout(editorLayout); // Set the widget's layout to our newly created layout.
    mapScene = new QGraphicsScene(); // Create a new graphics scene to draw upon.
    mapView = new MapViewer(mapScene,this); // Create a new graphics view to display our scene - set its parent to 'this' so that it doesn't open in a new window.
    mapView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    mapView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    mapView->setGeometry(20,20,1178,546); // Width first, then height.

和:

void MapViewer::mousePressEvent(QMouseEvent *event)
{
    // Show an empty message box, just to check that the event handler works!
    QMessageBox *notification = new QMessageBox();
    notification->show();
    notification->exec();
    // Some how access the same QGraphicsScene and View (mapScene, mapView) as above, so
    // I can update their contents on the open form / window.
}

如您所见,我希望再次访问图形场景以更新它,然后重绘它(或其他什么)。但是我根本无法访问图形场景,尽管以不同的方式声明小部件进行了几个小时的反复试验。

我知道侦听器本身是有效的,因为如果它设置为打开一个新的消息框,或输出到调试窗口,那么它就可以工作,只是我无法访问我已经定义的小部件。

我觉得这个问题有一个(相对)简单的解决方案,我只是错过了一些明显的东西。

您将QGraphicsScene传递给MapRender对象的构造函数。如何处理构造函数中的场景?理想情况下,您应该将其存储为 MapRender 的数据成员。例如:

class MapRender {
public:
    MapRender(QGraphicsScene* scene)
      : scene_(scene)
    {
    }
public slots:
    void mousePressEvent(QMouseEvent *event);
private:
    QGraphicsScene* scene_;
}

现在在你实现mousePressEvent,你可以访问场景成员:

void MapRender::mousePressEvent(QMouseEvent *event) {
    int CursorX = event->globalX();
    int CursorY = event->globalY();
    QGraphicsRectItem *clickedBox = new QGraphicsRectItem(40,40,32,32);
    clickedBox->setBrush(QBrush(Qt::blue));
    scene_->addItem(clickedBox);
}

请记住,理想情况下,您应该将构造函数的实现放在 cpp 文件中,但为了简洁起见,我的示例在声明中这样做。

void MapViewer::mousePressEvent(QMouseEvent *event)
{
    // Show an empty message box, just to check that the event handler works!
    QMessageBox *notification = new QMessageBox();
    notification->show();
    notification->exec();
    //  To add something whenever the user clicks, you don't need the view,
    //  just the scene.
    scene()->addItem( new MyItem() );
}

请记住,MapViewer派生自QGraphicsView,视图必须知道它所属的场景 - 因此它有一个scene()方法来返回它,您继承了它。