Qt 界面开发问题汇总(持续更新)
窗口的最小化、最大化按钮自定义
setWindowFlags(Qt::CustomizeWindowHint);
setWindowFlags(Qt::WindowCloseButtonHint); // 只要关闭按钮
setWindowFlags(Qt::WindowFlags type)
全屏显示与还原
1、遮挡任务栏
// 这两个都可以!
showFullScreen(); // 设置窗口全屏显示
showMaximized(); // 设置窗口最大化显示
2、不遮挡任务栏
void showMaximize()
{
// 若已经最大化
if(is_max)
{
// 恢复界面位置,并设置按钮图标为最大化图标,提示“最大化”
this->setGeometry(location);
max_button->setIcon(QIcon("maxbtn"));
max_button->setToolTip(tr("max"));
}
else
{
// 设定当前界面的位置,还原时使用
location = this->geometry();
// 获取桌面位置,设置为最大化,并设置按钮图标为还原图标,提示“还原”
QDesktopWidget *desk = QApplication::desktop();
this->setGeometry(desk->availableGeometry());
max_button->setIcon(QIcon("restorbtn"));
max_button->setToolTip(tr("restor"));
}
is_max = !is_max;
}
注:窗口既然可以最大化,当然还要进行还原,is_max 为一个 bool 值变量,表示窗口是否最大化,初始值为 false。location 为桌面的位置,每次最大化开始先记录当前的位置,等待还原时候使用。
扩展:
isFullScreen(); // 判断窗口当前是处于全屏状态还是非全屏状态
showNormal(); // 设置窗口恢复原来显示
隐藏任务栏显示
setWindowFlags(Qt::Tool | Qt::X11BypassWindowManagerHint);
绘制背景图片并且实现圆角效果
void paintEvent(QPaintEvent *)
{
QPainter painter(this);
QBrush brush;
brush.setTextureImage(QImage(background_image)); // 背景图片
painter.setBrush(brush);
painter.setPen(Qt::black); // 边框色
painter.drawRoundedRect(this->rect(), 5, 5); // 圆角5像素
}
Qt设置窗体透明
1、全透明
setWindowOpacity(double value)。该函数用来设置窗体透明度,有效范围从 1.0 到 0.0,并且会影响子控件。默认情况下,此属性的值是 1.0(不透明)。
this->setWindowOpacity(0.7);
2、子控件透明
使用 Qt 样式表,background:rgba(r, g, b, opacity),rgb 是颜色值,opacity 是设置为半透明的透明度,有效范围从 1.0 到 0.0。使用样式表设置一张背景图,以及 widget 和 label 的透明度(设置透明度要指定对象,避免影响其他控件)
//子控件透明
this->setStyleSheet("#centralWidget{border-image:url(://timg.jpg);}"
"#label{background:rgba(255,255,0,0.4);}"
"#widget{background:rgba(255,0,0,0.3);}");
3、父窗口透明
情况一:背景无图片。设置属性 Qt::WA_TranslucentBackground 将 MainWindow 变为全透明,在 windows 上这个属性需配合 Qt::FramelessWindowHint 使用。然后设置 centralWidget 样式中的 opacity 调节父窗口的透明度并设置子控件不透明。
this->setWindowFlags(Qt::FramelessWindowHint);//需要去掉标题栏
this->setAttribute(Qt::WA_TranslucentBackground);
this>setStyleSheet("#centralWidget{background:rgba(0,255,255,0.4);}"
"#label{background:rgba(255,255,0,1);}"
"#widget{background:rgba(0,255,255,1);}");
情况二:背景有图片。仍然使用属性 Qt::WA_TranslucentBackground 将 MainWindow 变为全透明。然后在 paintevent 中将图片绘制在窗体上,并设置透明度。
void MainWindow::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QPixmap pix("://timg.jpg");
QPixmap scalePix = pix.scaled(this->width(), this->height(),
Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
painter.setOpacity(0.4);
painter.drawPixmap(0, 0, scalePix);
}
注:若设置背景属性失败,可尝试设置该属性解决:setAttribute(Qt::WA_StyledBackground);
。
设置应用程序的字体
QFont font("Courier", 10, QFont::Normal, false);
QApplication::setFont(font);
Qt 无边框窗口的两种实现
setWindowFlags(Qt::CustomizeWindowHint);
setWindowFlags(Qt::FramelessWindowHint);
两个函数都可以去掉标题栏,区别是第一个可以鼠标缩放窗口。
Qt设置活动窗口
遇到一个 Qt 窗口问题记录下,已经显示的窗口被其他窗口遮挡。再调用 show 无法将窗口激活显示到最前面。解决方式如下:
if(!this->isActiveWindow()) //判断是否是活动窗口
{
this->activateWindow(); //设置成活动窗口
}
如何判断一个窗口是否关闭
bool QWidget::isVisible(); // 窗口显示返回true
bool QWidget::isHidden(); // 窗口隐藏返回true
如果 widget 设置了 Qt::WA_DeleteOnClose 的话,widget 调用 close() 会被 delete,这种情况可以在外部用一个 flag 记录和判断。
窗口关闭时释放内存
当用户关闭窗口时,其默认行为是隐藏,所以还会保留在内存中,解决方法是在构造函数中加入这个一句:setAttribute(Qt::WA_DeleteOnClose);
Qt::WA_DeleteOnClose 属性是可以在 QWidget 上进行设置并影响这个窗口部件的行为的标记之一。
Qt捕捉窗口关闭事件
有时候我们希望在关闭窗口之前做一些操作,例如保存缓存数据或向用户提示是否关闭窗口等等。由于一般的窗口都是继承自 QWidget, 那么我们可以通过覆盖 QWidget 中的虚函数closeEvent(QCloseEvent* event);
来达到这个目的。
void MainWindow::closeEvent(QCloseEvent *event)
{
QMessageBox::StandardButton button;
button=QMessageBox::question(this,tr("退出程序"),QString(tr("确认退出程序")),QMessageBox::Yes|QMessageBox::No);
if(button==QMessageBox::No)
{
event->ignore(); // 忽略退出信号,程序继续进行
}
else if(button==QMessageBox::Yes)
{
event->accept(); // 接受退出信号,程序退出
}
// TODO: 在退出窗口之前,实现希望做的操作
}
Qt5实现鼠标点击窗口外部关闭该窗口
方式一:重写窗口。该方式最简单,但是有一个弊病,需要为每个要实现该功能的窗口都重写该函数。
bool Form::event(QEvent *event)
{
if (event->type() == QEvent::ActivationChange)
{
if(QApplication::activeWindow() != this)
{
this->close();
}
}
return QWidget::event(event);
}
方式二:使用事件过滤器
步骤一:为每个要实现该功能的窗口安装事件过滤器,一般在构造函数里安装:
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//f和f1都是窗口类实例
f=new Form;
f1=new Form1;
f->installEventFilter(this);
f1->installEventFilter(this);
}
步骤二:重写事件过滤函数:
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
if (event->type() == QEvent::ActivationChange)
{
if(watched == f || watched == f1)//需要实现该功能的控件
{
if(QApplication::activeWindow() != watched)
{
QWidget *w=static_cast<QWidget *>(watched);
w->close();
}
}
}
return QWidget::eventFilter(watched, event);
}
Enter退出问题
我新建了一个 QDialog 窗口,里面有多个 QLabel 和 QLineEdit 和一个 Exit 退出按钮,但是编辑完 QLineEdit 按回车后窗口就马上退出了,后来发现是按钮默认设置成了 StrongFocus 的原因。
解决方法:
设置窗口中的退出按钮的focusPolicy
属性为NoFocus
。
Esc退出问题
需要重写 QDialog 的keyPressEvent()
:
#include <QKeyEvent>
void MyDialog::keyPressEvent(QKeyEvent *event)
{
switch (event->key())
{
case Qt::Key_Escape: // 按下的为Esc键
break; // 不做反应直接退出
default:
QDialog::keyPressEvent(event);
}
}
QWidget设置控件的层次关系
设置控件置于父窗口的顶部:widget->raise();
设置控件层次:widget->stackUnder(other_widget);
设置控件置于父窗口的底部:widget->lower();
Qt去掉按钮等控件的虚线框
方法1:可以通过代码ui->pushButton->setFocusPolicy(Qt::NoFocus)
或在 Qt Creator 的属性列表中设置。
方法2:如果在嵌入式设备中需要通过按键切换控件,最简单的方法就是通过控件的 focus 来实现,就不能使用方法1了。此时可以通过 qss 样式表来去掉虚线框,代码如下所示:
ui->pushButton->setStyleSheet("outline: none");
方法3:也是通过qss样式表来实现,代码如下所示:
ui->pushButton->setStyleSheet("padding: -1");
参考: