原文链接:
https://blog.csdn.net/kissgoodbye2012/article/details/120404744?spm=1001.2101.3001.6650.13&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-13.pc_relevant_antiscanv2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-13.pc_relevant_antiscanv2&utm_relevant_index=22
要做一个类似下面的qt界面,顶部是导航栏的样子——包含图标和程序名称,右边是界面切换按钮,然后放大、缩小和关闭按钮也在,还能拖动。这样,就更像一个商用的软件了。
1.去掉菜单栏、工具栏;
2.顶部导航栏包含程序图标、名称、界面切换按钮、放大缩小关闭按钮;
3.顶部导航栏可以拖动;
4.导航栏按钮可以切换界面。
可以参考的相关博客链接
在UI设计界面,在menuBar和mainToolBar上右键,选择移除菜单栏和移除工具栏。
把顶部的图标和程序名称、放大缩小关闭按钮都去掉,使用如下语句。
this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint);
主要是用installEventFilter来实现的。参考第6章节。
这个顶部导航栏是通过注册监听事件,让app监控所有的程序事件。如果属性是可移动的,然后记录鼠标的坐标等,来控制窗口的位置和大小。
#ifndef APPINIT_H
#define APPINIT_H
#include
class AppInit : public QObject
{
Q_OBJECT
public:
static AppInit *Instance();
explicit AppInit(QObject *parent = 0);
void start();
protected:
bool eventFilter(QObject *obj, QEvent *evt);
private:
static AppInit *self;
signals:
public slots:
};
#endif // APPINIT_H
#include "appinit.h"
#include "qmutex.h"
#include "qapplication.h"
#include "qevent.h"
#include "qwidget.h"
AppInit *AppInit::self = 0;
AppInit *AppInit::Instance()
{
if (!self) {
QMutex mutex;
QMutexLocker locker(&mutex);
if (!self) {
self = new AppInit;
}
}
return self;
}
AppInit::AppInit(QObject *parent) : QObject(parent)
{
}
bool AppInit::eventFilter(QObject *obj, QEvent *evt)
{
QWidget *w = (QWidget *)obj;
//如果窗口w的属性“canMove"是假的,继续监听
if (!w->property("canMove").toBool()) {
return QObject::eventFilter(obj, evt);
}
//如果属性是可移动
static QPoint mousePoint;
static bool mousePressed = false;
//获取鼠标事件
QMouseEvent *event = static_cast<QMouseEvent *>(evt);
if (event->type() == QEvent::MouseButtonPress) {
//如果鼠标被按下,且是左键按下
if (event->button() == Qt::LeftButton) {
mousePressed = true;
//记下当前坐标:全局坐标-窗口坐标
mousePoint = event->globalPos() - w->pos();
return true;
}
//如果鼠标松开
} else if (event->type() == QEvent::MouseButtonRelease) {
mousePressed = false;
return true;
//如果鼠标在移动
} else if (event->type() == QEvent::MouseMove) {
if (mousePressed && (event->buttons() && Qt::LeftButton)) {
//移动当前窗口到某个位置
w->move(event->globalPos() - mousePoint);
return true;
}
}
return QObject::eventFilter(obj, evt);
}
void AppInit::start()
{
qApp->installEventFilter(this);
}
//函数功能:让自定义的顶部导航栏可以拖动
AppInit::Instance()->start();
当我们有一排按钮需要程序来添加点击事件时,如果一个个connect那么代码就太长了,connect需要写,它们的槽函数又要单独写,而这些按钮响应的事件处理又差不多。那么可以用如下的写法,立马让你成为QT中级程序员的感觉。
使用findChildren函数找到某个widget下所有的按钮,如下面代码所示。
//设置顶部导航按钮
QList<QToolButton *> tbtns = ui->widgetTop->findChildren<QToolButton *>();
foreach (QToolButton *btn, tbtns) {
btn->setIconSize(icoSize);
btn->setMinimumWidth(icoWidth);
btn->setCheckable(true);
connect(btn, SIGNAL(clicked()), this, SLOT(buttonClick()));
}
首先,findChildren函数找到了widgetTop下的所有QToolButton类型按钮。
然后,给每一个按钮设置图标尺寸,宽度和可选择属性,然后连接connect到buttonClick()槽函数。
槽函数代码如下:
void UIDemo01::buttonClick()
{
QToolButton *b = (QToolButton *)sender();
//获取当前点击事件按钮的名称
QString name = b->text();
QList<QToolButton *> tbtns = ui->widgetTop->findChildren<QToolButton *>();
foreach (QToolButton *btn, tbtns) {
if (btn == b) {
//如果是当前点击事件的按钮,将其设为选中状态
btn->setChecked(true);
} else {
//如果不是当前点击事件的按钮,将其设为未选中状态
btn->setChecked(false);
}
}
if (name == "主界面") {
ui->stackedWidget->setCurrentIndex(0);
} else if (name == "系统设置") {
ui->stackedWidget->setCurrentIndex(1);
} else if (name == "警情查询") {
ui->stackedWidget->setCurrentIndex(2);
} else if (name == "调试帮助") {
ui->stackedWidget->setCurrentIndex(3);
} else if (name == "用户退出") {
//退出程序
exit(0);
}
}
这个槽函数,首先使用sender()函数获得了发生点击事件的那个QToolButton类型按钮的句柄。
然后,将其设为选中状态,将其他的按钮设为未选中状态;
最后,根据按钮的名称来选择跳转到的主界面。
首先,在.h文件中注册这些函数
private slots:
void on_btnMenu_Min_clicked();
void on_btnMenu_Max_clicked();
void on_btnMenu_Close_clicked();
然后,直接重写这些函数即可。
void UIDemo01::on_btnMenu_Min_clicked()
{
//qt自带函数
showMinimized();
}
void UIDemo01::on_btnMenu_Max_clicked()
{
//静态定义变量,只在第一次使用
static bool max = false;
//静态定义变量获得尺寸
static QRect location = this->geometry();
//记忆放大前的窗口尺寸,方便取消最大化时返回原位置和大小
if (max) {
this->setGeometry(location);
} else {
//保存当前的窗口尺寸
location = this->geometry();
//设置界面可达的最大尺寸
this->setGeometry(qApp->desktop()->availableGeometry());
}
//最大化就不能移动了
this->setProperty("canMove", max);
max = !max;
}
void UIDemo01::on_btnMenu_Close_clicked()
{
//qt自带函数
close();
}
有时我们需要捕获某个控件上的鼠标事件,比如这个界面在导航栏双击可以最大化和取消最大化。
首先,在.h文件中注册bool eventFilter(QObject *watched, QEvent *event);函数
protected:
bool eventFilter(QObject *watched, QEvent *event);
然后,给需要捕获鼠标事件的控件添加鼠标事件注册
ui->widgetTitle->installEventFilter(this);//顶部导航栏注册鼠标事件
最后,在鼠标事件中编写处理程序
bool UIDemo01::eventFilter(QObject *watched, QEvent *event)
{
//如果是鼠标双击事件
if (event->type() == QEvent::MouseButtonDblClick) {
//如果发生的控件是 ui->widgetTitle
if (watched == ui->widgetTitle) {
//调用发生最大化的函数
on_btnMenu_Max_clicked();
return true;
}
}
//我们处理了点击事件,把事件返回到上层,让它们继续处理其他事件
return QWidget::eventFilter(watched, event);
}
六、installEventFilter的使用
installEventFilter的使用参考
简述:
事件过滤器,可以实现一个QObject监视另一个QObject的所有事件,但是两个QObject必须在同一个线程内
使用:
被监视者(ui->widge)安装事件过滤器
ui->widget->installEventFilter(this);
在监视者(this)里重新实现eventFilter()函数,此函数返回false时,表示监视者(this)不过滤此事件,事件将会继续发送到被监视者(ui->widge);返回true时表示监视者过滤此事件,事件将不会发送到被监视者。
bool CustomerSwitchet::eventFilter(QObject *obj,QEvent *e)
{
QWidget*wid = qobject_cast<QWidget*>(obj);
if(wid==ui->widget)
{
//根据事件类型,写处理逻辑
qDebug()<<"widget";
}
return false;
}
https://blog.csdn.net/kissgoodbye2012/article/details/121725580
当前,我需要解决如下的一个问题:
有一个曲线图,包含有1条显性主曲线和31条隐性类正态分布曲线(所谓的显性和隐性,指的是曲线是一直显示的,还是在拖动它的控制点时才显示)。显性主曲线是31条隐性类正态分布曲线之和。每条类正态分布曲线有3个控制点,控制点可以拖动,这3个控制点代表这条类正态分布曲线曲线的中心频率、Q值和增益。
如果离散的分别进行操作,虽然也能实现功能,但所有东西都是搅在一起的,且代码量肯定很大。这里使用一个类来理清关系。
https://blog.csdn.net/kissgoodbye2012/article/details/121938706
正则表达式是用于描述符合某些复杂规则的字符串的工具,也就是用来匹配字符串的。
原文链接:https://blog.csdn.net/qq_16488989/article/details/108884580
最近在使用Qt5,Qt Creator做一个管理系统类的项目,自然需要用到登录界面,故记录一下登录界面的制作。其中一些功能的实现也得益于之前Qt5基础视频不规则窗口部分的学习。
没必要用qmainwindow,不需要那些菜单,一般用qwidget就可以,注意勾选ui。
1、添加容器
调整容器为合适大小,同时调整整个画布为合适大小。
2、添加按钮,标签,文字组件
构思:
账号密码部分使用Input Widgets:Line Edit
Logo和忘记密码使用两个Display Widgets:TextLabel
是否记住我选择一个Buttons:CheckBox
登录按钮使用Buttons:PushButton
3、修改组件名称
首先修改Line Edit默认文本属性,分别点击两个LineEdit修改文本属性为Username和Password。
然后其他的按钮文本标签直接双击修改名称即可。
以上两步之后,可以得到这个样子(这里统一在Wighets右边的菜单里修改过字体,一会可以通过样式表统一去改)。
4、添加样式表
类似于css,Qt具有Qss,最为关键的一步就是添加样式表。在Frame容器外 画布内 右键改变样式表,输入以下代码。
*{
background:rgb(255, 255, 255);
font-size:15px;
font-style:MingLiU-ExtB;
}
QFrame{
border:sold 10px rgba(0,0,0);
background-image:url(H:/GUI_design/day04/image/Login_Blue5);//背景
}
QLineEdit{
color:#8d98a1;
background-color:#405361;
font-size:16px;
border-style:outset;
border-radius:10px;
font-style:MingLiU-ExtB;
}
QPushButton{
background:#ced1d8;
border-style:outset;
border-radius:10px;
font-style:MingLiU-ExtB;
}
QPushButton:pressed{
background-color:rgb(224,0,0);
border-style:inset;
font-style:MingLiU-ExtB;
}
QCheckBox{
background:rgba(85,170,255,0);
color:white;
font-style:MingLiU-ExtB;
}
QLabel{
background:rgba(85,170,255,0);
color:white;
font-style:MingLiU-ExtB;
font-size:14px;
}
1、添加最小化和关闭窗口按钮
按钮选择Buttons:Tool Button,最小化采用-,关闭窗口采用x。
2、按钮转到槽
将两个按钮都转到槽。
3、代码示例
转到槽之后,只需要在相应的函数里添加close()和showMinimized()功能即可。具体的代码如下。
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_toolButton_clicked();
void on_toolButton_2_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
main.cpp
#include "widget.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
//核心代码就这几行
void Widget::on_toolButton_clicked()
{
close();
}
void Widget::on_toolButton_2_clicked()
{
showMinimized();
}
这个时候我们还需要把Widget自带的上边框去掉,并且去掉背景。
widget.cpp文件中添加如下两句代码即可。
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//去窗口边框
setWindowFlags(Qt::FramelessWindowHint | windowFlags());
//把窗口背景设置为透明;
setAttribute(Qt::WA_TranslucentBackground);
}
需要添加一个鼠标移动和鼠标按下事件。以*e来获取鼠标移动或按下。
main.cpp
#include "widget.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
protected:
void mouseMoveEvent(QMouseEvent *e);//鼠标移动
void mousePressEvent(QMouseEvent *e);//鼠标按下移动
private slots:
void on_close_clicked();
void on_minimized_clicked();
private:
Ui::Widget *ui;
QPoint p;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include
#include
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//去窗口边框
setWindowFlags(Qt::FramelessWindowHint | windowFlags());
//把窗口背景设置为透明;
setAttribute(Qt::WA_TranslucentBackground);
}
Widget::~Widget()
{
delete ui;
}
void Widget::mousePressEvent(QMouseEvent *e)
{
if(e->button() == Qt::LeftButton)
{
//求坐标差值
//当前点击坐标-窗口左上角坐标
p = e->globalPos() - this->frameGeometry().topLeft();
}
}
void Widget::mouseMoveEvent(QMouseEvent *e)
{
if(e->buttons() & Qt::LeftButton)
{
//移到左上角
move(e->globalPos() - p);
}
}
void Widget::on_close_clicked()
{
close();
}
void Widget::on_minimized_clicked()
{
showMinimized();
}
原文链接:https://blog.csdn.net/wangbaba_1/article/details/113648465
比如说在窗口上覆盖一个QLabel,这个label始终与窗口一样大。然后在label中设置图片,视觉效果上和直接给窗口设置背景图片一样。
Widget::Widget(QWidget *parent) :
QWidget(parent)
{
m_lblBg = new QLabel(this);
m_lblBg ->setPixmap(QPixmap(":/bg.jpg"));
m_lblBg ->setScaledContents(true);
}
void Widget::resizeEvent(QResizeEvent * ev)
{
m_lblBg->resize(this->size());
}
创建一个label作为Widget的子窗口,然后设置图片。通过在Widget的resizeEvent事件中设置label的大小与Widget一致。这里需要注意调用QLabel的setScaledContents(true),否则效果和第一种一样。由于QLabel可以用来显示动图因此使用这种方式可以实现窗口的动态背景图片。
由于QLabel可以用来显示动图因此使用这种方式可以实现窗口的动态背景图片。
原文链接:https://blog.csdn.net/wangxiaobei2017/article/details/77824938
工具按钮(QToolButton)区别于普通按钮(QPushButton)的一点是,工具按钮(QToolButton)可以带图标,他们两个有同一个父类(QAbstractButton);
工具按钮(QToolButton)有两部分组成:文本text 和 图标icon(建议用png格式的图片)