快速创建多个控件方法。
Button *plusButton = createButton(tr("+"), SLOT(additiveOperatorClicked()));
…
…
Button *Calculator::createButton(const QString &text, const char *member)
{
Button *button = new Button(text);
connect(button, SIGNAL(clicked()), this, member);
return button;
}
多个功能大致相同的方法。例如数字键
for (int i = 0; i < NumDigitButtons; ++i) {
digitButtons[i] = createButton(QString::number(i), SLOT(digitClicked()));
}
…
…
void Calculator::digitClicked()
{
Button *clickedButton = qobject_cast<Button *>(sender());
//do something
}
T qobject_cast ( QObject * object )
本方法返回object向下的转型T,如果转型不成功则返回0,如果传入的object本身就是0则返回0。
在使用时有两个限制:
1# T类型必须继承自QObject。
2#在声明时必须有Q_OBJECT宏。
多个界面用到同一功能的窗体,例如:键盘、导航栏
可以创建一个功能窗体,然后采用窗体控件提升的方法。
* 选择文件/文件夹的对话框:QFileDialog。选择目录的是:QFileDialog::getExistingDirectory(this);
* Combobox :下拉按钮大小,通过样式去设置。:drop-down
* 背景颜色应该是在窗体的一个widget中,不要直接在窗体中设置颜色。
* widget作为一个窗体的全部的时候,可以窗体的全部的边距设置为0;在窗体的Layout属性中。
十进制数格式化,保留两位数
QString MainWindow::toStr(int i)
{
QString ii = QString("%1").arg(i);
if(i <= 9)
return "0"+ii;
else
return ii;
}
* QString("%1:%2PM").arg(h-12,2,10,QChar('0')).arg(min,2,10,QChar('0'));
添加QT的依赖库,可以直接启动qt程序
首先找到这个工具,这个工具叫做“windeployqt”。它一般位于Qt安装目录下的mingw_XX\bin目录下,像我的目录就在C:\ProgramData\Qt\5.8\mingw53_32\bin。
此时,建议将整个目录直接加入系统环境变量,便于后续使用。
确认你的程序是用Qt Creator哪个模式设计的,总共有2个模式,Qt Widgets Application和Qt Quick Application,不同模式下的参数命令是不一样的:
在Qt Widgets Application模式下
输入”windeployqt hello.exe”命令,其中hello.exe是我的程序名称。【完整目录】
Qt Quick Application模式下
输入”windeployqt hello.exe–qmldir”命令,其中hello.exe是我的程序名称,qmldir是你的qml目录,这个目录一般位于mingwXX目录下,像我的目录就在C:\ProgramData\Qt\5.8\mingw53_32\qml。
Qt生成随机数的方法
1.生成随机数
生成随机数主要用到了函数qsrand和qrand,这两个函数在#include <QtGlobal>中,qsrand用来设置一个种子,该种子为qrand生成随机数的起始值。比如说qsrand(10),设置10为种子,那么qrand生成的随机数就在[10,32767]之间。而如果在qrand()前没有调用过qsrand(),那么qrand()就会自动调用qsrand(1),即系统默认将1作为随机数的起始值。使用相同的种子生成的随机数一样。下列代码生成了[0,9]之间的10个随机数。
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
for(int i=0; i<10; i++)
{
int test =qrand()%10;
qDebug()<<test;
}
template<typename _type>
QStringList MainWindow::getInt(_type f, _type t, int counts)
{
QStringList vec;
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
for(int i = 0; i< counts; ++i){
_type test = f+qrand()/(_type)(RAND_MAX/(t-f));
vec.push_back(QString("%1").arg(test));
}
return vec;
}
**2.**生成不重复的随机数
这个没有特别好的方法,需要自己手动计算
3.生成递增的随机数
就是在随机数生成后进行排序,Qt提供了一个非常好用的排序函数qSort,详细的用法可参考Qt帮助。
qSort(numbersList.begin(),numbersList.end());
QLabel自动换行的实现,也可手动实现
- 让QLabel自适应text的大小,直接用下面的代码:
LabelName->adjustSize();
- 让QLabel能够自动判断并换行显示:
LabelName->setGeometry(QRect(328, 240, 329, 27*4)); //四倍行距
LabelName->setWordWrap(true);
LabelName->setAlignment(Qt::AlignTop)
3.QLable等控件垂直显示数据的方法,在每个字符后加\n ,如:截\n距\n设\n置
Qt的QLabel支持HTML的标签语言。例如:
const QString& title = QString("<body><label style=\"color:%1;font:21px 思源黑体 Medium;\">%2</label>"
"<label style=\"color:%1;font:15px PingFang SC;\">%3</label>"
"<label style=\"color:%1;font:21px PingFang SC;\">%4</label></body>").arg("#FFFFFF").arg("AD").arg("前").arg("测试");
制作多语言包
连接:https://blog.youkuaiyun.com/du_bingbing/article/details/52458369;关键词:国际化,中英文,语言包
1.运行lupdate,从应用程序中提取所有经tr()标识过的字符串。生成一个后缀为*.ts的文件。
2.使用Qt Linguist翻译这个*.ts。然后用其生成*.qm。
3.在应用程序中用QTranslator这个类加载*.qm文件
要用lupdate生成后缀为*.ts的文件就要先在应用程序的工程文件*.pro中加入这一句:
TRANSLATIONS= orbitEditor_zh_CN.ts
翻译完后,点File–>Release就可以生成*.qm文件了。在main.cpp中用如下语句加载:
//切换成英文
uint language = pQ7Reader->GetConfigure()->LanguageConfig();
QTranslator translator;
if ( language == zybioLanguage::English )
{
if ( !translator.load( QCoreApplication::applicationDirPath() + "/translations/en_CN.qm" ) )
{
LOG4CXX_INFO( logger, "can't load en_CN.qm file" );
Msgbox box( MsgboxIcon::warning, QObject::tr( "警告" ), QObject::tr( "加载英文语言包失败" ) );
box.exec();
return -3;
}
qApp->installTranslator( &translator );
}
else if( language == zybioLanguage::Chinese )
{
if(!translator.load( QCoreApplication::applicationDirPath() + "/translations/qt_zh_CN.qm" ))
{
Msgbox box( MsgboxIcon::warning, QObject::tr( "警告" ), QObject::tr( "加载中文语言包失败" ) );
box.exec();
return -3;
}
qApp->installTranslator( &translator );
}
当然记得把*.qm加入资源文件*.qrc。根据路径的不同,自己修改上面load那句。
这样翻译完后,可能会出现两个问题:
1.Qt的内部类比如QMessageBox,QDialog等中的语句没有翻译成中文。对于这个问题,再加载一个翻译文件就行。Qt已经为我们准备好了,在"安装目录\translations中。我用的就是qt_zh_CN.ts这个文件,Qt已近为我们翻译好了。只要将它导出为*.qm文件就可以加载了。
软件不用重启可以实现多语言的方式:https://blog.youkuaiyun.com/lwwl12/article/details/80485123
* 把之前的QTranslator对象保存,可以使用指针的形式
* 在更改语言的时候,把语言给remove。qApp->removeTranslator(m_trans);
* 然后QTranslator对象再次调用load函数,加载新的语言包。
* 然后再qApp->installTranslator(m_trans);
* 然后刷新UI。
ui->retranslateUi(this);
//
备注
* 运行多语言要求要确保运行的系统上有字体文件,就是*.ttf文件,在window上默认就是有的,但是在一些嵌入式ARM版本上,是需要人为的部署进去的。
QT查找同类控件并进行批量处理
例如,一个页面上有很多qpushbotton,都要设置成阴影效果,如果一个一个去设置就会有很多代码,所以可以用如下一种方法去设置,让代码更简洁。如果针对某个对象,对象名objectName可以获取.关键QT方法:findChildren
QList<QPushButton *> Btns = ui->widget->findChildren<QPushButton *>();
foreach (QPushButton * btn, Btns) {
QGraphicsDropShadowEffect *shadow_effect = new QGraphicsDropShadowEffect(this);
shadow_effect->setOffset(0, 6);
shadow_effect->setColor(QColor(15,98,178));
shadow_effect->setBlurRadius(10);
btn->setGraphicsEffect(shadow_effect);
}
当程序存在很多自定义样式的控件时候,可以采用如下几种方法加快开发速度:
- 把样式表写在qss中
- 写设置该类控件的样式类(400的开发模式)
- 把同一类的控件抽离成一个自定义控件,自定义一个类继承该控件,然后实现对应的样式和函数。然后实现提升。
判断QString是否是纯数字:
/* ---示例代码----*/
bool isDigitString(const QString& src) {
QByteArray ba = item.toLatin1();//QString 转换为 char*
const char *s = ba.data();
while(*s && *s>='0' && *s<='9')s++; return !bool(*s);}
/* ---示例代码----*/
QPushButton实现长按的功能
/*
* +号按下
*/
void MainWindow::on_pushButton_4_pressed()
{
if(!timer1)
{
timer1 = new QTimer();
connect(timer1,&QTimer::timeout,this,&MainWindow::on_pushButton_4_clicked);
}
timer1->start(100);
}
/*
* 加号释放
*/
void MainWindow::on_pushButton_4_released()
{
timer1->stop();
}
QPushButton的四种状态样式设置:
QPushButton{
border-image: url(:/images/FuncWidget/serum.png);
}
QPushButton:focus{
border-image: url(:/images/FuncWidget/serumdissel.png);
}
QPushButton:disabled{
border-image: url(:/images/FuncWidget/serumdis.png);
}
QPushButton:checked{
border-image: url(:/images/FuncWidget/serumdown.png);
}
对数字的处理函数:QFloat16
可以四舍五入
可以判断是否为数字
打印和打印预览:QPrinter
setOrientation()告诉QPrinter要使用哪个页面方向。
setPaperSize()告诉QPrinter期望从打印机获得的纸张大小。
setResolution()告诉QPrinter您希望打印机提供什么样的分辨率,单位是点每英寸(DPI)。
setFullPage()告诉QPrinter是要处理整个页面,还是只处理打印机可以绘制的部分。
setCopyCount()告诉QPrinter应该打印多少个文档副本。
Qt编程实现守护程序
- 在Linux嵌入式的系统中,有个叫做看门狗的程序,当超过阈值时候,就会启动硬件程序复位,这样来帮助和保护程序是出于正常运行状态。在pc端可以编程有个守护程序来实现这个功能,保证程序是在正常运行状态。提供一个软件实现守护进程的办法,原理就是udp通信,单独写个守护进程程序,专门负责检测主程序是否存在,不存在则启动。主程序只需要启动live类监听端口,收到hello就回复ok就行。
为了使得兼容任意程序,特意提炼出来共性,增加了多种设置。
* 可设置检测的程序名称。
* 可设置udp通信端口。
* 可设置超时次数。
* 自动记录已重启次数。
* 自动记录最后一次重启时间。
* 是否需要重新刷新桌面。
* 可重置当前重启次数和最后重启时间。
* 自动隐藏的托盘运行或者后台运行。
* 提供界面设置程序名称已经开启和暂停服务。
* 代码网站:[http://www.qter.org/portal.php?mod=view&aid=776](http://www.qter.org/portal.php?mod=view&aid=776)
去除带有带有小数点的数值,小数点后为0的情况,double float 当小数点后未0则变成int型
* //double 转QString
QString max;
if(max.lastIndexOf(".0") == max.length() - 2)
{
max.replace(".0", "");
}
设置Tab键的焦点切换顺序设置
* setTabOrder();
QComboBox等控件,鼠标点击事件等显示不同的响应方法:
* 可以使用事件过滤器,
* 先注册事件installEventFilter()
* 再进行响应实现*eventFilter*(QObject*obj,QEvent*ev); //鼠标点击QEvent::MouseButtonPress
删除容器全部内容;
* qDeleteAll(const Container &c);不需要遍历删除
deleteLater
就是在删除一个对像时,依赖它的子对象,子对象的子对象都会关联地删除。
当我们使用父对象来创建一个对象的时候 ,父对象会把这个对象添加到自己的子对象列表中。当这个父对象被删除的时候,它会遍历它的子对象类表并且删除每一个子对象,然后子对象们自己再删除它们自己的子对象,这样递归调用直到所有对象都被删除。 这种父子对象机制会在很大程度上简化我们的内存管理工作,减少内存泄露的风险。
所以,使用deleteLater主要作用还是减少内存泄露的风险。
设置只能运行一个Qt实例。网址:链接
#include <QSharedMemory>
QSharedMemory shared("name");//最好使用UUID。
if (shared.attach())
{
return 0;
}
shared.create(1);
///
//单例运行
const QString sharedKey = "70d67e23-8ef2-44a4-b8f6-027c379fdf44";
int try_n = 3;
while (--try_n > 0)
{
if(QSharedMemory(sharedKey).attach())
QThread::sleep(1);
else
break;
}
if (try_n == 0)
{
// 前面进程未退出
CMessageBox_Dlg msg(nullptr);
msg.information(QObject::tr("提示"), QObject::tr("只能运行单个软件"), false); // 这里牺牲多语言
return 0;
}
QSharedMemory shared(sharedKey);
if(!shared.create(1))
return 1
实现程序崩溃生成转储文件
//.pro 文件
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
QMAKE_LFLAGS_RELEASE = $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO
LIBS += -ldbghelp
//Windows程序崩溃自动转储
#include <WinSock2.h>必须放在Windows.h之前
#include <Windows.h>
#include <DbgHelp.h>
#ifdef WIN32
LONG __stdcall ExceptCallBack( EXCEPTION_POINTERS *pExcPointer)
{
HANDLE hFile = CreateFile(L"CrashDump.dmp", GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL , nullptr);
MINIDUMP_EXCEPTION_INFORMATION loExceptionInfo;
loExceptionInfo.ExceptionPointers = pExcPointer;
loExceptionInfo.ThreadId = GetCurrentThreadId();
loExceptionInfo.ClientPointers = TRUE;
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),hFile, MiniDumpWithFullMemory, &loExceptionInfo, nullptr, nullptr);
CloseHandle(hFile);
return EXCEPTION_EXECUTE_HANDLER;
}
[[noreturn]] void PureCallHandler(void)
{
SetUnhandledExceptionFilter(ExceptCallBack);
throw std::invalid_argument(""); //此处抛出异常,查看调用堆栈排查真正崩溃代码
}
[[noreturn]] void InvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved)
{
Q_UNUSED(expression) Q_UNUSED(function) Q_UNUSED(file) Q_UNUSED(line) Q_UNUSED(pReserved)
SetUnhandledExceptionFilter(ExceptCallBack);
throw std::invalid_argument(""); //此处抛出异常,查看调用堆栈排查真正崩溃代码
}
#endif
///使用
//Windows程序崩溃自动转储
#ifdef WIN32
SetUnhandledExceptionFilter(ExceptCallBack);
_set_invalid_parameter_handler(InvalidParameterHandler);
_set_purecall_handler(PureCallHandler);
#endif
窗体的状态、事件可以通过QEvent去获取。QEvent::WindowDeactivate窗体是否失效
能够自由的拖动的缩放:分裂器。
使用:选择两个控件,然后右键选择布局。
分裂器的例子:“chip”
图片截取方式
QPixmap QPixmap::copy ( const QRect & rectangle = QRect() ) const
QPixmap QPixmap::copy ( int x, int y, int width, int height ) const
用这两个函数,就可以截取一部分图片。
QPixmap:用于显示,使用硬件加速渲染显示。不适应与大图的处理。
QImage:适用于图片处理。
QWidget实现自适应缩放,
QWidget在缩放的时候,会触发
void resizeEvent(QResizeEvent *event)
{
QSize size = event->size();
this->resize() //可以重新自定义大小
}
时间日期控件QDateEditQDateTimeEdit
* 下拉箭头可以通过设置calendarPopup属性去实现.这样会弹出时间和日历表
取对象名转为字符串类型:staticMetaObject
//customPlot项目
QVector<QCPScatterStyle::ScatterShape> shapes;
QCPScatterStyle::staticMetaObject.enumerator(QCPScatterStyle::staticMetaObject.indexOfEnumerator("ScatterShape")).valueToKey(shapes.at(i))
connect的使用
- 信号转发给信号:
- connect(ui->tableWidget_pro,SIGNAL(cellClicked(int,int)),this,SIGNAL(cellClicked(int)));
- 使用lambda表达式
- connect(dlg, &QDialog::finished, [&](int result) {…});禁止使用该方式的连接,尤其是使用了& 来获取当前类的全部的对象。如果是不获取则是可以考虑使用。
- connect(dlg, &QDialog::finished, this, [&](int result) {…});替代上面的使用方式,必须要有接收者。但是不建议使用。
原因:第一种方式会导致lambda表达式访问非法内存。因为在当前对象销毁之后,如果sender没有销毁,可以继续发送finished信号,那么在lambda表达式可以继续获取执行,如果表达式内,存在变量的访问。则是会导致访问非法内存。第二种方式可以考虑。但是不建议使用。尤其是lambda表达式内使用了临时变量。如果还留在当前对象(如UI),那么则是会一直触发该lambda表达式。如果使用第二种,必须离开当前作用域时候,调用disconnect。
* 例如:自定义类TableForm,有cellChecked(bool)信号
connect(table,&TableForm::cellChecked,&{…}):
* 在qt中使用信号槽时,有时会想中途断开信号槽的连接,接下来将呈现四种连接断开方法:one:断开明确指定接受对象信号槽,如果连接断开成功返回true,否则返回falsebool QObject::disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)two:断开所有连接到对象的信号disconnect(myObject, 0, 0, 0);three:断开所有连接到特定信号disconnect(myObject, SIGNAL(mySignal()), 0, 0);four:断开特定接收器disconnect(myObject, 0, myReceiver, 0);第五个参数代表槽函数在哪个线程中执行 :
1)自动连接(AutoConnection),默认的连接方式,如果信号与槽,也就是发送者与接受者在同一线程,等同于直接连接;如果发送者与接受者处在不同线程,等同于队列连接。
2)直接连接(DirectConnection),当信号发射时,槽函数立即直接调用。无论槽函数所属对象在哪个线程,槽函数总在发送者所在线程执行,即槽函数和信号发送者在同一线程。[这种方式不能跨线程传递消息]
3)队列连接(QueuedConnection),当控制权回到接受者所在线程的事件循环时,槽函数被调用。槽函数在接受者所在线程执行,即槽函数与信号接受者在同一线程。[这种方式既可以在线程内传递消息,也可以跨线程传递消息]
4)锁定队列连接(BlockingQueuedConnection)
Qt::BlockingQueuedConnection:槽函数的调用时机与Qt::QueuedConnection一致,不过发送完信号后发送者所在线程会阻塞,直到槽函数运行完。接收者和发送者绝对不能在一个线程,否则程序会死锁。在多线程间需要同步的场合可能需要这个。[说明它是专门用来多线程间传递消息的,而且是阻塞的]
5)单一连接(UniqueConnection)
Qt::UniqueConnection:这个flag可以通过按位或(|)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接时,再进行重复的连接就会失败。也就是避免了重复连接
- 不建议使用默认的形式,一般而言,默认的类型AutoConnection,connect多次也会执行多次槽(即使同一个对象的同一个槽)。推荐使用****UniqueConnection,除非你知道你的连接方式
坐标系转换:QWidget:mapToGlobal()
* 全局坐标系可以转为相对坐标系:mapToGlobal(mouseEvent->pos())
* 某控件相对于当前界面的坐标系:mapTo(this,QPoint(0,0))
按钮的提示性文字:QToolTip
* 可以手动显示void QToolTip::showText()
* 如:QToolTip::showText(mapToGlobal(mouseEvent->pos()),toolTip(),this,rect(),3000);
获取桌面对象:
* QDesktopWidget*desktop=QApplication::desktop();//可以获取桌面大小等等信息
逐行读取【QPlainTextEdit】组件里的字符串
//plainTextEdit的内容逐行添加为comboBox的项
QTextDocument* doc=ui->plainTextEdit->document () ; //文本对象
int cnt=doc->blockCount () ;//回车符是一个 block
QIcon icon(M:/images/icons/aim.ico");
ui->comboBox->clear();
for (int i=0; i<cnt;i++)
{
QTextBlock textLine=doc->findBlockByNumber (i) ; // 文本中的一段
QString str=textLine.text();
ui->comboBox->addItem(icon,str);
}
使用QPlainTextEdit自带的快捷菜单
- 在 UI 设计器里,选择为 plainTextEdit 的customContextMenuRequested()信号生成槽函数,编写如下的代码,就可以创建并显示 QPlainTextEdit 的标准快捷菜单:
void Widget::on_plainTextEdit_customContextMenuRequested(const QPoint &pos)
{
//创建并显示标准弹出式菜单
QMenu* menu=ui->plainTextEdit->createStandardContextMenu();
menu->exec(pos);
}
设置窗体置顶,并且处于活动状态
show();
raise();
activateWindow();
有用的全局宏的使用
* Q_DISABLE_COPY:禁止拷贝和赋值;可以用于单例的设计。
全屏:
* QApplication::desktop()->width(),QApplication::desktop()->height()
* showFullScreen();
* showMaximized(); //或者其他;取消全屏
隐藏标题栏
* this->setWindowFlags(Qt::FramelessWindowHint|Qt::Dialog);//隐藏标题栏
设置鼠标的形状
* setCursor(Qt::CrossCursor);
设置全局的快捷键:
* 使用第三方库:QxtGlobalShortcut
最小化到托盘:
* QSystemTrayIcon类
//实现最小化
this->hide();
//新建托盘要显示的icon
QIcon icon = QIcon(":/new/prefix1/Cat.png");
//将icon设到QSystemTrayIcon对象中
mSysTrayIcon->setIcon(icon);
//当鼠标移动到托盘上的图标时,会显示此处设置的内容
mSysTrayIcon->setToolTip(tr("OCR"));
//在系统托盘显示此对象
mSysTrayIcon->show();
// 恢复窗体
//最小化托盘
connect(mSysTrayIcon.get(), &QSystemTrayIcon::activated,
[&](QSystemTrayIcon::ActivationReason reason){
switch(reason){
case QSystemTrayIcon::Trigger:
//单击托盘图标
this->show();
break;
case QSystemTrayIcon::DoubleClick:
//双击托盘图标
//双击后显示主程序窗口
this->show();
break;
default:
break;
}
});
qDebug()\qInfo()格式化输出
* 可以使用qSetMessagePattern();
* 在项目工程中设置 QT_MESSAGE_PATTERN 环境变量;
QT_MESSAGE_PATTERN 的优先级要比 qSetMessagePattern 的函数调用优先级高
* qDebug()可以实现既在控制台输出内容,又可以在日志log4cxx打印的方式:qInstallMessageHandler()
qInstallMessageHandler(myMessageOutput);
static log4cxx::LoggerPtr g_logger;
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
switch (type) {
case QtDebugMsg:
LOG4CXX_INFO(g_logger, QString("Debug: %1 (%2:%3, %4)").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function).toStdString());
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
fflush(stderr);
break;
// case QtInfoMsg:
// LOG4CXX_INFO(g_logger, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
// break;
// case QtWarningMsg:
// LOG4CXX_INFO(g_logger, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
// break;
// case QtCriticalMsg:
// LOG4CXX_INFO(g_logger, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
// break;
// case QtFatalMsg:
// LOG4CXX_INFO(g_logger, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
// abort();
}
}
把一个widget放置在另外一个窗体上面
* 在Q7的lis发送弹窗上实现遮罩层会在lis下面。
* raise()
在一个UI上有多个同类型的控件都是注册事件(QComboBox)
* 在*eventFilter*(QObject*watched,QEvent*event)中对事件进行过滤实现对应的方法。
* 以前的方法一般是多个if…elseif..来实现各个combobox的操作。
* 现在新的方式:
首先先把各个的ComboBox 的数据放在items中,然后各个不同的内容可以使用属性的方式来存储(setProperty())在eventFilter()方法中,如下实现:
if(event->type() == QEvent::MouseButtonPress)
{
QComboBox *cbox = qobject_cast<QComboBox*>(watched);
if(!!cbox && zybio::is_element_in_collection(cbox,
ui->comboBox_patient_type, ui->comboBox_department,
ui->comboBox_submitter, ui->comboBox_clinical_diagnosis,
ui->comboBox_checker,ui->comboBox_examiner,ui->comboBox_comment))
{
const QString& title = cbox->property("title").toString();
QStringList infoList;
for(int i = 1; i < cbox->count(); ++i)
infoList.append(cbox->itemText(i));
StyledDialog dialog;
SelectInfo_Dlg* content = dialog.setSubDialog<SelectInfo_Dlg>( title, cbox->currentText(), infoList );
if(dialog.exec() == QDialog::Accepted)
{
const auto& list = content->getCheckedBtnData();
if( !list.isEmpty() )
{
cbox->setCurrentText(list.front());
}
else
{
cbox->setCurrentIndex(0);
}
}
return true;
}
}
///
template< typename _Element >
inline bool is_element_in_collection( _Element const& elem, _Element const& coll )
{
return elem == coll;
}
template<>
inline bool is_element_in_collection< const char* >( const char* const& elem, const char* const& coll )
{
return strcmp( elem, coll ) == 0;
}
template< typename _Element, typename... _Collection >
inline bool is_element_in_collection( const _Element& elem, const _Element& elem0, const _Collection&... coll )
{
return is_element_in_collection( elem, elem0 ) || is_element_in_collection( elem, coll... );
}
template< typename _Element, unsigned int _N >
inline bool is_element_in_collection( _Element const& elem, _Element const( &coll )[ _N ] )
{
static_assert( !std::is_pointer< _Element >::value, "not pointer type" );
return std::any_of( std::cbegin( coll ), std::cend( coll ), [ &elem ]( _Element const& one ){ return elem == one; } );
}
template< typename _Element, typename _Collection >
inline bool is_element_in_collection( _Element const& elem, _Collection const& coll )
{
return std::any_of( coll.begin(), coll.end(), [ &elem ]( _Element const& one ){ return elem == one; } );
}
tablewidget中莫名出现一个可输入的item
* 原因:setRowCount()时候,如果table存在一个焦点,那么则是会触发一些信号,导致tablewidget出现一个可编辑输入的item。
* 解决方法:在调用setRowCount之前把焦点设置到其他控件上。
在模拟态运行一个弹窗,但是没有传入父类时候,可能会导致可以回到父类再次点击出现弹窗
* 对话框是窗口模态,则只在对话框打开时阻止与父窗口的交互。----qt文档
密码框不能正常弹出键盘的问题。
* 在触摸屏触摸点击的情况下,在*mousePressEvent*(QMouseEvent*event)实现调用OSK程序,但是密码框会导致osk无法调用弹出。
* 只能自己实现密码框的显示。来实现
其他
-
修改窗体的名称:setWindowTitle(“myQt program”);//修改程序名
-
修改图标:在.pro 文件 。加上:RC_ICONS = cat.ico
-
QString::fromLocal8Bit()解决中文乱码;# pragma execution_character_set(“utf-8”)
-
qDebug() 控制台打印。
-
QMessageBox:: 弹窗。
-
appendPlainText() 追加文本
-
自定义控件
-
继承对应的控件。
-
不用继承QoBject类
-
不用在构造方法中new 一个新的对应控件。因为当其他对象new这个对象时候就已经是new了对应控件
-
实现控件的事件
-
给控件注册事件:installEventFileter(this);
-
重写事件过滤器方法:bool eventFilter(QObject *watched, QEvent *event)
i. 在该方法中,可以通过QMouseEvent *mouse = (QMouseEvent *)event;获取鼠标的键值
ii. (mouse->buttons()&Qt::LeftButton) && event->type()==QEvent::MouseButtonPress ; //获取鼠标的触发方式和键值。
iii. watched == ui->btn_0 && event->type()==QEvent::MouseButtonPress //获取触发事件的对象和方式
iv. btn = (QPushButton * ) watched; //获取触发事件的对象。
- 取得对应的布局管理器(只有通过布局管理器,才能将控件添加到widget/窗体中)
my_btn *btn = new my_btn();
QGridLayout *gridLayout = static_cast<QGridLayout*>(ui->wg_btn->layout());
gridLayout->addWidget(btn,row,col);
或者自己添加管理器:
QWidget *window = new QWidget;
QPushButton *button1 = new QPushButton("One");
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(button1);
window->setLayout(layout);
window->show();
-
禁用QSlider和QComboBox的滚动功能
-
重载这两个控件:继承QComboBox;然后重新实现wheelEvent() ;可以不做任何处理。
-
showPopup();显示QComboBox的下拉框内容
可以设置窗体的各种样式,如关闭按钮、栏目、最小化、还原按钮等等。
Qt 程序获取程序所在路径、用户目录路径、临时文件夹等特殊路径的方法
获取程序所在路径
QString QCoreApplication::applicationDirPath()
如果还想要程序的完整名称
qApp->applicationFilePath()
当前工作目录
QString QDir::currentPath()
如果我们是双击一个程序运行的,那么程序的工作目录就是程序所在目录。
如果是在命令行下运行一个程序,那么运行程序时在命令行的哪个目录,那个目录就是当前目录。
临时文件夹
QStandardPaths类中有各种standardLocations等可以获取临时文件以及其他方式。