Qt实现弹出窗口,点击其他位置消失

Qt实现弹出窗口,点击其他位置消失

一开始时想的很美好,写button的点击事件,然后在弹窗界面中写eventFilter(QEvent *e)事件

1
2
3
4
5
6
7
8
if (event->type() == QEvent::ActivationChange)
{
if(QApplication::activeWindow() != this)
{
this->close();
}
}
return QWidget::event(event);

但是这样写发现一个问题,当我想实现点击按钮也可以关闭dialog时,不行了,因为EventFilter是第一触发事件,当我点按钮是,判断当前的活动窗口不是dialog,他先关闭,然后触发按钮的点击事件,再打开了dialog。很麻烦。

后来有了解到Qt有一个popup的属性

1
info->setWindowFlags(Qt::FramelessWindowHint | Qt::Popup);

这样设置了之后,窗口是无边框且是点击其他位置关闭,但是还是会有上面的问题,没解决。

再后来,在一篇blog中看到了Qt::WA_NoMouseReplay属性
机翻一下:用于弹出窗口小部件。指示在弹出小部件关闭时不应重播最近的鼠标按下事件。该标志由小部件的作者设置,并在小部件每次接收到新的鼠标事件时由Qt内核清除。
大意就是它会拦截鼠标事件不会传递,专用于弹窗事件。
呜呜呜,原来Qt早就搞定了这个事件,找了半天,还是Qt不熟悉。
具体使用,在弹出的窗口里重写mousePressEvent(QMouseEvent *e)事件:

1
2
3
4
5
void InfoDialog::mousePressEvent(QMouseEvent *e)
{
setAttribute(Qt::WA_NoMouseReplay);
QDialog::mousePressEvent(e);
}

Qt的宏定义区分不同操作系统

程序中遇到需要区分操作系统时,可使用qt的宏定义:

中,定义了各个系统的宏定义

Q_OS_AIX
Defined on AIX.
Q_OS_ANDROID
Defined on Android.
Q_OS_BSD4
Defined on Any BSD 4.4 system.
Q_OS_BSDI
Defined on BSD/OS.
Q_OS_CYGWIN
Defined on Cygwin.
Q_OS_DARWIN
Defined on Darwin-based operating systems such as macOS, iOS, watchOS, and tvOS.
Q_OS_DGUX
Defined on DG/UX.
Q_OS_DYNIX
Defined on DYNIX/ptx.
Q_OS_FREEBSD
Defined on FreeBSD.
Q_OS_HPUX
Defined on HP-UX.
Q_OS_HURD
Defined on GNU Hurd.
Q_OS_IOS
Defined on iOS.
Q_OS_IRIX
Defined on SGI Irix.
Q_OS_LINUX
Defined on Linux.
Q_OS_LYNX
Defined on LynxOS.
Q_OS_MAC
Deprecated synonym for Q_OS_DARWIN. Do not use.
Q_OS_MACOS
Defined on macOS.
Q_OS_NETBSD
Defined on NetBSD.
Q_OS_OPENBSD
Defined on OpenBSD.
Q_OS_OSF
Defined on HP Tru64 UNIX.
Q_OS_OSX
Deprecated synonym for Q_OS_MACOS. Do not use.
Q_OS_QNX
Defined on QNX Neutrino.
Q_OS_RELIANT
Defined on Reliant UNIX.
Q_OS_SCO
Defined on SCO OpenServer 5.
Q_OS_SOLARIS
Defined on Sun Solaris.
Q_OS_TVOS
Defined on tvOS.
Q_OS_ULTRIX
Defined on DEC Ultrix.
Q_OS_UNIX
Defined on Any UNIX BSD/SYSV system.
Q_OS_UNIXWARE
Defined on UnixWare 7, Open UNIX 8.
Q_OS_WATCHOS
Defined on watchOS.
Q_OS_WIN32
Defined on 32-bit and 64-bit versions of Windows.
Q_OS_WIN64
Defined on 64-bit versions of Windows.
Q_OS_WIN
Defined on all supported versions of Windows. That is, if Q_OS_WIN32, Q_OS_WIN64, or Q_OS_WINRT is defined.
Q_OS_WINPHONE
Defined on Windows Phone 8.
Q_OS_WINRT
Defined for Windows Runtime (Windows Store apps) on Windows 8, Windows RT, and Windows Phone 8.

举例1:
记得需要有QObject的头文件,才可以

1
2
3
4
5
6
7
#include<QObject>

#ifdef Q_OS_WIN
#include <winsock2.h>
#endif

#include <mysql.h>

举例2:
对于标记了Q_OBJECT这个宏的类,其成员函数可以直接上面的区分操作系统的这些宏定义。

***.h文件:

1
2
3
4
5
6
7
8
9
10
11
class DetailStepInfo : public QObject
{
Q_OBJECT

public:

....................

...................

}

***.cpp文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bool DetailStepInfo::**************()
{

#ifdef Q_OS_WIN

#endif

#ifdef Q_OS_LINUX
QString command = QString("chmod +rw /****************************");
QProcess proc;
proc.execute(command);
#endif

...........................

}

