Qt子控件全屏的一种方法

目录

  • 引言
  • 实现思路
  • 代码

引言

常见的子控件方法如下:

setWindowFlags (Qt::Window);
showFullScreen ();
setWindowFlags (Qt::SubWindow);
showNormal ();

由于showFullScreen()只对顶级窗口有效果,对子窗口无效。全屏前需要设置windowsFlags为Qt::Window,退出全屏需要设置为Qt::SubWindow。

以上能够满足windows的常规使用,但在linux和mac下无法满足,对复杂应用也会出现不能适配的情况。

由此打算自己实现一个通用的方法,也避免对不同平台进行过多适配,简化代码。

实现思路

上述方法中,设置windowFlags就是为了让子窗体变成弹窗,借以调用全屏函数。但退出全屏使用showNormal将弹窗还原为子控件,总觉得是瞎猫碰到死耗子,实际showNormal的原意并非如此。

所以按照之前的逻辑,同时为了避免设置windowFlags,可以设置一个专用来展示全屏的弹窗,将需要全屏的控件移动至全屏弹窗布局中,继而实现全屏。

主要逻辑如下:
1.全屏则将“目标控件”加入“全屏弹窗”布局,并通过setGeometry使弹窗占满当前屏幕,移动到顶层显示
2.退出全屏则将“目标控件”恢复布局,隐藏“全屏弹窗”
3.为保证退出全屏后“目标控件”能恢复原样,需要“占位控件”作为恢复原布局的指引,即找到替换位置
4.控件布局的替换通过QLayout::replaceWidget实现
5.上述方法基于“目标控件”原本已经存在布局中,所以应增加容错判断

实现效果如下:
Qt子控件全屏的一种方法_第1张图片

代码

class FullScreenDlg : public QDialog
{
    Q_OBJECT

public:
    FullScreenDlg(QWidget *parent = nullptr);
    ~FullScreenDlg();

    bool moveFullScreen(QWidget* tmpWidget);
    bool moveNormal();

protected:
    void keyPressEvent(QKeyEvent *ev) Q_DECL_OVERRIDE;

private:
    QWidget* m_placeholderWidget;
    QWidget* m_contextWidget;
};
FullScreenDlg::FullScreenDlg(QWidget *parent)
    : QDialog(parent, Qt::WindowFlags() | Qt::FramelessWindowHint)
    , m_contextWidget(nullptr)
{
    m_placeholderWidget = new QWidget(this);

    auto mainLayout = new QHBoxLayout(this);
    mainLayout->setMargin(0);
    mainLayout->addWidget(m_placeholderWidget);
}

FullScreenDlg::~FullScreenDlg()
{

}

bool FullScreenDlg::moveFullScreen(QWidget *tmpWidget)
{
    if(tmpWidget->parentWidget() == nullptr || tmpWidget->parentWidget()->layout() == nullptr)
        return false;

    if(tmpWidget->parentWidget()->layout()->replaceWidget(tmpWidget, m_placeholderWidget)){
        m_contextWidget = tmpWidget;
        layout()->addWidget(m_contextWidget);
        auto tmpGeometry = qApp->desktop()->availableGeometry(QCursor::pos());
        setGeometry(tmpGeometry);
        show();
        raise();
        return true;
    }

    return false;
}

bool FullScreenDlg::moveNormal()
{
    if(m_contextWidget == nullptr)
        return false;

    if(m_placeholderWidget->parentWidget()->layout()->replaceWidget(m_placeholderWidget, m_contextWidget)){
        m_contextWidget = nullptr;
        layout()->addWidget(m_placeholderWidget);
        hide();
        return true;
    }

    return false;
}

void FullScreenDlg::keyPressEvent(QKeyEvent *ev)
{
    if(ev->key() == Qt::Key_Escape){
        moveNormal();
    }
    return QDialog::keyPressEvent(ev);
}
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_dlg = new FullScreenDlg(this);

    auto contentWidget = new QLabel(this);
    contentWidget->setStyleSheet("QLabel{background-color:yellow;}");
    contentWidget->setText("to be continue...");

    auto fullBtn = new QPushButton("switch", contentWidget);
    fullBtn->setCheckable(true);
    connect(fullBtn, &QPushButton::clicked, this, [=]{
        if(fullBtn->isChecked()){
            m_dlg->moveFullScreen(contentWidget);
        }
        else{
            m_dlg->moveNormal();
        }
    });

    auto mainWidget = new QWidget(this);
    setCentralWidget(mainWidget);

    auto mainLayout = new QHBoxLayout(mainWidget);
    mainLayout->addWidget(contentWidget);
}

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

你可能感兴趣的:(qt,qt,ui,开发语言)