QT Linux窗口完全置顶,自定义标题栏,可拖动,圆角

1、背景
如果在项目实际中需要窗口在任何情况下都是处于置顶状态,可以设置setWindowFlags( windowFlags()|Qt::WindowStaysOnTopHint| Qt::X11BypassWindowManagerHint );
这里Qt::X11BypassWindowManagerHint是linux特有的。设置完标志后,窗口自带的标题栏就不显示了,而且不能拖动。我们需要给它再将标题栏加上,并且实现可鼠标拖动。如果为了显示效果,可以实现窗口圆角。上代码:
2、代码

class TopDialog : public QDialog
{
    Q_OBJECT

public:
    explicit TopDialog(QWidget *parent = nullptr);
    ~TopDialog();

private:
    Ui::TopDialog *ui;
    QLabel *pLabel;

protected:
    QPoint pos;

    virtual bool eventFilter(QObject *obj,QEvent* ev) override;
    virtual void paintEvent(QPaintEvent* event) override;
    virtual void enterEvent(QEvent* event) override;
    virtual void showEvent(QShowEvent* event) override;

};

这里的pLabel是我们自定义的标题栏,eventFilter是为了显示鼠标拖动pLabel的时候,整个窗口都跟着移动。

TopDialog::TopDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::TopDialog)
{
    ui->setupUi(this);
    setWindowFlags( Qt::WindowStaysOnTopHint| Qt::X11BypassWindowManagerHint );
    pLabel = new QLabel(this);
    pLabel->setText("信息提交");
    pLabel->setAlignment(Qt::AlignVCenter|Qt::AlignHCenter);
    pLabel->setStyleSheet("\
    background-color:hsl(160,0,240);\
    border-top-left-radius:5px;\
    border-top-style:solid;border-top-width:1px;border-top-color:rgb(198,198,198);\
    border-left-style:solid;border-left-width:1px;border-left-color:rgb(198,198,198);\
    border-right-style:solid;border-right-width:1px;border-right-color:rgb(198,198,198);\
    border-top-right-radius:5px;\
                            ;");

    pLabel->setGeometry(0,0,this->width(),30);
    setAttribute(Qt::WA_TranslucentBackground);  //设置窗口背景透明

    pLabel->installEventFilter(this);
    this->setStyleSheet("\
                        QDialog{\
                        background-color:rgb(248,248,248);\
                        border-radius:5px;\
                        border-style:solid;\
                        border-width:1px;\
                        border-color:rgb(198,198,198);\
                        \
                        }");
}

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

bool TopDialog::eventFilter(QObject *obj,QEvent* ev)
{
    if(obj == pLabel){
        if(ev->type()==QEvent::Type::MouseButtonPress)//判断是否有鼠标点击事件
        {
            QMouseEvent* e=static_cast<QMouseEvent*> (ev);
            if(e->button()==Qt::LeftButton)//判断是否是左键点击
            {
                pos=e->pos();
            }
        }
        else if(ev->type()==QEvent::Type::MouseMove)//判断是否有鼠标移动事件
        {
            QMouseEvent* e=static_cast<QMouseEvent*> (ev);
            if(e->buttons()==Qt::LeftButton)//判断历史点击是否是左键点击
            {
                int x,y;
                x=e->pos().x()-pos.x();
                y=e->pos().y()-pos.y();
                this->move(this->x()+x,this->y()+y);
            }
        }
    }
    return QDialog::eventFilter(obj,ev);
}

void TopDialog::paintEvent(QPaintEvent* event)
{
    QStyleOption opt;
    opt.init(this);
    QPainter painter(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
}

void TopDialog::showEvent(QShowEvent* event)
{
    setWindowFlags( windowFlags()|Qt::WindowStaysOnTopHint| Qt::X11BypassWindowManagerHint );
    activateWindow();
}

void TopDialog::enterEvent(QEvent* event)
{
    setWindowFlags( windowFlags()|Qt::WindowStaysOnTopHint| Qt::X11BypassWindowManagerHint );
    activateWindow();
}

效果图:
在这里插入图片描述
3、讲解:

  • 可以看到显示效果是有一些圆角效果,主要是通过setAttribute(Qt::WA_TranslucentBackground); //设置窗口背景透明
    重写void TopDialog::paintEvent(QPaintEvent* event)虚函数。并且加入了主窗口的QSS和pLabel的QSS实现的。pLabel下边框没有设置。
  • pLabel是直接贴着父窗口,并且高度写死,就是为了模拟原来的标题栏
  • 我们的窗口有一个输入框,需要用户输入,但是如果切换焦点,再切回来,那么这个输入框会获取不到焦点。所以我们重写了showEvent和enterEvent
  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值