Qt生成缩略图片存入sqlite

Qt生成缩略图片存入sqlite

新建一个工程pro文件中加入 QT += sql 添加sql支持。

>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// main.cpp

#include <QApplication>
#include <QtGui>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

//添加数据库,不表
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "conn1");
db.setDatabaseName("/home/htux/thumbs.sqlite");
if(!db.open()) return 1;

QByteArray baImage;

QString filename = "/home/htux/file2.jpg";
QPixmap pixmapIn(filename);

QBuffer buffer(&baImage);
buffer.open(QIODevice::WriteOnly);

QPixmap pixmapSmall;
//让生成的缩略图高宽都不超过256.
pixmapSmall = pixmapIn.scaled(256,256,
Qt::KeepAspectRatio, Qt::SmoothTransformation);
//保存生成的缩略图到ByteArray, 格式为JPG, 图片质量50.
//图片质量的取值Qt文档中没查到,不过按照国际惯例应该是0-100
//保存几个不同质量的图片看看差别
pixmapSmall.save(&buffer, "JPG",50);
pixmapSmall.save("/home/htux/file2.png", "PNG");
pixmapSmall.save("/home/htux/file2-5.jpg", "JPG", 20);
pixmapSmall.save("/home/htux/file2-5.jpg", "JPG", 50);
pixmapSmall.save("/home/htux/file2-8.jpg", "JPG", 80);

QSqlQuery query(db);

query.exec("CREATE TABLE thumbs "
"(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
" filename VCHAR(20) , thumbnail BLOB);");

QString sql = QString("INSERT INTO thumbs VALUES "
"( NULL , :filename, :thumbnail );");

query.prepare(sql);
query.bindValue(":filename", filename);
query.bindValue(":thumbnail", baImage);

query.exec();

query.exec("select * from thumbs;");

//跳到最后存入的记录
if (!query.last()) return 1;

QPixmap pixmapOut;
//读出存入的图片
pixmapOut.loadFromData(query.value(2).toByteArray());

db.close();
//把图片用Label显示出来.
QLabel label;
label.setPixmap(pixmapOut);
label.show();

return a.exec();
}

QLineEdit获取焦点后全选字符/失去焦点清除选择

一直觉得Chrome的地址栏的体验非常好,获取焦点后自动全选,无论是想复制地址还是重新输入新的地址都帮我们省掉了一步,如何用QLineEdit实现这个特点呢。

网上搜索了一下,发现一篇博客http://www.cnblogs.com/91program/p/5521420.html ,但是这篇博客讲述的方法有点复杂,最后还要通过延时来达到目的,有点怪异。

最后只得查看QLineEdit的类参考仿照Chrome实现,Chrome的地址栏在无焦点状态下鼠标按下不动的时候,地址栏获取了焦点,光标位于鼠标位置;鼠标无移动释放,全选地址栏字符;再次单击,清除全选;鼠标按下移动后释放,则不会全选,而是选择字符;地址栏失去焦点,清除选择。

看起来我们需要判断鼠标按下时的位置与鼠标释放时鼠标有没有移动,申请一个变量m_pressPos来存储鼠标按下时的位置。还需要知道鼠标单击的时候QLineEdit是否已获得焦点,我们用变量m_onFocus来记录。定义一个QLineEdit子类,然后重新实现mousePressEvent,mouseReleaseEvent,focusOutEvent。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#ifndef URLLINEEDIT_H
#define URLLINEEDIT_H

#include <QLineEdit>

class UrlLineEdit : public QLineEdit
{
Q_OBJECT
public:
UrlLineEdit(QWidget *parent = 0);
~UrlLineEdit();
protected:
void mouseReleaseEvent(QMouseEvent *e);
void mousePressEvent(QMouseEvent *e);
void focusOutEvent( QFocusEvent * e );
private:
bool m_onFocus;
QPoint m_pressPos;
};
#endif // URLLINEEDIT_H

#include "urllineedit.h"
#include <QFocusEvent>

UrlLineEdit::UrlLineEdit(QWidget *parent)
:QLineEdit(parent),
m_onFocus(false)
{

}

UrlLineEdit::~UrlLineEdit()
{

}
void UrlLineEdit::mouseReleaseEvent(QMouseEvent *e)
{
if (e->button() == Qt::LeftButton ){
if( e->pos() == m_pressPos && !m_onFocus){
m_onFocus = true;
selectAll();
update();
} else {
int start = cursorPositionAt(m_pressPos);
setSelection( start , cursorPositionAt(e->pos())-start );
}
}
QLineEdit::mouseReleaseEvent(e);

}

void UrlLineEdit::mousePressEvent(QMouseEvent *e)
{
if (e->button() == Qt::LeftButton){
m_pressPos = e->pos();
setCursorPosition(cursorPositionAt(m_pressPos));
}
QLineEdit::mousePressEvent(e);
}

void UrlLineEdit::focusOutEvent(QFocusEvent *e)
{
m_onFocus = false;
if(!hasSelectedText()){
deselect();
}
QLineEdit::focusOutEvent(e);
}

通过测试基本上是实现了类似Chrome的这个特性。