Qt菜单栏与工具栏实战
文章目录
- 1. Menu
- 2. QActionGroup
- 3. ToolBar工具栏
- 4. Dock部件
- 5. 状态栏
- 5.1 临时信息
- 5.2 一般信息
- 5.3 永久信息
- 6. 菜单栏中添加任意部件
- 7. 禁用窗口关闭按钮 X
- 8. 拖拽事件
- 9. Q\_INIT\_RESOURCE 资源机制
- 10 .QT中tr()与&,字符串的使用
- 11. 中文乱码
- 12. 托盘与气泡框
- 12.1 添加头文件
- 12.2 创建QAction 及 托盘对象
- 13. 窗口居中显示与多个显示器居中显示
- 14. 设置打包图标及打包
- 15. 自定义鼠标样式
- 16. 开机启动->修改注册列表
- 17. 先固定窗口大小不变,再改变窗口大小
- 18. windows 系统设置全局键盘钩子
- 19. 获取windows 后台进程
- 20. 设置combobox下拉列表的宽度
- 20. lable 设置QMovie 自适应大小与删除movie
- 21. 设置背景透明
- 22. 标准路径
- 23. 移动窗口
- 24 图片旋转
- 25. 图像镜像
- 26. mouse 追踪没反应
- 27. 数据库建立与查询
- 28.lineEidit 设置正则表达式
- 29. 抗锯齿
- 30. Qt 无法在部件上绘图
- 31. 调用QPrinter输出pdf
- 32. 复制图片到粘贴板
- 33. 从粘贴板上读取数据
- 34.窗口部件阴影
- 35. QLineEdit 添加图标
- 36. 正则表达式
- 37. 采用默认程序打开文件
- 38. 中文编码
- 39. 高分屏
- 40. 定时显示
- 41.设置无边框
1. Menu
#include <QMenu>
#include <QAction>
说明 :添加一个菜单“编辑”,并在编辑菜单下添加一个QAction act_open。
QMenu *Eidt_menu=ui->menubar->addMenu(tr("编辑(&E)"));//菜单栏添加一个名为“编辑”的菜单//QAction *act_open=ui->menubar->addAction(tr("打开文件"));//将actopen 添加到菜单栏 方式A(不推荐)QAction *act_open=Eidt_menu->addAction(QIcon(":/images/images/open1.bmp"),tr("打开文件(&O)"));act_open->setShortcut(QKeySequence("Ctrl+O"));//给act_open添加快捷键Eidt_menu->addAction(act_open);//将act_open添加到"编辑"菜单的子菜单中,采用,A会有此时有两个一样的act_open。//信号与槽connect(act_open,SIGNAL(triggered()),this,SLOT(on_open_triggered()));
注:QAction的checkable属性,如果指定这个动作checkable为true,那么选中这个菜单时就会在它的前面显示“对勾”之类表示选中的状态的符号;如果该菜单有图标,就会用线框将图标围住,用来表示该动作被选中了。
2. QActionGroup
#include<QActionGroup>
QActionGroup动作组,他可以包含一组动作QAction,可以设置这组动作中是否只能有一动作处于选中状态,这对于互斥动作很有用;
QActionGroup *actionGroup=new QActionGroup(this); //创建actiongroup动作组。QAction *act_L=actionGroup->addAction(tr("左对齐(&L)"));act_L->setCheckable(true); //设置checkable属性为trueQAction *act_R=actionGroup->addAction(tr("右对齐(&R)"));act_R->setCheckable(true);QAction *act_C=actionGroup->addAction(tr("居中对齐(&C)"));act_C->setCheckable(true);act_L->setChecked(true);//设置act_L为选中状态Eidt_menu->addSeparator();//添加分隔线Eidt_menu->addAction(act_L);Eidt_menu->addAction(act_R);Eidt_menu->addAction(act_C);
3. ToolBar工具栏
#include<QToolBar>
工具栏QToolBar
类提供一个包含了一组控件的、可以移动的面板。QAction
对象添加到工具栏中,默认只是显示一个动作的图标。
QToolButton *toolBtn=new QToolButton(this);toolBtn->setText(tr("颜色"));QMenu *colorMenu=new QMenu(this);// colorMenu->addAction(tr("红色")); addAction函数具有QAction的返回值,否则只在colorMenu中添加选项红色,而无法添加槽函数// colorMenu->addAction(tr("绿色"));QAction *act_red=colorMenu->addAction(tr("红色"));QAction *act_green=colorMenu->addAction(tr("绿色"));connect(act_red,SIGNAL(triggered()),this,SLOT(on_act_red_triggered()));connect(act_green,SIGNAL(triggered()),this,SLOT(on_act_green_triggered()));toolBtn->setMenu(colorMenu);/** ToolButton 弹出模式*enum ToolButtonPopupMode {DelayedPopup, 延迟弹出MenuButtonPopup, 点击下三角,弹出InstantPopup, 点击下三角,弹出};*/toolBtn->setPopupMode(QToolButton::MenuButtonPopup);//设置弹出模式ui->toolBar->addWidget(toolBtn);//向工具栏添加QToolButton按钮QSpinBox *spinbox=new QSpinBox(this);//创建QSpinBoxui->toolBar->addWidget(spinbox);
4. Dock部件
#include<QDockWidget>
Dock部件可以停靠在QMainWindow中,也可以悬浮起来作为桌面顶级窗口,称为Dock部件或者停靠窗口。DOck部件一般用来存放其他部件来实现特殊功能,就像一个工具箱。
5. 状态栏
#include<QStatusBar>
用来显示状态信息,状态信息可以分成三类:
- 临时信息:如提示信息;
- 一般信息:正常信息,如页数行号;
- 永久信息:如显示版本号或者日期;
5.1 临时信息
临时信息可以使用showMessage()函数显示一个临时信息,他会出现在状态栏的最左边。
5.2 一般信息
一般信息,一般用addWidget()函数加一个QLabel到状态栏上,用于显示正常信息,他会生成到状态栏的最左边,可能被临时信息掩盖。
5.3 永久信息
永久信息,需要使用addPermanentWidget()函数来添加一个如QLabel一样的可以显示信息的部件,他会在状态栏的最右边生成,不会被临时消息掩盖;
//显示临时信息,显示时间3000毫秒即3秒ui->statusbar->showMessage(tr("欢迎使用多文档编辑器"),3000);//创建标签,设置标签样式并显示信息,然后将其以永久部件的形式添加到状态栏QLabel *permermantMessage=new QLabel(this);permermantMessage->setFrameStyle(QFrame::Sunken);permermantMessage->setText("www.qter.org");ui->statusbar->addPermanentWidget(permermantMessage);
状态栏的最右边还有一个QSizeGrip()部件,用来调整窗口大小。可以使用setSizeGripEnabled()进行禁用;
注:QSizeGrip()部件可以比较方便的调整窗口大小,所以一般不选择禁用;
6. 菜单栏中添加任意部件
#include<QWidgetAction>
工具栏中可以添加任意部件,但是菜单栏里也是可以的,不过菜单栏需要继承QWidgetAction类并且需要重新实现creatWidget()函数。
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private:Ui::MainWindow *ui;
private slots:void setText(const QString &text);
};
#endif // MAINWINDOW_H#ifndef MYACTION_H
#define MYACTION_H
#include <QWidgetAction>
#include <QLineEdit>
class MyAction:public QWidgetAction
{Q_OBJECT
public:explicit MyAction(QObject *parent=0);
protected:// 声明函数,该函数是QWidgetAction类中的虚函数QWidget * createWidget(QWidget *parent) override;
signals:// 新建信号,用于在按下回车键时,将行编辑器中的内容发射出去void getText(const QString &string);
private slots:// 新建槽,它用来与行编辑器的按下回车键信号关联void sendText();
private:QLineEdit *lineEidt;};#endif // MYACTION_H#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "myaction.h"
#include <QMenu>
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);MyAction *action=new MyAction(this);QMenu *eiditMenu=ui->menubar->addMenu(tr("编辑(&E)"));eiditMenu->addAction(action);connect(action,SIGNAL(getText(QString)),this,SLOT(setText(QString)));
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::setText(const QString &text)
{ui->textEdit->setText(text);
}#include "myaction.h"
#include <QLineEdit>
#include <QLabel>
#include <QSplitter>MyAction::MyAction(QObject *parent):QWidgetAction(parent)
{//创建行编辑器lineEidt =new QLineEdit;/*将QLineEidt写在此类的构造函数中,每生成一个MyAction对象都会生成一个QLineEidt对象。这是由于定义一个类对象后,都要执行一次构造函数。*///将行编辑器的按下回车信号与发送文本槽关联connect(lineEidt,&QLineEdit::returnPressed,this,&MyAction::sendText);//connect(lineEidt,SIGNAL(returnPressed()),this,SLOT(sendText()));}QWidget *MyAction::createWidget(QWidget *parent)
{//这里使用inherits()函数判断父部件是否是菜单或者工具栏//如果是,则创建该父部件的子部件,并且返回子部件//如果不是,则直接返回0if(parent->inherits("QMenu")||parent->inherits("QToolBar")){QSplitter *splitter=new QSplitter(parent);//在父部件上建立分裂器QLabel *label=new QLabel;label->setText(tr("插入文本"));splitter->addWidget(label);splitter->addWidget(lineEidt);return splitter;}
}void MyAction::sendText()
{//发送信号,将行编辑器中的内容发射出去emit getText(lineEidt->text());lineEidt->clear();
}
7. 禁用窗口关闭按钮 X
禁用窗口关闭按钮 X 只需要重写closeEvent(QCloseEvent *event)
事件,并忽略该事件;
void Widget::closeEvent(QCloseEvent *event)
{event->ignore();//忽略退出事件,转而执行最小化;this->setWindowState(Qt::WindowState::WindowMinimized);
}
8. 拖拽事件
\#include <QDragEnterEvent>\
\#include <QDropEvent> \
//【1】以主窗口控件为例,设置其AcceptDrops属性=truethis->setAcceptDrops(true);
//通过拖拽事件获取文件信息
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);
void Widget::dragEnterEvent(QDragEnterEvent *event)
{if(true){//必须设置否则不执行dropEventevent->acceptProposedAction();}
}void Widget::dropEvent(QDropEvent *event)
{QList<QUrl> urls=event->mimeData()->urls();if(urls.isEmpty())return;QString filename=urls.first().toLocalFile();addWidget(filename);
}
9. Q_INIT_RESOURCE 资源机制
Q_INIT_RESOURCE
是Qt的资源机制。
使用方法:
Q_INIT_RESOURCE(name)
首先,我们自己需要建立一个XXX.qrc
文件,“XXX”
代表该资源的名字。上述代码中的name
,就是代表需要初始化该资源。
接下来,程序编译时,编译器根据传入的name
,将XXX.qrc
中指定的资源,以二进制数的形式存储到Qt自动建立的名为qrc_XXX.cpp
的文件中,这里的XXX
就是你建立.qrc
文件的名字,也是调用Q_INIT_RESOURCE
传入的name
。
这句代码,写在类的构造函数中,可确保在静态链接的情况下将资源链接到最终的应用程序二进制文件中;写在main函数中,则全局可以使用。
同理,在将资源卸载的时候,需要调用Q_CLEANUP_RESOURCE()
。
10 .QT中tr()与&,字符串的使用
首先来说说tr的用处,因为qt是一个跨平台开发的工具,因此需要考虑在不同环境下的运行。然而在不同环境下的运行,字符集也会不同,因此qt给出的解决方案是使用tr将字符串包起来,然后就可以由qt去考虑字符集不同的问题.
接下来是为什么有些字符串前会有&符号。 比如说像下面这样的:
newAct = new QAction(QIcon(":/images/new.png"), tr("&New"), this)
openAct = new QAction(QIcon(":/images/open.png"), tr("&Open..."), this);
enter code exitAct = new QAction(tr("E&xit"), this);
但它对QAction有特殊含义:它将下列字符设置为菜单中条目的快捷方式,且快捷键为&
后面紧跟的字母,因此当您打开“文件”菜单时,按下n
键将激活“新建”
条目, x
将激活“退出”
等。根据操作系统的不同,&之后的字符也可以加下划线(在Windows
上,按Alt
键时仅加下划线)
11. 中文乱码
添加下面语句到main.cpp
#pragma execution_character_set("utf-8")
12. 托盘与气泡框
参考 Qt: System Tray Icon Example
12.1 添加头文件
#include <QSystemTrayIcon> //托盘
#include <QDialog>
#include <QAction>
#include <QMenu>
12.2 创建QAction 及 托盘对象
QAction *minimizeAction; //最小化
QAction *maximizeAction; //最大化
QAction *restoreAction; //恢复
QAction *quitAction; //退出
QSystemTrayIcon *trayIcon; //托盘
QMenu *trayIconMenu; //托盘菜单//创建QAction
minimizeAction = new QAction(QIcon(":/img/img/windows_min.png"),tr("最小化"), this);
connect(minimizeAction, &QAction::triggered, this, &QWidget::hide);maximizeAction = new QAction(QIcon(":/img/img/windows_max.png"),tr("最大化"), this);
connect(maximizeAction, &QAction::triggered, this, &QWidget::showMaximized);restoreAction = new QAction(QIcon(":/img/img/windows_restore.png"),tr("显示窗口"), this);
connect(restoreAction, &QAction::triggered, this, &QWidget::showNormal);quitAction = new QAction(QIcon(":/img/img/windows_quit.png"),tr("退出"), this);
connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit);//创建托盘及其菜单
trayIconMenu = new QMenu(this);
trayIconMenu->addAction(minimizeAction);
trayIconMenu->addAction(maximizeAction);
trayIconMenu->addAction(restoreAction);
trayIconMenu->addSeparator();
trayIconMenu->addAction(quitAction);trayIcon = new QSystemTrayIcon(this);
trayIcon->setContextMenu(trayIconMenu);
trayIcon->setIcon(QIcon(":/img/img/link.png"));// 创建气泡消息
// 创建出的气泡消息可能不会显示,具体解决方式看后面
void Widget::displayMessage()
{if(trayIcon->supportsMessages()){QSystemTrayIcon::MessageIcon msgIcon = QSystemTrayIcon::MessageIcon(QSystemTrayIcon::MessageIcon::Information);const QString titleInfo="提示信息";const QString bodyStr="程序未退出,将在托盘显示,如有需要,可以进一步操作!";int duration=15;//trayIcon->setVisible(true);trayIcon->showMessage(tr("提示信息"),bodyStr,msgIcon,duration*1000);qApp->processEvents();}else{qDebug()<<"不支持气泡消息"<<endl;}}// 构造函数中添加信号与槽//! 要添加此句,否则气泡对话框不显示
trayIcon->show();//点击气泡消息信号
connect(trayIcon, &QSystemTrayIcon::messageClicked, this, &Widget::messageClicked);//点击托盘图标信号:
connect(trayIcon, &QSystemTrayIcon::activated, this, &Widget::iconActivated);//响应托盘图标信号:
void Widget::iconActivated(QSystemTrayIcon::ActivationReason reason)
{switch (reason) {case QSystemTrayIcon::Trigger: //单击显示this->showNormal();break;case QSystemTrayIcon::DoubleClick: //双击退出this->close();break;case QSystemTrayIcon::MiddleClick:displayMessage();break;default:;}
}//响应气泡信号
void Widget::messageClicked()
{//do something
}// 重写closeEvent事件
void Widget::closeEvent(QCloseEvent *event)
{if(trayIcon->isVisible()){event->ignore();hide();displayMessage();}
}
13. 窗口居中显示与多个显示器居中显示
#include "widget.h"#include <QApplication>
#include <QDesktopWidget>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;QDesktopWidget *desktop=QApplication::desktop();w.move((desktop->width()-w.width())/2,(desktop->height()-w.height())/2);w.show();return a.exec();
}
原理很简单,是用像素大小来计算,在单屏幕上也并没有什么问题,但是在多屏下就有问题了,因为多屏下的像素是所有屏幕加起来,所以用上面的方法,程序界面位置是不可预料的
#include "widget.h"#include <QApplication>
#include <QDesktopWidget>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;int current_screen=a.desktop()->screenNumber(&w);//程序所在的屏幕编号QRect rect = a.desktop()->screenGeometry(current_screen);//程序所在屏幕尺寸w.move((rect.width()-w.width())/2,(rect.height()-w.height())/2); //移动居中显示w.show();return a.exec();
}
14. 设置打包图标及打包
将App.ico放在程序主目录后,.pro
添加
RC_ICONS=App.ico
#cmake
https://blog.csdn.net/changyana/article/details/138606122
打包:
windeployqt xxx.exe
15. 自定义鼠标样式
//此处通过重写 void enterEvent(QEvent *event)事件;void Widget::enterEvent(QEvent *event)
{//默认鼠标热点在自定义鼠标的中心;QCursor cursor(QPixmap(":/img/img/Mouse_cursor.png"),0,0);//修改鼠标热点为左上角,即鼠标尖//cursor.setShape(Qt::CursorShape::CustomCursor);this->setCursor(cursor);
}
16. 开机启动->修改注册列表
- 首先按键盘上的
ctrl+r
组合键,在弹出的运行界面输入regedit
命令回车 - 然后找到这个路径`HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
紧接着我们点击
run`项,并在右侧右键点击空白处,新建-字符串值- 再右键点击新建的字符串值,进行重命名,自己起个知道的名字,比如ps软件,只能英文名
- 我们找到桌面ps软件,并右键点击选择属性
- 在弹出的属性界面,找到目标位置,并将其路径进行复制
- 最后我们在注册表项里面,双击ps字符串,在数值数据里进行粘贴保存即可添加成功。
17. 先固定窗口大小不变,再改变窗口大小
- 在
resizeEvent
函数中设置setMaximumSize
或setFiximumSize
;(为什么要在这里设置,如果在构造函数中设置这个属性,最大化窗口无法使用,即使最后改变最大窗口大小setMaximumSize
。) - 恢复固定大小窗口为可调节大小的窗口,在某个函数中调用;
this->setMaximumSize(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX);
18. windows 系统设置全局键盘钩子
#include <Windows.h>HINSTANCE hInst = GetModuleHandle(NULL);HHOOK g_Hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, hInst, 0);//设置全局钩子//回调函数LRESULT KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{KBDLLHOOKSTRUCT* ks = (KBDLLHOOKSTRUCT*)lParam; // 包含低级键盘输入事件信息if (wParam == WM_KEYDOWN){if (ks->vkCode == 'F')//注意按键有KEY_DOWN和KEY_UP2个if ((GetKeyState(VK_CONTROL) && 0x80000)&&(GetKeyState(VK_SHIFT) && 0x80000)) //& 0x80000 判断是否是按下状态{//do something;}}// 将消息传递给钩子链中的下一个钩子return CallNextHookEx(NULL, nCode, wParam, lParam);
}
19. 获取windows 后台进程
#include <QProcess>
//processName 进程名称 包含后缀.exe
bool IsProcessExist(QString processName)
{QProcess process;process.start("tasklist");//打开tasklist,显示本地计算机或远程计算机上当前正在运行的进程列表;process.waitForFinished();QString str = process.readAllStandardOutput();//从tasklist获取所有进程列表;if(str.contains(processName)) //判断进程列表中是否包含processName,因此为了准确,processName需要写全称return true;elsereturn false;
}
20. 设置combobox下拉列表的宽度
QAbstractItemView *view=ui->filter->view();view->setFixedWidth(210);
20. lable 设置QMovie 自适应大小与删除movie
movie=new QMovie(":/img/background.gif");movie->start();ui->label->setScaledContents(true);ui->label->setMovie(movie);//删除movie->deleteLater();
21. 设置背景透明
this->setAttribute(Qt::WA_TranslucentBackground);
22. 标准路径
QString Picture_path = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
23. 移动窗口
bool mousePressed=false;QPoint mousePoint;void mousePressEvent(QMouseEvent *event);void mouseReleaseEvent(QMouseEvent *event);void mouseMoveEvent(QMouseEvent *event);void MainWindow::mousePressEvent(QMouseEvent *event)
{if (event->button() == Qt::LeftButton){mousePressed = true;mousePoint = event->globalPos() - this->pos();}
}void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{if (event->button() == Qt::LeftButton){mousePressed = false;}
}void MainWindow::mouseMoveEvent(QMouseEvent *event)
{if (mousePressed && (event->buttons() && Qt::LeftButton)) {this->move(event->globalPos() - mousePoint);}
}
24 图片旋转
QMatrix matrix;
matrix.rotate(45);QLabel *Label= new QLabel();
Label->setPixmap(QPixmap(“:/images.png”).transformed(matrix, Qt::SmoothTransformation));void Widget::paintEvent(QPaintEvent *)
{QPainter painter(this);QPixmap disc(":/disc.png");/* 碟机转动 */if(imageRotate++ == 360)imageRotate = 0;/* 设定旋转中心点 */painter.translate(130,150);/* 旋转的角度 */painter.rotate(imageRotate);/* 恢复中心点 */painter.translate(-130,-150);/* 画图操作 */painter.drawPixmap(40,60,180,180, disc);
}
25. 图像镜像
QImage image(":/Images/logo");
QImage mirroredImage = image.mirrored(false, false); // false 水平 flase 竖直
QPixmap pixmap = QPixmap::fromImage(mirroredImage);
26. mouse 追踪没反应
//设置目标区域所有可设置打开鼠标追踪开关,从顶至下设置this->setMouseTracking(true);
27. 数据库建立与查询
//建立与插入:
bool CustomInfomationWidget::creatConnectionSql()
{db=QSqlDatabase::addDatabase("QSQLITE","connection");db.setDatabaseName("timelogger.db");if(!db.open()){QMessageBox::warning(this,"warning","cannot connect to database");return false;}else{QSqlQuery querry(db); //首先先连接到dbquerry.exec("create table timelogger(id int primary key,year int(10),month int(10),day int(10),hour int(10),minute int(10),second int (10))");}
}
//查询:
QSqlQuery querry(db); //首先先连接到db//在数据库中查询表 timelogger:querry.exec("select * from timelogger");while (querry.next()) {int data1=querry.value(1).toInt();int data2=querry.value(2).toQString();...}
//删除:
QSqlQuery querry(db); //首先先连接到db
querry.exec(QString("DELETE FROM timelogger WHERE id = %1").arg(0));
28.lineEidit 设置正则表达式
正则表达式模板
//设置正则表达式,只能输入数字QRegExp regExp("^[0-9]*$");ui->lineEdit_Value->setValidator(new QRegExpValidator(regExp, this));
29. 抗锯齿
//1
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);//2
//QPainter::Antialiasing 告诉绘图引擎应该在可能的情况下进行边的反锯齿绘制
//QPainter::TextAntialiasing 尽可能的情况下文字的反锯齿绘制
//QPainter::SmoothPixmapTransform 使用平滑的pixmap变换算法(双线性插值算法),而不是近邻插值算法painter.setRenderHint(QPainter::Antialiasing, true);
30. Qt 无法在部件上绘图
Qt 无法在部件上绘图例如QLabel,只能setQPixmap(),灵活性较差,无法进行直接绘制;
QPainter对象的只能在继承自QPainterDevice的子类作为绘图设备,绘制出来的图形将在这个设备上进行显示,Qt一共提供了4个这样的类,分别是QPixmap,QBitmap,QImage,和QPicture
。
在控件上绘图又应该怎么办呢,我这以QLabel为例:使用事件过滤器来使QLabel对象捕获QEvent::Paint事件。即,绘图函数不需要放在paintevent()函数中也可以实现绘图。 实现这个功能的主要函数就还是事件过滤器的两个重要函数,即installEventFilter()和eventFileter() 。
//widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QPainter>namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = nullptr);~Widget();protected:bool eventFilter(QObject *obj, QEvent *event);void labelPaint();
private:Ui::Widget *ui;
};#endif // WIDGET_H//widget.cpp
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);ui->label->installEventFilter(this); //这行不能省
}Widget::~Widget()
{delete ui;
}bool Widget::eventFilter(QObject *watched, QEvent *event) //用过滤器eventFilter()拦截QLabel中的QEvent::Paint事件
{if(watched ==ui->label && event->type() == QEvent::Paint)paint();return QWidget::eventFilter(watched,event);
}void Widget::paint() //绘图
{QPainter painter(ui->label);painter.setPen(Qt::blue);// painter.drawLine(100,100,200,200);painter.drawEllipse(30,15,50,65);painter.drawLine(0,100,111,100);}
31. 调用QPrinter输出pdf
1. .pro添加打印机模块
qtHaveModule(printsupport): QT += printsupport2. 头文件添加
#ifndef QT_NO_PRINTER
#include <QPrinter>
#endif#if defined(QT_PRINTSUPPORT_LIB)
#include <QtPrintSupport/qtprintsupportglobal.h>
#if QT_CONFIG(printdialog)
#include <QPrintDialog>
#endif
#endif3.成员变量
#ifndef QT_NO_PRINTERQPrinter printer;
#endif4. 打印
void ImageViewer::print()
{Q_ASSERT(imageLabel->pixmap());
#if QT_CONFIG(printdialog)QPrintDialog dialog(&printer, this);if (dialog.exec()) {QPainter painter(&printer);QRect rect = painter.viewport();QSize size = imageLabel->pixmap()->size();size.scale(rect.size(), Qt::KeepAspectRatio);painter.setViewport(rect.x(), rect.y(), size.width(), size.height());painter.setWindow(imageLabel->pixmap()->rect());painter.drawPixmap(0, 0, *imageLabel->pixmap());}
#endif
}
其中:
QT_CONFIG 宏实现了对 Qt 特性的安全编译时检查。功能可以处于三种状态:
0 或未定义:这将在测试时导致编译错误
-1:该功能不可用
1:该功能可用
具体定义如下:
#define QT_CONFIG(feature) (1/QT_FEATURE_##feature == 1)例如:QT_CONFIG(printdialog)展开后为(1/QT_FEATURE_printdialog == 1) 即用来判断是否支持printdialog模块;
一般包含在每个模块的xxxx-config.h文件中;
32. 复制图片到粘贴板
#include <QClipboard>
#include <QMimeData>#ifndef QT_NO_CLIPBOARDQGuiApplication::clipboard()->setImage(image);
#endif // !QT_NO_CLIPBOARD
33. 从粘贴板上读取数据
#ifndef QT_NO_CLIPBOARDif(const QMimeData *mimeData=QGuiApplication::clipboard()->mimeData()){if(mimeData->hasImage())//Pixmap or QImage{const QPixmap pix=qvariant_cast<QPixmap>(mimeData->imageData());//qvariant_cast<QImage>if(!pix.isNull()){this->setImage(pix);}}}
#endif
34.窗口部件阴影
#include <QGraphicsDropShadowEffect>this->setAttribute(Qt::WA_TranslucentBackground);//设置背景透明QGraphicsDropShadowEffect *shadow=new QGraphicsDropShadowEffect;shadow->setOffset(-2,2);shadow->setColor(Qt::darkGray);shadow->setBlurRadius(8);this->setGraphicsEffect(shadow);
35. QLineEdit 添加图标
QAction *password=new QAction(this);password->setIcon(QIcon(":/style/password.png"));ui->lineEdit_Password->addAction(password,QLineEdit::LeadingPosition);
36. 正则表达式
// 正则表达式QRegExp exp("^[a-zA-Z0-9_-@.]{4,20}$");QRegExpValidator *validator = new QRegExpValidator(exp, this);ui->lineEdit_Username->setValidator(validator);
37. 采用默认程序打开文件
采用openUrl()
函数,可以根据Url的类型,选择一个合适的应用程序(一般是采用默认应用程序)打开该url指向的文件;
//QString fileName(qApp->applicationDirPath() + QStringLiteral("要打开的文件"));
QString fileName(“要打开的文件路径”);if (!QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(fileName).absoluteFilePath()))){QMessageBox::information(this, tr("warning"),tr("Failed to open the help guide."),QMessageBox::Ok);}
38. 中文编码
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VERQTextCodec *codec = QTextCodec::codecForName("gbk");
#elseQTextCodec *codec = QTextCodec::codecForName("utf-8");
#endifQTextCodec::setCodecForLocale(codec);QTextCodec::setCodecForCStrings(codec);QTextCodec::setCodecForTr(codec);
#elseQTextCodec *codec = QTextCodec::codecForName("utf-8");QTextCodec::setCodecForLocale(codec);
#endif
39. 高分屏
高分屏*就是在同样大小的屏幕面积上显示更多的像素点,也就是更多的可视信息。
- 从Qt5.6开始提供了高分屏缩放支持,需要在main函数前面设置
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
- 从Qt5.14开始提供了高分屏缩放策略设置,需要在main函数前面设置
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
- 从Qt6.0开始默认就开启高分屏属性
Qt::AA_EnableHighDpiScaling
,而且不允许关闭(所以你会发现程序用Qt6编译后界面变得很大)。可以通过setHighDpiScaleFactorRoundingPolicy
函数设置策略。 - 如果不想要高分屏,希望程序永远保持默认的尺寸,你需要在
main
函数前面设置QApplication::setAttribute(Qt::AA_Use96Dpi);
表示永远不缩放。 - 如果希望启用Qt的高分屏则需要设置
Qt::AA_EnableHighDpiScaling和setHighDpiScaleFactorRoundingPolicy
。缺点是图片容易发虚,比如复选框的边框,哪怕是Qt内置样式风格或者系统默认风格也一样。
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))QApplication::setAttribute(Qt::AA_Use96Dpi);
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
#endif
40. 定时显示
QMessageBox *messageBox = new QMessageBox(QMessageBox::Information, "Success", "File saved successfully.\nSaved at: " + filePath, QMessageBox::Ok, this);QTimer::singleShot(3000, messageBox, &QMessageBox::accept);
messageBox->show();
41.设置无边框
this->setWindowFlags(Qt::FramelessWindowHint);