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