如何使Qt Mainwindow彼此连接?

时间:2018-07-09 06:38:22

标签: c++ qt qt5

我在Qt中创建了两个QMainWindow类ui。单击MainWindowA中的按钮后,将显示MainWindowB。我想将MainWindowB附加到MainWindowA(当两个主窗口关闭时,它们像磁铁一样卡在一起),以便可以将它们作为“已附加”一起移动。如果将它们分开,它们将只是常规的QMainWindow。我该如何实现?

我尝试使用QDockWidget,但是当它“附加”(对接)时,它将影响原始MainWindowA中的其他组件。

enter image description here

mainwindowA.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    MainWindowB *newWin= new MainWindowB;
    newWin->show();
}

mainwindowB.cpp

#include "mainwindowb.h"
#include "ui_mainwindowb.h"

MainWindowB::MainWindowB(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindowB)
{
    ui->setupUi(this);
}

MainWindowB::~MainWindowB()
{
    delete ui;
}

1 个答案:

答案 0 :(得分:1)

您可以实现以下非常简单的方法:

#include <QApplication>
#include <QMainWindow>

class CMasterWindow : public QMainWindow
{
    Q_OBJECT

public:
    CMasterWindow(QWidget *parent = Q_NULLPTR)
        : QMainWindow(parent)
    {
        setWindowTitle(tr("master"));
    }

    ~CMasterWindow() { }

    virtual void moveEvent(QMoveEvent *me) Q_DECL_OVERRIDE
    {
        QMainWindow::moveEvent(me);
        emit SignalMoved(QRect(pos(), size()));
    }

    virtual void resizeEvent(QResizeEvent *re) Q_DECL_OVERRIDE
    {
        QMainWindow::resizeEvent(re);
        emit SignalMoved(QRect(pos(), size()));
    }

signals:
    void SignalMoved(QRect const &r);
};

class CSlaveWindow : public QMainWindow
{
    Q_OBJECT

public:
    CSlaveWindow(CMasterWindow *master)
        : QMainWindow(master),
        mpMaster(master),
        mbLocked(master != Q_NULLPTR)
    {
        setWindowTitle(tr("slave"));
        if(mpMaster != Q_NULLPTR)
        {
            bool ok = connect(mpMaster, &CMasterWindow::SignalMoved, this, &CSlaveWindow::MasterMovedSlot);
            Q_ASSERT(ok);
            mMasterRect = QRect(mpMaster->pos(), mpMaster->size());
            MasterMovedSlot(mMasterRect);
        }
    }
    ~CSlaveWindow() { }

    static int const snapMargin = 16;

    virtual void moveEvent(QMoveEvent *me) Q_DECL_OVERRIDE
    {
        QMainWindow::moveEvent(me);
        if(pos() == mExpectedMove)
        {
            // ignore self-initiated move (from MasterMovedSlot())
            return;
        }

        mbLocked = QRect(mMasterRect.topRight(), 2 * QSize(snapMargin, snapMargin)).intersects(QRect(pos(), QSize(snapMargin, snapMargin)));
        MasterMovedSlot(mMasterRect);
    }

private slots:
    void MasterMovedSlot(QRect const &r)
    {
        if(mbLocked)
        {
            mExpectedMove = r.topRight() + QPoint(snapMargin, 0);
            move(mExpectedMove);
        }
        mMasterRect = r;
    }

private:
    CMasterWindow *mpMaster;
    bool mbLocked;
    QPoint mExpectedMove;
    QRect mMasterRect;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    CMasterWindow *master = new CMasterWindow();
    master->show();
    (new CSlaveWindow(master))->show();

    return a.exec();
}

您需要将一个窗口定义为主窗口,将另一个窗口定义为从窗口-否则,您将无法分辨希望将两个窗口一起移动或希望将一个窗口从另一个窗口撕下的用户之间的区别。