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.上述方法基于“目标控件”原本已经存在布局中,所以应增加容错判断

实现效果如下:
在这里插入图片描述

代码

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;
}

遮挡任务栏

	auto tmpGeometry = qApp->desktop()->screenGeometry(QCursor::pos());
	setGeometry(tmpGeometry);
  • 7
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Arui丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值