介绍
Qt安装
https://download.qt.io/
目前我下载的是5.12.10版本
https://download.qt.io/archive/qt/5.12/5.12.10/
VS插件安装:
https://download.qt.io/archive/vsaddin/
第一个Qt项目
工程规范化:
创建一个文件夹Lesson ,然后分别创建bin 、doc 、lib 、src 文件夹.
1
2
3
4
5
6
7
D:.
│
└─Lesson
├─bin
├─doc
├─lib
└─src
新建一个qt工程,目录放在src 中.
目录文件介绍:
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
D :.
│
├─ bin
├─ doc
├─ lib
└─ src
├─ build - QtTest - Desktop_Qt_5_12_10_MSVC2017_32bit - Debug
│ │ . qmake . stash
│ │ Makefile
│ │ Makefile . Debug
│ │ Makefile . Release
│ │ ui_widget . h //这是qt设计器代码
│ │
│ ├─ debug
│ │ main . obj
│ │ moc_predefs . h //qt中与信号槽相关的代码
│ │ moc_widget . cpp
│ │ moc_widget . obj
│ │ QtTest . exe
│ │ QtTest . ilk
│ │ QtTest . pdb
│ │ QtTest . vc . pdb
│ │ widget . obj
│ │
│ └─ release
└─ QtTest
main . cpp
QtTest . pro //这是qt的项目文件,用来生成makefile文件.
QtTest . pro . user //这是qt的编译环境,可删掉,重新指定编译环境.
widget . cpp
widget . h
widget . ui
注意
在Qt中创建的.h .cpp文件的文件名要小写,为了跨平台.
在windows平台,文件名大小写不敏感,但在其他平台大小写可能是敏感的.
QMake
Qt程序编译步骤
编译Qt pro文件生成makefile
使用jom或make编译makefile
jom下载链接
jom或make会进行下述代码生成:
1
uic.exe widget.ui -o ui_widget.h
1
moc.exe widget.h moc_widget.cpp
控制台手工编译Qt程序步骤如下:
准备源文件
1
2
#include <stdio.h>
void func1 ();
1
2
3
4
5
#include "func1.h"
void func1 (){
printf ( "func1 \n " );
}
1
2
3
4
5
6
7
8
9
10
#include <stdlib.h>
#include <stdio.h>
#include "func1.h"
int main (){
func1 ();
printf ( "main \n " );
system ( "pause" );
return 0 ;
}
编写pro文件
1
2
3
4
5
6
7
8
SOURCES += \
main . cpp \
func1 . cpp
HEADERS += \
func1 . h
CONFIG += console
这一步也可以利用qmake自动生成
1
2
3
4
//命令行执行以下语句,添加VC环境
"D:/VS2019/VS2019/VC/Auxiliary/Build/vcvarsx86_amd64.bat"
//执行qmake语句
qmake - project
编译
1
2
3
4
call "D:/VS2019/VS2019/VC/Auxiliary/Build/vcvarsx86_amd64.bat"
qmake - o makefile LuoQt . pro
jom / f makefile
pause
控制台编译Qt.7z
Qt项目转VS工程
有以下两种方式:
命令行
1
2
3
4
//添加VC环境
"D:/VS2019/VS2019/VC/Auxiliary/Build/vcvarsx86_amd64.bat"
//生成vcxproj文件
qmake - tp vc luoQt . pro
利用插件打开pro项目
信号槽
摘要
类似Windows的消息机制
信号函数只发送不需要知道接收者
槽函数只接收不管通信.在主线程中调用,不要在其他线程中调,会崩!!!
使用QObject::connect()函数进行绑定
Qt信号槽原理如下:
绑定信号函数与槽函数.
调用信号函数(将信号写入队列中).
主线程从队列中获取信号.
通过QtCreator设置信号槽
有以下两种方式:
拖动.
添加,点下方的加号进行添加.
手动添加槽函数
Q_OBJECT:
如果一个类中,我们添加了信号槽,我们就要定义Q_OBJECT 这个宏,这样的话,QT的moc程序才会帮我们生成代码.
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class luoqt : public QWidget
{
Q_OBJECT
public :
luoqt ( QWidget * parent = Q_NULLPTR );
//信号函数,只声明即可
signals :
void TstSignal ();
//槽函数声明
public slots :
void TstSlot ();
private :
Ui :: luoqtClass ui ;
};
//槽函数定义
void luoqt :: TstSlot ()
{
printf ( "Hello TstSlot \n " );
}
利用QtCreator绑定信号槽
将上述写的槽函数绑定到按钮的点击事件中:
新建一个按钮,利用QtCreator拖动来设置.
点击上述编辑按钮后,添加新建的槽函数.
将按钮点击和刚创建的槽函数绑定起来.
这样的话,就可以了,测试的时候,我们将控制台打开.
将上述写的信号函数和槽函数绑定起来:
利用QtCreator拖动来设置,在空白的地方拖一下就可以了.
添加信号函数和槽函数.
绑定.
Qt生成代码分析:
上面这些操作Qt帮我们生成了很多的代码,
手动绑定信号槽
新建一个按钮.
添加信号和槽函数.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//luoqt.h
class luoqt : public QWidget
{
Q_OBJECT
public :
luoqt ( QWidget * parent = Q_NULLPTR );
//信号函数
signals :
void TstSignal ();
//槽函数
public slots :
void TstSlot ();
void TstConnect ();
private :
Ui :: luoqtClass ui ;
};
使用connect函数进行绑定.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//luoqt.cpp
luoqt :: luoqt ( QWidget * parent )
: QWidget ( parent )
{
ui . setupUi ( this );
//使用connect进行绑定
//发送者 信号函数 接收者 槽函数
QObject :: connect ( ui . btn_connect , SIGNAL ( TstSignal ()), this , SLOT ( TstConnect ()));
}
void luoqt :: TstSlot ()
{
printf ( "Hello TstSlot \n " );
}
void luoqt :: TstConnect ()
{
printf ( "Hello TstConnect \n " );
}
QThread
新建一个类,继承QThread,重写run函数即可.
1
2
3
4
5
6
7
8
9
#include <QThread>
class LuoThread : public QThread
{
public :
void run () {
//休眠5s
QThread :: msleep ( 5000 );
}
};
1
2
3
4
5
//调用,调start,就会自动调用上述的run函数
LuoThread luoThread ;
luoThread . start ();
//或者使用下面这种
( new LuoThread ()) -> start ();
所有用户界面对象的基类.
使用示例:
假设我们要实现的是,程序启动的时候,运行的窗口是我们新建的类所关联的一个窗口,然后5s之后窗口隐藏.
新建一个类,继承QWidget.
1
2
3
4
5
6
7
8
9
10
11
12
//LuoQWidget.h
#include <QWidget>
class LuoQWidget : public QWidget
{
Q_OBJECT
public :
LuoQWidget ();
~ LuoQWidget ();
signals :
void LuoHide ();
};
1
2
3
4
5
6
7
8
9
10
11
//LuoQWidget.cpp
LuoQWidget :: LuoQWidget ()
{
//手动绑定信号槽
QObject :: connect ( this , SIGNAL ( LuoHide ()), this , SLOT ( hide ()));
}
LuoQWidget ::~ LuoQWidget ()
{
}
新建一个类,继承QThread.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//LuoThread.h
#include "LuoQWidget.h"
#include <QThread>
class LuoThread : public QThread
{
public :
LuoThread ( LuoQWidget * pQWidget ) {
m_pQWidget = pQWidget ;
}
public :
void run () {
//休眠5s
QThread :: msleep ( 5000 );
//发信号
m_pQWidget -> LuoHide ();
}
private :
LuoQWidget * m_pQWidget ;
};
main函数中进行调用.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//main.cpp
#include <QtWidgets/QApplication>
#include "LuoQWidget.h"
#include "LuoThread.h"
int main ( int argc , char * argv [])
{
QApplication a ( argc , argv );
LuoQWidget w ;
w . setWindowTitle ( "LuoQWidget" );
w . show ();
LuoThread luoThread ( & w );
luoThread . start ();
return a . exec ();
}
注意
不要在其他线程中直接调用槽函数,否则会崩,我们可以绑定一个信号和槽函数,然后在其他线程中发信号.
相关函数:
获取窗口坐标和尺寸:
1
2
3
4
5
6
7
8
9
10
11
QRect & QWidget :: geometry ();
void QWidget :: setGeometry ( int ax , int ay , int aw , int ah );
QWidget w ;
w . x ();
w . y ();
w . width ();
w . height ();
void QWidget :: move ( int ax , int ay );
void QWidget :: resize ( int w , int h );
窗口状态:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void setWindowState ( Qt :: WindowStates state );
//参数如下
enum WindowState {
WindowNoState = 0x00000000 ,
WindowMinimized = 0x00000001 ,
WindowMaximized = 0x00000002 ,
WindowFullScreen = 0x00000004 ,
WindowActive = 0x00000008
};
//Qt定义的槽函数
void showMinimized ();
void showMaximized ();
void showFullScreen ();
void showNormal ();
定制窗口:
1
2
3
4
5
6
7
8
9
10
11
12
QWidget w ;
//无边框
w . setWindowFlags ( Qt :: FramelessWindowHint );
//去掉最大最小化按钮
//w.setWindowFlag(Qt::WindowMinimizeButtonHint, false);
//w.setWindowFlag(Qt::WindowMaximizeButtonHint, false);
//标题栏保留,去除所有按钮
w . setWindowFlags ( Qt :: WindowTitleHint | Qt :: CustomizeWindowHint );
w . show ();
QString
使用示例
空判断
1
2
3
4
5
QString qstr ;
if ( qstr . isEmpty ())
{
printf ( "qstr is empty \n " );
}
字符串拼接
1
2
3
4
QString qstr1 = "Luo" ;
QString qstr2 = "Hun" ;
qstr1 += qstr2 ;
//qstr1, LuoHun
字符串格式化
1
2
3
4
5
6
QString qstr ;
qstr = QString ( "name = %1, arg = %2 %3" )
. arg ( "Luo" , 2 )
. arg ( 56 )
. arg ( 10 , 0 , 16 );
//qstr, name = Luo, arg = 56 a
单个整型字符串互转
1
2
3
4
//单个整型转字符串
QString qstrNum = QString :: number ( 5566 );
//字符串转整型
int num = qstrNum . toInt ();
提取字符串
1
2
3
4
5
6
7
8
9
QString qstr = "Luo5566,Hun8899" ;
QString qstrLeft = qstr . left ( 5 );
//qstrLeft, Luo55
QString qstrMid = qstr . mid ( 2 , 6 );
//qstrMid, o5566,
QString qstrRight = qstr . right ( 5 );
//qstrRight, n8899
字符串查找
1
2
3
QString qstr = "Luo5566,Hun8899" ;
int n = qstr . indexOf ( "55" );
//n, 3
检查字符串是否以XXX开始或结束
1
2
3
4
5
6
7
8
9
10
QString qstr = "Luo5566Hun" ;
if ( qstr . startsWith ( "luo" , Qt :: CaseInsensitive ))
{
printf ( "startsWith True \n " );
}
if ( qstr . endsWith ( "Hun" , Qt :: CaseSensitive ))
{
printf ( "endsWith True \n " );
}
字符串替换
1
2
3
QString qstr = "Luo5566,5566Hun8899" ;
QString qstr1 = qstr . replace ( "5566" , "2233" );
//qstr1, Luo2233,2233Hun8899
字符串两端删除空白符
1
2
3
QString qstr = " Luo5566,Hun8899 " ;
QString qstr1 = qstr . trimmed ();
//qstr1, Luo5566,Hun8899
分割字符串
1
2
3
4
5
6
7
8
9
10
QString qstr = "Luo5566:5566Hun:8899" ;
QStringList qLst = qstr . split ( ":" );
for ( QString str : qLst )
{
printf ( "%s \n " , str . toStdString (). c_str ());
}
//Luo5566
//5566Hun
//8899
VS中解决中文乱码
QString内部采用UTF-16编码,构造函数QString::QString(const char *str)默认使用fromUtf8(),将str所指的执行字符集从UTF-8转码成UTF-16.
VS默认创建的源码文件格式为GBK.
QtCreator默认创建的源码文件格式为UTF-8.
使用QStringLiteral
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <QDebug>
#include <QStringLiteral>
#include <QMessageBox>
int main ( int argc , char * argv [])
{
QApplication a ( argc , argv );
QWidget w ;
QString qstr = QStringLiteral ( "中文" );
qDebug () << qstr ;
QMessageBox :: information ( NULL , "Luo" , qstr );
w . show ();
return a . exec ();
}
注意
如果源文件本身的格式为UTF-8,再用QStringLiteral这个宏进行转换就会产生乱码.
手动将该源文件格式转换为UTF-8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <QDebug>
#include <QStringLiteral>
#include <QMessageBox>
int main ( int argc , char * argv [])
{
QApplication a ( argc , argv );
QWidget w ;
QString qstr = "中文" ;
qDebug () << qstr ;
QMessageBox :: information ( NULL , "Luo" , qstr );
w . show ();
return a . exec ();
}
使用代码修改源文件字符集为UTF-8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <QDebug>
#include <QStringLiteral>
#include <QMessageBox>
#pragma execution_character_set("utf-8")
int main ( int argc , char * argv [])
{
QApplication a ( argc , argv );
QWidget w ;
QString qstr = "中文" ;
qDebug () << qstr ;
QMessageBox :: information ( NULL , "Luo" , qstr );
w . show ();
return a . exec ();
}
编码方式转换
设置本地字符集:
1
2
#include <QTextCodec>
QTextCodec :: setCodecForLocale ( QTextCodec :: codecForName ( "GBK" )); //或UTF-8
GBK->UTF-8:
通常在VS 中使用QString::fromLocal8Bit
1
2
3
char * szSrc = "中文测试" ;
//VS本地编码默认为GBK
QString qstr = QString :: fromLocal8Bit ( szSrc );
UTF-8->GBK:
通常在QtCreator 中使用QString::fromUtf8
1
2
3
const char * szSrc = "中文测试" ;
//QtCreator本地编码默认为UTF-8
QString qstr = QString :: fromUtf8 ( szSrc );
QString与WinAPI
将QString中存放的中文在WinAPI中使用.
1
2
3
4
5
6
7
char * szSrc = "中文测试" ;
//VS 中使用QString::fromLocal8Bit
//QtCreator中使用QString::fromUtf8
QString qstr = QString :: fromLocal8Bit ( szSrc );
:: MessageBoxA ( NULL , qstr . toLocal8Bit (), "MessageBoxA" , MB_OK );
:: MessageBoxW ( NULL , qstr . toStdWString (). c_str (), L "MessageBoxW" , MB_OK );
QLabel
主要成员函数:
1
2
3
4
5
6
7
8
9
10
11
void setText ( QString ); //设置label框内的文本.
void hide (); //隐藏label框.
void setBuddy ( QWidget * ); //把另一个部件设为label框的伙伴,方便快捷使用.
void clear (); //清空label框内所有内容.
void setPixmap ( QPixmap ( QString )); //设置图片.
void setMovie ( QMovie * ); //设置电影.
void setScaledContents ( bool ); //设置是否按比例填充满整个label框(非常重要)
void setToolTip ( QString ); //设置信息提示,鼠标放在label框上面会自动跳出文字.
void setToolTipDuration ( int ); //设置信息提示的持续时间,单位是毫秒.
void setAlignment ( Qt :: Alignment ); //设置label框的对齐格式.
void setStyleSheet ( QString ); //设置label框的样式.
播放Gif动画:
1
2
3
4
5
6
QLabel * label = new QLabel ( this );
label -> setGeometry ( 0 , 0 , 400 , 400 );
QMovie * mov = new QMovie ( "tst.gif" );
label -> setMovie ( mov );
label -> show ();
mov -> start ();
文本格式:
两种格式:
PlainText, \n换行.
RichText, 支持html.
Url链接:
首先选择RichText.
1
2
<br>是换行.
QtCreator有点Bug,我目前使用的是5.12.0,要在文本中输入<br>后双击文本,才可以弹出下面的框
通过上图插入链接,Qt已经定义好了两个信号,然后就可以写槽函数来处理相应的事件了.
1
2
3
4
//鼠标点击url链接信号
void linkActivated ( QString );
//鼠标滑过url链接信号
void linkHovered ( QString ));
属性设置:
通过勾选上述标志,可设置QLabel可选择可编辑等.
事件信号:
1
2
3
4
void QAbstractButton :: clicked ()
void QAbstractButton :: clicked ( bool checked = false ) //是否选中
void QAbstractButton :: pressed ()
void QAbstractButton :: released ()
设置快捷键:
在英文按钮前加&符号.
这样的话,通过快捷键Alt + P就可以激发click信号了.
使用下述代码
1
2
ui . btn_shortCut -> setShortcut ( tr ( "Alt+x" ));
ui . btn_shortCut -> setShortcut ( tr ( "Alt+x,Ctrl+c" ));
QLineEdit
常用函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void setText ( QString ); //设置文本,槽函数 不发信号
QString text (); //获取文本
void setPlaceholderText ( const QString & ); //设置提示文字
void setClearButtonEnabled ( bool enable ); //是否设置一个清空按钮
void setReadOnly ( bool );
void setMaxLength ( int );
void setEchoMode ( QLineEdit :: EchoMode ); //设置行编辑框内文本的显示模式
//最常用的模式,分别为:QLineEdit::Normal,QLineEdit::Password.默认为QLineEdit::Normal.
void setDragEnabled ( bool ); //设置行编辑框内的被选择的文本能否被拖拽,默认不能被拖拽
void setAcceptDrops ( bool ); //设置行编辑框能否被拖拽进来文本.
bool isModified (); //判断文本是否被修改.
void selectAll (); //选中框内所有文本.
QString displayText (); //返回显示的文本.
QString selectedText (); //返回被选中的文本.
void setInputMask ( const QString & inputMask ); //格式掩码
void setValidator ( QVaildator * ); //设置输入验证器
事件信号:
1
2
3
4
void editingFinished (); //按下回车,焦点移开
void returnPressed (); //格式有效,如setInputMask的参数为"NNN",则编辑框内必须输入3个英文字母或者数字,此时按回车,方可激发该信号
void textChanged ( const QString & text ); //setText()也会激发这个信号
void textEdited ( const QString & text );
格式掩码:
假如说编辑框中要设置格式,比如说要指定输入IP地址
1
2
ui . Edt_IP -> setInputMask ( "000.000.000.000;_" );
//;后面的_,表示无输入时,填_
格式校验:
设置有效范围:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <QIntValidator>
#include <QDoubleValidator>
//设置只输入整型,设置有效范围为10, 100
QIntValidator * iVal = new QIntValidator ();
iVal -> setRange ( 10 , 100 );
ui . Edt_Int -> setValidator ( iVal );
//设置只输入浮点,设置有效范围为10, 20,精度为2,即小数点后面有两位
QDoubleValidator * dVal = new QDoubleValidator ( 0 );
dVal -> setRange ( 10 , 20 , 3 );
dVal -> setNotation ( QDoubleValidator :: StandardNotation );
ui . Edt_Double -> setValidator ( dVal );
//验证邮箱
QRegExp exp ( "[a-zA-Z0-9-_]+@[a-zA-Z0-9_]+ \\ .[a-zA-Z]+" );
QRegExpValidator * rVal = new QRegExpValidator ();
rVal -> setRegExp ( exp );
ui . Edt_RegExp -> setValidator ( rVal );
注意
上述是设置LineEdit的有效范围,并不是限制输入的范围,如果想要限制输入的范围,我们可以使用QSpinBox、QDoubleSpinBox.
1
2
ui . spinBox -> setRange ( 10 , 20 );
ui . doubleSpinBox -> setRange ( 1.0 , 20.0 );
校验是否有效:
我们可以设置一个按钮,当编辑框输入内容后,点击按钮来校验.
1
2
3
4
5
6
7
8
9
10
11
const QValidator * pQValidator = ui . Edt_Int -> validator ();
int pos = 0 ;
int nRet = pQValidator -> validate ( ui . Edt_Int -> text (), pos );
if ( nRet == QValidator :: Acceptable )
{
qDebug () << QStringLiteral ( "格式正确" );
}
//nRet的返回值有以下三种
//QValidator::Invalid 格式正确
//QValidator::Intermediate 中间输入没结束
//QValidator::Acceptable 格式正确
Qt布局
遍历QObject子节点:
1
2
3
4
5
6
7
8
9
QObjectList cs = this -> children ();
for ( int i = 0 ; i < cs . size (); i ++ )
{
//遍历子节点, 获取节点对象名称
qDebug () << cs [ i ] -> objectName ();
//遍历子节点, 获取节点对象类型
const QMetaObject * oj = cs [ i ] -> metaObject ();
qDebug () << oj -> className ();
}
递归遍历QObject子节点:
可以遍历子节点的子节点.
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
void PrintName ( QObject * obj )
{
if ( ! obj ) //为空直接返回
{
return ;
}
printf ( "%s :" , obj -> objectName (). toStdString (). c_str ());
const QMetaObject * mobj = obj -> metaObject (); //获取元数据
QString cname = mobj -> className ();
printf ( "%s \n " , cname . toStdString (). c_str ());
//对PushButton进行操作
if ( cname == "QPushButton" )
{
QPushButton * pb = qobject_cast < QPushButton *> ( obj );
if ( pb )
{
pb -> setText ( pb -> text () + "class" );
}
}
//递归打印名字
QObjectList cs = obj -> children ();
if ( cs . size () <= 0 )
{
return ;
}
for ( int i = 0 ; i < cs . size (); i ++ )
{
PrintName ( cs [ i ]);
}
}
QSizePolicy布局尺寸策略分析:
有四种布局:
Vertical Layout
Horizontal Layout
Grid Layout
Form Layout
SizeHint推荐尺寸:
1
2
QSize sizeHint () //推荐尺寸,只能重载修改
QSize size () //不包含边框的窗口尺寸
QSizePolicy::PolicyFlag:
1
2
3
4
QSizePolicy :: GrowFlag //必要时可超过推荐
QSizePolicy :: ExpandFlag //尽可能的拓展
QSizePolicy :: ShrinkFlag //必要时可小于推荐
QSizePolicy :: IgnoreFlag //缺省大小被忽略
QSizePolicy::Policy:
QSizePolicy::Policy
QSizePolicy::PolicyFlag
Fixed
0
只参考sizeHint()
Minimum
GrowFlag
伸展和收缩 >= sizeHint()
Maximum
ShrinkFlag
伸展和收缩 <= sizeHint()
Preferred
GrowFlag | ShrinkFlag
Expanding
GrowFlag | ShrinkFlag | ExpandFlag
尽量缩放,最小值为推荐值
MinimumExpanding
GrowFlag | ExpandFlag
Ignored
ShrinkFlag | GrowFlag | IgnoreFlag
忽略推荐大小,尽量缩放
QVBoxlayout,QHBoxLayout:
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
#include <QWidget>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
int main ( int argc , char * argv [])
{
QApplication a ( argc , argv );
//设置全局字体
QFont f ( "Yahei Mono" , 12 );
a . setFont ( f );
QWidget * LuoWin = new QWidget ;
LuoWin -> resize ( 400 , 400 );
//垂直布局
QVBoxLayout * lay = new QVBoxLayout ;
//新建一个按钮
QPushButton * btn1 = new QPushButton ( "btn1" );
//设置按钮的尺寸策略, 设置Fixed, 使用推荐尺寸
btn1 -> setSizePolicy ( QSizePolicy :: Expanding , QSizePolicy :: Expanding );
//设置按钮的最大最小尺寸
btn1 -> setMinimumSize ( 20 , 10 );
btn1 -> setMaximumSize ( 600 , 100 );
QPushButton * btn2 = new QPushButton ( "btn2" );
//布局中添加按钮
lay -> addWidget ( btn1 );
lay -> addWidget ( btn2 );
//设置布局的边界, 在LuoWin->show()前设置和后面设置是不一样的,在前设置才可以改变btn1->width()的值
lay -> setContentsMargins ( 0 , 0 , 0 , 0 );
//设置布局中元素之间的间距,垂直布局,当缩的很小的时候,就可以看到间距了
lay -> setSpacing ( 10 );
//添加上述布局
LuoWin -> setLayout ( lay );
LuoWin -> show ();
//打印推荐尺寸,这个值只有在设置了布局,才可能有效
qDebug () << "width: \t " << btn1 -> sizeHint (). width () << " height:" << btn1 -> sizeHint (). height ();
//打印实际尺寸
qDebug () << "width: \t " << btn1 -> width () << " height:" << btn1 -> height ();
return a . exec ();
}
QGridLayout:
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
#include <QWidget>
#include <QSizePolicy>
#include <QGridLayout>
#include <QPushButton>
int main ( int argc , char * argv [])
{
QApplication a ( argc , argv );
//设置全局字体
QFont f ( "Yahei Mono" , 12 );
a . setFont ( f );
QWidget * LuoWin = new QWidget ;
LuoWin -> resize ( 200 , 200 );
QGridLayout * lay = new QGridLayout ;
QPushButton * btn00 = new QPushButton ( "btn00" );
QPushButton * btn02 = new QPushButton ( "btn02" );
QPushButton * btn12 = new QPushButton ( "btn12" );
QPushButton * btn33 = new QPushButton ( "btn33" );
lay -> addWidget ( btn00 , 0 , 0 );
lay -> addWidget ( btn02 , 0 , 2 );
lay -> addWidget ( btn12 , 1 , 2 );
lay -> addWidget ( btn33 , 3 , 3 );
//设置控件之间的间距
//水平间距
lay -> setHorizontalSpacing ( 20 );
//垂直间距
lay -> setVerticalSpacing ( 10 );
//也可以使用setSpacing同时设置水平和垂直间距
//lay->setSpacing(10);
//设置布局的对齐方式
lay -> setAlignment ( Qt :: AlignLeft );
LuoWin -> setLayout ( lay );
LuoWin -> show ();
return a . exec ();
}
QFormLayout:
以下示例,实现遍历FormLayout布局所有元素,并实现空验证和清除.
luoqt.h:
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
#pragma once
#include <QtWidgets/QWidget>
#include "ui_luoqt.h"
#include <QDebug>
#include <QFile>
#include <QFormLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QLabel>
class luoqt : public QWidget
{
Q_OBJECT
public :
luoqt ( QWidget * parent = Q_NULLPTR );
public slots :
//设置皮肤样式
static void SetStyle ( const QString & styleName );
void Save ();
void Clear ();
private :
Ui :: luoqtClass ui ;
};
luoqt.cpp:
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include "luoqt.h"
luoqt :: luoqt ( QWidget * parent )
: QWidget ( parent )
{
ui . setupUi ( this );
//新建一个FormLayout布局
QFormLayout * lay = new QFormLayout ;
QLineEdit * edtName = new QLineEdit ;
//创建一个带有给定文本的QLabel及QWidget控件行
lay -> addRow ( "&Name" , edtName );
QLineEdit * edtEmail = new QLineEdit ;
lay -> addRow ( "&Email" , edtEmail );
QLineEdit * edtAge = new QLineEdit ;
//插入到下标1的位置, 从0开始
lay -> insertRow ( 1 , "&Age" , edtAge );
//显示出错信息
QLabel * labelInfo = new QLabel ;
labelInfo -> setText ( "Input" );
labelInfo -> setStyleSheet ( "color:red" );
//插入到下标0的位置, 从0开始
lay -> insertRow ( 0 , "" , labelInfo );
//添加Save clear按钮
QPushButton * btnSave = new QPushButton ( "Save" );
QPushButton * btnClear = new QPushButton ( "Clear" );
//信号槽绑定
QObject :: connect ( btnSave , SIGNAL ( clicked ()), this , SLOT ( Save ()));
QObject :: connect ( btnClear , SIGNAL ( clicked ()), this , SLOT ( Clear ()));
//添加一个平行布局
QHBoxLayout * hLay = new QHBoxLayout ;
hLay -> addWidget ( btnSave );
hLay -> addWidget ( btnClear );
lay -> addRow ( hLay );
this -> setLayout ( lay );
}
void luoqt :: SetStyle ( const QString & styleName )
{
QFile file ( QString ( "./image/%1.qss" ). arg ( styleName ));
bool b = file . open ( QFile :: ReadOnly );
QString qss = QLatin1String ( file . readAll ());
qApp -> setStyleSheet ( qss );
qApp -> setPalette ( QPalette ( QColor ( "#F0F0F0" )));
}
void luoqt :: Save ()
{
//扎到layout
QFormLayout * lay = ( QFormLayout * ) this -> layout ();
//找到显示错误信息的Label
QLabel * label = ( QLabel * ) lay -> itemAt ( 0 , QFormLayout :: FieldRole ) -> widget ();
//存放错误信息
QString qstrErr = "" ;
//遍历FormLayout的所有元素
for ( int i = 0 ; i < lay -> rowCount (); i ++ )
{
//Label
QLayoutItem * LabelItem = lay -> itemAt ( i , QFormLayout :: LabelRole );
if ( ! LabelItem )
{
continue ;
}
QLabel * titleLabel = ( QLabel * ) LabelItem -> widget ();
if ( ! titleLabel )
{
continue ;
}
//Field
QLayoutItem * fieldItem = lay -> itemAt ( i , QFormLayout :: FieldRole );
QLineEdit * pWidget = ( QLineEdit * ) fieldItem -> widget ();
if ( ! pWidget )
{
continue ;
}
QString qstrName = pWidget -> metaObject () -> className ();
if ( qstrName == "QLineEdit" )
{
if ( pWidget -> text (). trimmed () == "" )
{
pWidget -> setFocus ();
qstrErr += titleLabel -> text ();
qstrErr += "is Empty \n " ;
}
}
}
label -> setText ( qstrErr );
}
void luoqt :: Clear ()
{
//扎到layout
QFormLayout * lay = ( QFormLayout * ) this -> layout ();
//遍历所有LineEdit
//遍历FormLayout的所有元素
for ( int i = 0 ; i < lay -> rowCount (); i ++ )
{
QLayoutItem * fieldItem = lay -> itemAt ( i , QFormLayout :: FieldRole );
QLineEdit * pWidget = ( QLineEdit * ) fieldItem -> widget ();
if ( ! pWidget )
{
continue ;
}
QString qstrName = pWidget -> metaObject () -> className ();
if ( qstrName == "QLineEdit" )
{
pWidget -> setText ( "" );
}
}
}
main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "luoqt.h"
#include <QtWidgets/QApplication>
int main ( int argc , char * argv [])
{
QApplication a ( argc , argv );
//设置全局字体
QFont f ( "Yahei Mono" , 12 );
a . setFont ( f );
luoqt w ;
w . show ();
return a . exec ();
}
QCheckBox
默认多选.
常用函数:
1
2
3
4
5
6
7
8
9
//文本获取与设置
QString text () const ;
void setText ( const QString & text );
//状态获取与设置
bool isChecked () const ;
void setChecked ( bool );
//设置自动排他,单选属性
//若同Widget上的两个QCheckBox设置该属性,则每次只能选择其中一个
void setAutoExclusive ( bool );
事件信号:
1
2
void QAbstractButton :: clicked ( bool checked = false ); //按钮点击,就会触发该信号
void QAbstractButton :: toggled ( bool checked ); //状态发生变化,就会触发该信号
将一组按钮放在ButtonGroup上,点击时,可以知道哪个按钮被点击了.
常用信号:
1
2
3
4
5
6
7
8
void buttonClicked ( QAbstractButton * button );
void buttonClicked ( int id );
void buttonPressed ( QAbstractButton * button );
void buttonPressed ( int id );
void buttonReleased ( QAbstractButton * button );
void buttonReleased ( int id );
void buttonToggled ( QAbstractButton * button , bool checked );
void buttonToggled ( int id , bool checked );
示例:
luoqt.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <QCheckBox>
#include <QButtonGroup>
class luoqt : public QWidget
{
Q_OBJECT
public :
luoqt ( QWidget * parent = Q_NULLPTR );
public slots :
void LuoClicked ( QAbstractButton * button );
void LuoToggled ( QAbstractButton * button , bool checked );
private :
Ui :: luoqtClass ui ;
};
luoqt.cpp:
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
#include "luoqt.h"
luoqt :: luoqt ( QWidget * parent )
: QWidget ( parent )
{
ui . setupUi ( this );
QButtonGroup * btnGroup = new QButtonGroup ( this );
//加组后,默认变为单选
btnGroup -> addButton ( ui . checkBox1 );
btnGroup -> addButton ( ui . checkBox2 );
btnGroup -> addButton ( ui . checkBox3 );
//改为多选
btnGroup -> setExclusive ( false );
//信号槽绑定
QObject :: connect ( btnGroup , SIGNAL ( buttonClicked ( QAbstractButton * )), this , SLOT ( LuoClicked ( QAbstractButton * )));
QObject :: connect ( btnGroup , SIGNAL ( buttonToggled ( QAbstractButton * , bool )), this , SLOT ( LuoToggled ( QAbstractButton * , bool )));
}
void luoqt :: LuoClicked ( QAbstractButton * button )
{
qDebug () << "LuoClicked:" << button -> text () << button -> isChecked ();
}
void luoqt :: LuoToggled ( QAbstractButton * button , bool checked )
{
qDebug () << "LuoToggled:" << button -> text () << button -> isChecked ();
}
类似QCheckBox, 默认单选
示例:
luoqt.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <QMessageBox>
#include <QPushButton>
#include <QRadioButton>
#include <QVBoxLayout>
#include <QButtonGroup>
class luoqt : public QWidget
{
Q_OBJECT
public :
luoqt ( QWidget * parent = Q_NULLPTR );
public slots :
void LuoSave ();
private :
Ui :: luoqtClass ui ;
};
luoqt.cpp:
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
#include "luoqt.h"
luoqt :: luoqt ( QWidget * parent )
: QWidget ( parent )
{
ui . setupUi ( this );
//单选按钮
QRadioButton * btnRadio1 = new QRadioButton ( "btnRadio1" );
QRadioButton * btnRadio2 = new QRadioButton ( "btnRadio2" );
QRadioButton * btnRadio3 = new QRadioButton ( "btnRadio3" );
//按钮组
QButtonGroup * btnGroup = new QButtonGroup ( this );
btnGroup -> setObjectName ( "btnGroup" ); //这里设置ObjectName, 方便下面查找
btnGroup -> addButton ( btnRadio1 );
btnGroup -> addButton ( btnRadio2 );
btnGroup -> addButton ( btnRadio3 );
//垂直布局
QVBoxLayout * layVbox = new QVBoxLayout ( this );
//遍历QButtonGroup
for ( int i = 0 ; i < btnGroup -> buttons (). size (); i ++ )
{
layVbox -> addWidget ( btnGroup -> buttons ()[ i ]);
}
//保存按钮
QPushButton * btnSave = new QPushButton ( "Save" );
layVbox -> addWidget ( btnSave );
QObject :: connect ( btnSave , SIGNAL ( clicked ()), this , SLOT ( LuoSave ()));
}
void luoqt :: LuoSave ()
{
//获取btnGroup
QButtonGroup * btnGroup = this -> findChild < QButtonGroup *> ( "btnGroup" );
if ( ! btnGroup )
{
return ;
}
//获取被选中的按钮
QRadioButton * btnSelRadio = ( QRadioButton * ) btnGroup -> checkedButton ();
if ( ! btnSelRadio )
{
QMessageBox :: warning ( this , "" , "Please checked!" );
}
else
{
QMessageBox :: information ( this , "" , btnSelRadio -> text ());
}
}
QComboBox
常用函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//新增数据
void addItem ( const QString & text , const QVariant & userData = QVariant ());
void addItem ( const QIcon & icon , const QString & text , const QVariant & userData = QVariant ());
void addItems ( const QStringList & texts );
//插入数据
void insertItem ( int index , const QString & text , const QVariant & userData = QVariant ());
void insertItem ( int index , const QIcon & icon , const QString & text , const QVariant & userData = QVariant ());
void insertItems ( int index , const QStringList & list );
//QVariant 用户自定义数据
//获取当前下标
int currentIndex () const
//获取当前文本
QString currentText () const
//删除数据
void removeItem ( int index );
void clearEditText (); //可编辑模式时,清空
void clear ();
事件信号:
1
2
3
4
5
6
7
8
9
10
11
//用户选中
void activated ( int index );
void activated ( const QString & text );
//状态发生变化
void currentIndexChanged ( int index );
void currentTextChanged ( const QString & text );
//只读模式没有
void editTextChanged ( const QString & text );
//选择下拉框,滑过,高亮某行时,就会触发该信号
void highlighted ( int index )
void highlighted ( const QString & text )
示例:
luoqt.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <QIcon>
#include <QComboBox>
class luoqt : public QWidget
{
Q_OBJECT
public :
luoqt ( QWidget * parent = Q_NULLPTR );
public slots :
void LuoClick ();
private :
Ui :: luoqtClass ui ;
};
luoqt.cpp:
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
#include "luoqt.h"
struct LuoType
{
int x ;
int y ;
};
//使Qt支持此类型
Q_DECLARE_METATYPE ( LuoType )
luoqt :: luoqt ( QWidget * parent )
: QWidget ( parent )
{
ui . setupUi ( this );
ui . comboBox -> clear ();
//添加用户自定义数据
LuoType luoType ;
luoType . x = 100 ;
QVariant var ;
var . setValue ( luoType );
ui . comboBox -> addItem ( "001" , var );
QIcon icon ( ":/luoqt/kenan.png" );
ui . comboBox -> addItem ( icon , "002" );
ui . comboBox -> insertItem ( 1 , "003" );
}
void luoqt :: LuoClick ()
{
//获取当前行下标
qDebug () << ui . comboBox -> currentIndex ();;
//打印第0行的自定义数据
qDebug () << ui . comboBox -> itemText ( 0 );
QVariant var = ui . comboBox -> itemData ( 0 );
qDebug () << var . value < LuoType > (). x ;
}
QSlider
属性:
1
2
3
4
5
6
7
8
9
setRange ( int min , int max );
//键盘,方向键控制
void setSingleStep ( int );
//鼠标, 这里通过鼠标点击,并不是点到哪里,就拖动到哪里
void setPageStep ( int );
//方向
void setOrientation ( Qt :: Orientation );
//Qt::Horizontal
//Qt::Vertical
事件信号:
1
2
3
4
void sliderMoved ( int value ); //拖动
void sliderPressed (); //点击滑块
void sliderReleased (); //松开滑块
void valueChanged ( int value ); //点击或者设置
重载鼠标事件:
实现鼠标点击到哪里,滑块就滑动到哪里.
新建一个类LuoSlider,继承QSlider,重载mousePressEvent
LuoSlider.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <QSlider>
#include <QWidget>
#include <QMouseEvent>
#include <QDebug>
class LuoSlider : public QSlider
{
public :
LuoSlider ( QWidget * p = NULL );
~ LuoSlider ();
public :
virtual void mousePressEvent ( QMouseEvent * e );
};
LuoSlider.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "LuoSlider.h"
LuoSlider :: LuoSlider ( QWidget * p /*= NULL*/ ) : QSlider ( p )
{
}
LuoSlider ::~ LuoSlider ()
{
}
void LuoSlider :: mousePressEvent ( QMouseEvent * e )
{
double dbl = ( double ) e -> pos (). x () / ( double ) width ();
int nVal = dbl * ( maximum () - minimum ()) + minimum ();
setValue ( nVal );
QSlider :: mousePressEvent ( e );
qDebug () << e -> pos (). x ();
}
将新建的类LuoSlider与界面上的QSlider关联
属性:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//单选,多选
QAbstractItemView :: SelectionMode selectionMode () const ;
void setSelectionMode ( QAbstractItemView :: SelectionMode mode );
enum SelectionMode {
NoSelection ,
SingleSelection , //单选
MultiSelection , //多选
ExtendedSelection , //Ctrl + 鼠标 多选, Shift + 鼠标 连续选
ContiguousSelection //Ctrl + 鼠标 以及 Shift + 鼠标 都是连续选
};
//从上到下或从左到右排列
flow
//每一行的行高
gridSize
//图标的宽高
iconSize
常用函数:
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
//新增数据
void addItem ( const QString & label );
void addItem ( QListWidgetItem * item );
void addItems ( const QStringList & labels );
//添加数据
void insertItem ( int row , QListWidgetItem * item );
void insertItem ( int row , const QString & label );
void insertItems ( int row , const QStringList & labels );
//获取ListWidget, item个数
int count () const ;
//获取当前行数据
QListWidgetItem * currentItem () const ;
int currentRow () const ;
//设置列表控件的编辑策略
void setEditTriggers ( QAbstractItemView :: EditTriggers triggers );
enum EditTrigger {
NoEditTriggers = 0 ,
CurrentChanged = 1 ,
DoubleClicked = 2 ,
SelectedClicked = 4 ,
EditKeyPressed = 8 ,
AnyKeyPressed = 16 ,
AllEditTriggers = 31
};
//排序
void sortItems ( Qt :: SortOrder order = Qt :: AscendingOrder );
//将列表控件的某一项,设置为控件
void setItemWidget ( QListWidgetItem * item , QWidget * widget )
//Public Slots
void clear ();
事件信号:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//鼠标键盘选中
void currentItemChanged ( QListWidgetItem * current , QListWidgetItem * previous );
void currentRowChanged ( int currentRow );
void currentTextChanged ( const QString & currentText );
//激活, 双击
//可编辑状态下,双击不会触发该信号
void itemActivated ( QListWidgetItem * item );
//列表内容改变
//通过代码修改或者手动修改列表项显示的文字,会触发该信号
//通过代码新增列表数据,该信号并不会触发
void itemChanged ( QListWidgetItem * item );
//鼠标左键松开
void itemClicked ( QListWidgetItem * item );
//鼠标左键或右键双击
void itemDoubleClicked ( QListWidgetItem * item );
//在设置鼠标跟踪后,鼠标移上去,才会触发该信号
//setMouseTracking(true);
void itemEntered ( QListWidgetItem * item );
//鼠标左键或右键按下
void itemPressed ( QListWidgetItem * item );
//选择改变
void itemSelectionChanged ();
示例:
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
#include <QListWidget>
#include <QIcon>
#include <QLineEdit>
luoqt :: luoqt ( QWidget * parent )
: QWidget ( parent )
{
ui . setupUi ( this );
//清空数据
ui . listWidget -> clear ();
//插入数据方式一
QListWidgetItem * item1 = new QListWidgetItem ;
item1 -> setText ( "item1" );
ui . listWidget -> addItem ( item1 );
//插入数据方式二
new QListWidgetItem ( "item2" , ui . listWidget );
//插入数据方式三
ui . listWidget -> addItem ( "item3" );
//插入包含图标的数据
QListWidgetItem * item4 = new QListWidgetItem ;
item4 -> setText ( "item4" );
item4 -> setIcon ( QIcon ( ":/luoqt/kenan.png" ));
ui . listWidget -> addItem ( item4 );
//插入其他控件, 如LineEdit
QListWidgetItem * item5 = new QListWidgetItem ( "12" , ui . listWidget );
QLineEdit * edtLine = new QLineEdit ( "item5 LineEdit" );
ui . listWidget -> setItemWidget ( item5 , edtLine );
//设置鼠标跟踪
//ui.listWidget->setMouseTracking(true);
//设置编辑策略, 双击启用编辑状态
ui . listWidget -> setEditTriggers ( QAbstractItemView :: DoubleClicked );
//遍历listWidget中的每个item,设置属性
for ( int i = 0 ; i < ui . listWidget -> count (); i ++ )
{
ui . listWidget -> item ( i ) -> setFlags ( Qt :: ItemIsEditable | Qt :: ItemIsSelectable | Qt :: ItemIsEnabled );
}
//设置排序, 升序
ui . listWidget -> sortItems ( Qt :: AscendingOrder );
}
属性:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//标题显示(上方、左侧)
horizontalHeader () verticalHeader ()
//滚动条显示
setVerticalScrollBarPolicy
//选择模式,跟QListWidget一样
selectionMode
//选择行、列、一项
//常用的是行选择
setSelectionBehavior
//左上角全选按钮 标题上方和左侧都显示的时候,可以看到这个按钮
setCornerButtonEnabled
//网格显示
setShowGrid setGridStyle
//排序按钮
setSortingEnabled
事件信号:
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
//在设置鼠标跟踪后,鼠标移上去,才会触发该信号,自定义widget不一定有效(Bug)
//setMouseTracking(true);
void cellEntered ( int row , int column );
void cellChanged ( int row , int column );
void cellClicked ( int row , int column );
void cellDoubleClicked ( int row , int column );
//仅 QTableWidgetItem 可触发下述信号
//在设置鼠标跟踪后,鼠标移上去,才会触发该信号,自定义widget无效
//setMouseTracking(true);
void itemEntered ( QTableWidgetItem * item );
void itemChanged ( QTableWidgetItem * item );
void itemClicked ( QTableWidgetItem * item );
void itemDoubleClicked ( QTableWidgetItem * item );
//标题栏点击信号
//QTableWidget标题栏的类型为QHeaderView
//可在QT手册中查看QHeaderView的信号事件
void sectionClicked ( int logicalIndex );
//代码进行绑定
QObject :: connect ( ui . tableWidget -> horizontalHeader (),
SIGNAL ( sectionClicked ( int )),
this ,
SLOT ( SectionClicked ( int )));
清空内容:
1
2
3
4
5
6
7
8
9
10
#include <QTableWidget>
#include <QDebug>
#include <QIcon>
#include <QLabel>
#include <QPixmap>
#include <set>
#include <QMessageBox>
ui . tableWidget -> setColumnCount ( 0 );
ui . tableWidget -> setRowCount ( 0 );
插入标题:
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
class LuoHeader : public QTableWidgetItem
{
public :
LuoHeader :: LuoHeader ( QString qstr ) : QTableWidgetItem ( qstr )
{
}
LuoHeader ::~ LuoHeader ()
{
qDebug () << this -> text () << "removed" ;
}
};
//插入列标题
ui . tableWidget -> setColumnCount ( 5 );
//方式1
ui . tableWidget -> setHorizontalHeaderItem ( 0 , new QTableWidgetItem ( "Col1" ));
//方式2
ui . tableWidget -> setHorizontalHeaderItem ( 1 , new QTableWidgetItem );
ui . tableWidget -> horizontalHeaderItem ( 1 ) -> setText ( "Col2" );
//方式3
ui . tableWidget -> setHorizontalHeaderItem ( 2 , new LuoHeader ( "C3" ));
//在同样的位置插入标题,会清理之前的对象,一会查看控制台,就会发现LuoHeader的析构函数会被调用
ui . tableWidget -> setHorizontalHeaderItem ( 2 , new LuoHeader ( "Col2" ));
//设置标题列的宽度
ui . tableWidget -> setColumnWidth ( 0 , 200 );
//插入行标题
ui . tableWidget -> setRowCount ( 3 );
//设置方式跟上面一样, 只不过要将Horizontal换成Vertical
//这里展示一种不一样的玩法
QStringList qstrList = { "Row1" , "Row2" , "Row3" };
ui . tableWidget -> setVerticalHeaderLabels ( qstrList );
插入数据:
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
int nRow = 0 ;
int nCol = 0 ;
//上面设置了 3行5列
//在0行0列、0行1列、0行2列添加内容
ui . tableWidget -> setItem ( 0 , 0 , new QTableWidgetItem ( "Item 0, 0" ));
ui . tableWidget -> setItem ( 0 , 1 , new QTableWidgetItem ( "Item 0, 1" ));
ui . tableWidget -> setItem ( 0 , 2 , new QTableWidgetItem ( "Item 0, 2" ));
//结尾添加一行
nRow = ui . tableWidget -> rowCount ();
ui . tableWidget -> insertRow ( nRow );
ui . tableWidget -> setItem ( nRow , 0 , new QTableWidgetItem ( "ItemEnd" ));
//开始添加一行
ui . tableWidget -> insertRow ( 0 );
ui . tableWidget -> setItem ( 0 , 0 , new QTableWidgetItem ( "ItemBegin" ));
//插入QIcon图片
nRow = 0 ;
nCol = 1 ;
ui . tableWidget -> setItem ( nRow , nCol , new QTableWidgetItem );
ui . tableWidget -> item ( nRow , nCol ) -> setIcon ( QIcon ( ":/luoqt/kenan.png" ));
//设置行高
ui . tableWidget -> setRowHeight ( nRow , 80 );
//设置图标显示大小
ui . tableWidget -> setIconSize ( QSize ( ui . tableWidget -> rowHeight ( nRow ), ui . tableWidget -> rowHeight ( nRow )));
//插入Widget图片
nRow = 2 ;
nCol = 0 ;
QLabel * qLabel = new QLabel ;
QPixmap qPix ( ":/luoqt/kenan.png" );
//缩放到和表格单元的宽高一致
qPix = qPix . scaled ( ui . tableWidget -> columnWidth ( nCol ), ui . tableWidget -> rowHeight ( nRow ));
qLabel -> setPixmap ( qPix );
ui . tableWidget -> setCellWidget ( nRow , nCol , qLabel );
//插入空数据
ui . tableWidget -> insertRow ( 0 );
ui . tableWidget -> insertRow ( 0 );
//设置每次选择以行为单位
ui . tableWidget -> setSelectionBehavior ( QAbstractItemView :: SelectRows );
获取选中数据:
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
//方式一
//这种方式,无法选择空行
qDebug () << QStringLiteral ( "方式一--------------------------------" );
QList < QTableWidgetItem *> qTableItems = ui . tableWidget -> selectedItems ();
for ( int i = 0 ; i < qTableItems . size (); i ++ )
{
qDebug () << qTableItems [ i ] -> row ()
<< ":"
<< qTableItems [ i ] -> column ()
<< " text="
<< qTableItems [ i ] -> text ();
}
//方式2
//这种方式,可以选择空行
qDebug () << QStringLiteral ( "方式二--------------------------------" );
//选择模式器
QItemSelectionModel * qItemSelModel = ui . tableWidget -> selectionModel ();
//获取所有的选择索引
QModelIndexList qModelIndexLst = qItemSelModel -> selectedIndexes ();
//获取所有被选中的行号
std :: set < int > stdRows ;
for ( int i = 0 ; i < qModelIndexLst . size (); i ++ )
{
//重复的插入会失败
stdRows . insert ( qModelIndexLst [ i ]. row ());
}
删除数据:
1
2
3
//Slot
void removeColumn ( int column )
void removeRow ( int row )
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
//给用户提示
QString qstrMsg = QStringLiteral ( "您确认删除:" );
for ( std :: set < int >:: iterator itr = stdRows . begin (); itr != stdRows . end (); itr ++ )
{
QTableWidgetItem * item = ui . tableWidget -> item ( * itr , 0 );
qstrMsg += "[" ;
qstrMsg += QString :: number ( * itr + 1 );
qstrMsg += ":" ;
if ( item )
{
qstrMsg += item -> text ();
}
qstrMsg += "]" ;
}
int nRet = QMessageBox :: information ( this , "" ,
qstrMsg , QStringLiteral ( "确认" ),
QStringLiteral ( "取消" ));
//用户点击了确认按钮, nRet == 0
//用户点击了取消按钮, nRet == 1
if ( nRet == 0 )
{
//删除多行
while ( true )
{
//获取所有的选择索引
QModelIndexList s = qItemSelModel -> selectedIndexes ();
if ( s . size () <= 0 )
{
break ;
}
//每次删除一行
ui . tableWidget -> removeRow ( s [ 0 ]. row ());
}
}
QTableWidget.7z
属性:
1
2
3
4
5
6
7
8
9
10
11
12
13
//标题显示与隐藏
header () -> setVisible ( true )
//排序
setSortingEnabled
//动画
setAnimated
//滚动条显示
setVerticalScrollBarPolicy
serHorizontalScrollBarPolicy
//选择模式,跟QListWidget一样
selectionMode
//选择行、列、一项
setSelectionBehavior
常用函数:
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
//QTreeWidget
//插入顶部节点
void insertTopLevelItem ( int index , QTreeWidgetItem * item );
void insertTopLevelItems ( int index , const QList < QTreeWidgetItem *> & items );
void QTreeWidget :: addTopLevelItem ( QTreeWidgetItem * item );
void QTreeWidget :: addTopLevelItems ( const QList < QTreeWidgetItem *> & items );
//获取顶部节点
QTreeWidgetItem * QTreeWidget :: topLevelItem ( int index ) const ;
//获取顶部节点数量
int topLevelItemCount () const ;
//插入Widget控件
void QTreeWidget :: setItemWidget ( QTreeWidgetItem * item , int column , QWidget * widget );
//获取选中节点
QList < QTreeWidgetItem *> QTreeWidget :: selectedItems () const ;
//设置列数量
void setColumnCount ( int columns );
//QTreeWidgetItem
//插入子节点
void addChild ( QTreeWidgetItem * child );
void addChildren ( const QList < QTreeWidgetItem *> & children );
//设置文本
void setText ( int column , const QString & text );
//获取父节点
QTreeWidgetItem * QTreeWidgetItem :: parent () const ;
//获取treeWidget
QTreeWidget * treeWidget () const ;
槽函数:
1
2
3
4
5
void clear ();
//收缩
void collapseItem ( const QTreeWidgetItem * item );
//展开
void expandItem ( const QTreeWidgetItem * item );
事件信号:
1
2
3
4
5
6
7
8
9
10
void currentItemChanged ( QTreeWidgetItem * current , QTreeWidgetItem * previous );
void itemActivated ( QTreeWidgetItem * item , int column );
void itemChanged ( QTreeWidgetItem * item , int column );
void itemClicked ( QTreeWidgetItem * item , int column );
void itemCollapsed ( QTreeWidgetItem * item );
void itemDoubleClicked ( QTreeWidgetItem * item , int column );
void itemEntered ( QTreeWidgetItem * item , int column );
void itemExpanded ( QTreeWidgetItem * item );
void itemPressed ( QTreeWidgetItem * item , int column );
void itemSelectionChanged ();
清空内容:
1
2
3
4
5
6
7
8
9
#include <QTreeWidget>
#include <QPushButton>
//清理标题,不清理数据
//ui.treeWidget->setColumnCount(0);//设置为0,不会清理
ui . treeWidget -> setHeaderItem ( new QTreeWidgetItem );
//清空数据
ui . treeWidget -> clear ();
插入标题:
1
2
3
4
5
6
//设置4列
QTreeWidgetItem * pTreeHeader = ui . treeWidget -> headerItem ();
pTreeHeader -> setText ( 0 , "head1" );
pTreeHeader -> setText ( 1 , "head2" );
pTreeHeader -> setText ( 2 , "head3" );
pTreeHeader -> setText ( 3 , "head4" );
插入数据:
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
//顶部节点插入
//在结尾处插入
//方式一
ui . treeWidget -> addTopLevelItem ( new QTreeWidgetItem ());
ui . treeWidget -> topLevelItem ( 0 ) -> setText ( 0 , "tree node1" );
ui . treeWidget -> topLevelItem ( 0 ) -> setText ( 1 , "tree node2" );
//方式二
ui . treeWidget -> addTopLevelItem ( new QTreeWidgetItem ({ "tree node11" , "tree node22" }));
//在指定位置插入
ui . treeWidget -> insertTopLevelItem ( 0 , new QTreeWidgetItem ({ "tree node1-1" , "tree node2-2" }));
//在结尾插入
ui . treeWidget -> insertTopLevelItem ( ui . treeWidget -> topLevelItemCount (), new QTreeWidgetItem ({ "tree node End" }));
//子节点插入
//方式一
ui . treeWidget -> topLevelItem ( 0 ) -> addChild ( new QTreeWidgetItem ({ "child1" , "child2" , "child3" }));
/ ui . treeWidget -> topLevelItem ( 1 ) -> addChild ( new QTreeWidgetItem ({ "child11" }));
//方式二
QTreeWidgetItem * pTreeItem = ui . treeWidget -> topLevelItem ( 1 );
ui . treeWidget -> addTopLevelItem ( new QTreeWidgetItem ( pTreeItem , { "child110012" }));
//插入图标
ui . treeWidget -> setIconSize ( QSize ( 60 , 60 ));
ui . treeWidget -> topLevelItem ( 0 ) -> setIcon ( 0 , QIcon ( ":/luoqt/ke nan.png" ));
//插入Widget控件
QPushButton * btn = new QPushButton ( "test" );
ui . treeWidget -> setItemWidget ( ui . treeWidget -> topLevelItem ( 1 ), 0 , btn );
QDialog
常用函数:
1
2
//拿Dialog的返回值,与exec的返回值一样
int QDialog :: result () const ;
槽函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
//默认显示的是非模态对话框.
//可在show前调用setModal(true),或者setWindowModality(Qt::ApplicationModal),将其设置为模态对话框.
void QWidget :: show ();
//阻塞,有返回值, 显示的是模态对话框.
virtual int exec ();
//可将一个按钮的点击信号与下述槽函数绑定
//exec的返回值为 QDialog::Accepted
virtual void accept ();
//exec的返回值为 QDialog::Rejected
virtual void reject ();
//可在与按钮点击信号绑定的槽函数中调用,这样就可以自定义exec的返回值为 r
virtual void done ( int r );
自定义MessageBox:
新建一个Qt类继承QDialog
自定义界面
可以弄一个QLabel控件用来显示要提示的信息,
将确认按钮与QDialog的槽函数accept绑定,
将取消按钮与QDialog的槽函数reject绑定.
QProgressBar应用:
新建一个线程类,模拟做事:
LuoThread.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <QThread>
class LuoThread : public QThread
{
Q_OBJECT
public :
LuoThread ();
~ LuoThread ();
protected :
void run ();
signals :
///0~1000
void SetPos ( int pos );
};
LuoThread.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "luothread.h"
LuoThread :: LuoThread ()
{
}
LuoThread ::~ LuoThread ()
{
}
void LuoThread :: run ()
{
//模拟做事
//这个地方需要设置QProgressBar的范围为0-1000
for ( int i = 0 ; i <= 1000 ; i ++ )
{
SetPos ( i );
msleep ( 5 );
}
}
新建一个对话框类,显示进度:
LuoProgressDialog.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <QDialog>
#include <QThread>
#include "ui_LuoProgressDialog.h"
class LuoProgressDialog : public QDialog
{
Q_OBJECT
public :
LuoProgressDialog ( QWidget * parent = Q_NULLPTR );
~ LuoProgressDialog ();
public slots :
//0~1000
void SetPos ( int pos );
private :
Ui :: LuoProgressDialog ui ;
};
LuoProgressDialog.cpp:
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
#include "LuoProgressDialog.h"
LuoProgressDialog :: LuoProgressDialog ( QWidget * parent )
: QDialog ( parent )
{
ui . setupUi ( this );
//为了实现圆角效果,在QDialog上面放一个QWidget控件
//在QWidget控件上面放一个QProgressBar控件
//去掉标题栏
this -> setWindowFlags ( Qt :: FramelessWindowHint );
//设置背景透明
this -> setAttribute ( Qt :: WA_TranslucentBackground , true );
}
LuoProgressDialog ::~ LuoProgressDialog ()
{
}
void LuoProgressDialog :: SetPos ( int pos )
{
ui . progressBar -> setValue ( pos );
if ( pos == 1000 )
{
for ( int i = 100 ; i > 0 ; i -- )
{
//透明度 1.0 0.0
this -> setWindowOpacity (( float ) i / 100.0 );
QThread :: msleep ( 10 );
//界面上有一个QLabel控件
//这个地方的setText只是发出信号,需要等待槽函数进行处理
//LuoProgressDialog::SetPos(int pos)这个槽函数不退出,setText的槽函数是不会处理的
ui . label -> setText ( QString :: number ( i ));
//这一步会将消息队列中的消息都处理下,会立即调用槽函数
QEventLoop loop ;
loop . processEvents ();
}
this -> close ();
}
}
为了实现圆角效果,需要设置QWidget的样式为:
1
2
3
4
5
# widget {
background-color : qlineargradient ( spread : reflect , x1 : 0.999896 , y1 : 0.494136 , x2 : 1 , y2 : 1 , stop : 0 rgba ( 0 , 0 , 0 , 255 ), stop : 1 rgba ( 255 , 255 , 255 , 255 ));
border : 1 px groove rgb ( 232 , 232 , 232 );
border-radius : 20 ;
}
Main中调用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "luothread.h"
#include "LuoProgressDialog.h"
int main ( int argc , char * argv [])
{
QApplication a ( argc , argv );
//进度条
LuoProgressDialog luoPro ;
//线程
LuoThread luoThread ;
//信号槽绑定
QObject :: connect ( & luoThread , SIGNAL ( SetPos ( int )), & luoPro , SLOT ( SetPos ( int )));
//启动线程
luoThread . start ();
//显示对话框
luoPro . exec ();
return a . exec ();
}
QDialog.7z
Qt菜单
Widget创建菜单:
添加菜单
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
LuoWidget :: LuoWidget ( QWidget * parent )
: QWidget ( parent )
{
ui . setupUi ( this );
//插入菜单栏
QMenuBar * m = new QMenuBar ( this );
//设置菜单栏大小
m -> resize ( width (), m -> height ());
//一级菜单
QMenu * m1 = m -> addMenu ( QStringLiteral ( "菜单1" ));
//二级菜单
QAction * a1 = m1 -> addAction ( QStringLiteral ( "二级菜单1.1" ));
QAction * a2 = m1 -> addAction ( QStringLiteral ( "二级菜单1.2" ));
QAction * a3 = m1 -> addAction ( QStringLiteral ( "二级菜单1.3" ));
//设置图标
a3 -> setIcon ( QIcon ( ":/LuoMenu/ke nan.png" ));
//三级菜单
QMenu * m14 = m1 -> addMenu ( QStringLiteral ( "二级菜单1.4" ));
m14 -> addAction ( QStringLiteral ( "三级菜单1.4.1" ));
//设置图标
m14 -> setIcon ( QIcon ( ":/LuoMenu/ke nan.png" ));
//一级菜单
QMenu * m2 = m -> addMenu ( QStringLiteral ( "菜单2" ));
QMenu * m3 = m -> addMenu ( QStringLiteral ( "菜单3" ));
}
事件信号
1
2
3
4
5
6
7
8
9
10
11
12
13
//QMenuBar
void hovered ( QAction * action );
void triggered ( QAction * action );
//QMenu
void hovered ( QAction * action );
void triggered ( QAction * action );
//QAction
void changed ();
void hovered ();
void toggled ( bool checked );
void triggered ( bool checked = false );
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
//槽函数
public slots :
void Hover ()
{
qDebug () << "Hover" ;
}
void Action1 ()
{
qDebug () << "Action1" ;
}
void Action ( QAction * act )
{
qDebug () << "Action " << act -> text ();
}
//进行绑定
//一级菜单
m1 = m -> addMenu ( QStringLiteral ( "菜单1" ));
//QMenu所有子节点(子节点的子节点)点击后,都会触发该信号
connect ( m1 , SIGNAL ( triggered ( QAction * )), this , SLOT ( Action ( QAction * )));
//二级菜单
QAction * a1 = m1 -> addAction ( QStringLiteral ( "二级菜单1.1" ));
//QAction 触发信号
connect ( a1 , SIGNAL ( triggered ()), this , SLOT ( Action1 ()));
QAction * a2 = m1 -> addAction ( QStringLiteral ( "二级菜单1.2" ));
//QAction 鼠标悬停信号
connect ( a2 , SIGNAL ( hovered ()), this , SLOT ( Hover ()));
动态产生菜单
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//槽函数
void Hovered ( QAction * act )
{
//动态菜单
if ( act -> text () == QStringLiteral ( "菜单3" ))
{
act -> menu () -> clear ();
act -> menu () -> addAction ( QStringLiteral ( "菜单3.1" ));
act -> menu () -> addAction ( QStringLiteral ( "菜单3.2" ));
act -> menu () -> addAction ( QStringLiteral ( "菜单3.3" ));
}
}
//信号槽绑定
//插入菜单栏
QMenuBar * m = new QMenuBar ( this );
//悬停,动态菜单生成
connect ( m , SIGNAL ( hovered ( QAction * )), this , SLOT ( Hovered ( QAction * )));
菜单单选和多选
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
//槽函数
void Action1 ( bool b )
{
qDebug () << "Action1 " << b ;
}
//二级菜单
QAction * a1 = m1 -> addAction ( QStringLiteral ( "二级菜单1.1" ));
QAction * a2 = m1 -> addAction ( QStringLiteral ( "二级菜单1.2" ));
QAction * a3 = m1 -> addAction ( QStringLiteral ( "二级菜单1.3" ));
//设置可选
a1 -> setCheckable ( true );
a2 -> setCheckable ( true );
a3 -> setCheckable ( true );
//添加到组
QActionGroup * ag = new QActionGroup ( this );
ag -> addAction ( a2 );
ag -> addAction ( a3 );
//单选
ag -> setExclusive ( true );
//是否选中
connect ( a1 , SIGNAL ( triggered ( bool )), this , SLOT ( Action1 ( bool )));
//添加快捷键
a1 -> setShortcut ( QString ( "A" ));
按钮菜单
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//准备一个按钮,响应点击事件
//按钮点击事件
void Click ()
{
//鼠标位置显示菜单
//m1的类型是QMenu
m1 -> exec ( QCursor :: pos ());
}
QMenuBar * m = new QMenuBar ( this );
//设置菜单栏大小
m -> resize ( width (), m -> height ());
//一级菜单
m1 = m -> addMenu ( QStringLiteral ( "菜单1" ));
//二级菜单
QAction * a1 = m1 -> addAction ( QStringLiteral ( "二级菜单1.1" ));
QAction * a2 = m1 -> addAction ( QStringLiteral ( "二级菜单1.2" ));
QAction * a3 = m1 -> addAction ( QStringLiteral ( "二级菜单1.3" ));
//三级菜单
QMenu * m14 = m1 -> addMenu ( QStringLiteral ( "二级菜单1.4" ));
m14 -> addAction ( QStringLiteral ( "三级菜单1.4.1" ));
点击按钮的时候,就会弹出菜单.
工具栏
1
2
3
4
5
6
#include <QToolBar>
QToolBar * tBar = new QToolBar ( this );
tBar -> setGeometry ( 0 , m -> height (), width (), 30 );
tBar -> setIconSize ( QSize ( 30 , 30 ));
tBar -> addAction ( a1 );
状态栏
1
2
3
4
5
#include <QStatusBar>
QStatusBar * sBar = new QStatusBar ( this );
sBar -> setGeometry ( 0 , height () - 30 , width (), 30 );
sBar -> showMessage ( QStringLiteral ( "测试消息3秒消失!" ), 3000 );
QMainWindow:
QMainWindow继承QWidget,封装了很多操作.
1
2
3
4
5
6
7
QMainWindow
│
├─ QMenuBar
├ └─ QMenu
├ └─ QAction
├─ QToolBar
└─ QStatusBar
菜单栏:
1
2
3
4
5
6
7
8
9
10
11
12
13
//一级菜单
QMenu * m1 = this -> menuBar () -> addMenu ( QStringLiteral ( "菜单1" ));
//二级菜单
QAction * a11 = m1 -> addAction ( QStringLiteral ( "菜单1.1" ));
QAction * a12 = m1 -> addAction ( QStringLiteral ( "菜单1.2" ));
QAction * a13 = m1 -> addAction ( QStringLiteral ( "菜单1.3" ));
//添加图标
a12 -> setIcon ( QIcon ( ":/LuoMenu/ke nan.png" ));
//一级菜单
QMenu * m2 = this -> menuBar () -> addMenu ( QStringLiteral ( "菜单2" ));
QMenu * m3 = this -> menuBar () -> addMenu ( QStringLiteral ( "菜单3" ));
工具栏:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ui . mainToolBar -> addAction ( a11 );
ui . mainToolBar -> addAction ( a12 );
ui . mainToolBar -> addAction ( a13 );
//设置ToolBar样式, 文件名显示在图标下面
ui . mainToolBar -> setToolButtonStyle ( Qt :: ToolButtonTextUnderIcon );
//工具栏换行
this -> addToolBarBreak ();
//默认顶部插入工具栏
//可调用下面的重载函数,调整插入位置
//void addToolBar(Qt::ToolBarArea area, QToolBar * toolbar)
QToolBar * tBar2 = this -> addToolBar ( "toolBar2" );
tBar2 -> addAction ( QStringLiteral ( "顶部" ));
状态栏:
1
this -> statusBar () -> showMessage ( "Status Bar" );
Qt菜单.7z
Qt事件
重载Qt事件有2种方式:
重载event这个虚函数,在里面判断event的类型,
重载各自的事件虚函数(如 keyPressEvent).
QEvent
重载事件:
1
virtual bool event ( QEvent * event ) override ;
示例:
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//声明
public :
//重载event
bool event ( QEvent * ev );
//实现
bool LuoEvent :: event ( QEvent * ev )
{
switch ( ev -> type ())
{
case QEvent :: KeyPress : {
//键盘事件
//推荐重载keyPressEvent或keyReleaseEvent
QKeyEvent * keyEv = ( QKeyEvent * ) ev ;
//判断是否是自动触发的
if ( ! keyEv -> isAutoRepeat ())
{
//这个输出的是大写
qDebug () << ( char ) keyEv -> key ();
//这个可以区分大小写
qDebug () << keyEv -> text ();
if ( keyEv -> key () == 'A' )
{
//返回true表示已被处理
return true ;
}
}
}
case QEvent :: MouseButtonPress : {
//鼠标事件
QMouseEvent * me = ( QMouseEvent * ) ev ;
//相对坐标(本地坐标)
qDebug () << "QEvent::MouseButtonPress "
<< QStringLiteral ( "相对坐标 " )
<< me -> x ()
<< me -> y ();
//程序窗口坐标
qDebug () << "QEvent::MouseButtonPress "
<< QStringLiteral ( "程序窗口坐标 " )
<< me -> windowPos (). x ()
<< me -> windowPos (). y ();
//屏幕坐标
qDebug () << "QEvent::MouseButtonPress "
<< QStringLiteral ( "屏幕坐标 " )
<< me -> screenPos (). x ()
<< me -> screenPos (). y ();
//本地坐标转屏幕坐标
QPoint gPos = mapToGlobal ( me -> pos ());
qDebug () << "QEvent::MouseButtonPress "
<< QStringLiteral ( "本地坐标转屏幕坐标 " )
<< gPos . x ()
<< gPos . y ();
//获取鼠标的屏幕坐标
qDebug () << "QCursor" << QCursor :: pos (). x () << QCursor :: pos (). y ();
//鼠标按钮事件
if ( me -> buttons () & Qt :: LeftButton )
{
qDebug () << "LeftButton" ;
}
if ( me -> buttons () & Qt :: RightButton )
{
qDebug () << "RightButton" ;
}
if ( me -> buttons () & Qt :: MiddleButton )
{
qDebug () << "MiddleButton" ;
}
}
case QEvent :: Resize : {
//窗口大小改变事件
QResizeEvent * re = ( QResizeEvent * ) ev ;
qDebug () << "Resize Old " << re -> oldSize ()
<< "Resize New " << re -> size ();
}
default :
break ;
}
return QWidget :: event ( ev );
}
键盘事件
重载事件:
1
2
virtual void keyPressEvent ( QKeyEvent * event );
virtual void keyReleaseEvent ( QKeyEvent * event );
示例:
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
//声明
public :
//键盘事件
void keyPressEvent ( QKeyEvent * ev );
void keyReleaseEvent ( QKeyEvent * ev );
//实现
void LuoEvent :: keyPressEvent ( QKeyEvent * ev )
{
//键盘按下某个按键后,会多次响应
//解决键盘按钮连发现象,判断是否是自动触发的,若是则返回
if ( ev -> isAutoRepeat ())
{
return ;
}
qDebug () << "keyPressEvent " << ev -> key ();
}
void LuoEvent :: keyReleaseEvent ( QKeyEvent * ev )
{
if ( ev -> isAutoRepeat ())
{
return ;
}
qDebug () << "keyReleaseEvent " << ev -> key ();
}
鼠标事件
重载事件:
1
2
3
4
5
6
7
8
9
//鼠标移进来
virtual void enterEvent ( QEvent * event );
//鼠标移出去
virtual void leaveEvent ( QEvent * event );
virtual void mouseDoubleClickEvent ( QMouseEvent * event );
//鼠标移动事件,需要开启鼠标跟踪,setMouseTracking(true)
virtual void mouseMoveEvent ( QMouseEvent * event );
virtual void mousePressEvent ( QMouseEvent * event );
virtual void mouseReleaseEvent ( QMouseEvent * event );
坐标:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//相对坐标(本地坐标)
//相对于Widget的位置
int QMouseEvent :: x () const ;
int QMouseEvent :: y () const ;
//程序窗口坐标
//相对于程序窗口的位置
const QPointF & QMouseEvent :: windowPos () const ;
//屏幕坐标
//相对于屏幕的位置
const QPointF & QMouseEvent :: screenPos () const ;
//本地坐标转屏幕坐标
QPoint mapToGlobal ( const QPoint & pos ) const ;
//获取鼠标的屏幕坐标
[ static ] QPoint QCursor :: pos ();
按键:
1
2
3
4
5
6
7
8
9
10
//获取按键状态,鼠标的哪个键被按下
Qt :: MouseButtons QMouseEvent :: buttons () const ;
enum MouseButton {
NoButton = 0x00000000 ,
LeftButton = 0x00000001 ,
RightButton = 0x00000002 ,
MidButton = 0x00000004 , // ### Qt 6: remove me
MiddleButton = MidButton ,
...
};
窗口大小改变
可重载该事件来解决不同电脑屏幕分辨率不同,而导致的控件显示异常的现象.
重载事件:
1
virtual void resizeEvent ( QResizeEvent * event );
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//声明
public :
//窗口大小改变事件
void resizeEvent ( QResizeEvent * re );
//实现
void LuoEvent :: resizeEvent ( QResizeEvent * re )
{
qDebug () << "resizeEvent" ;
//窗口改变前的大小
//re->oldSize()
//窗口改变后的大小
//re->size()
}
Qt事件.7z
QPainter
重载事件:
1
virtual void paintEvent ( QPaintEvent * event );
绘制文本:
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
//声明
public :
//重载这个虚函数
void paintEvent ( QPaintEvent * event );
//实现
void LuoPaint :: paintEvent ( QPaintEvent * event )
{
//设置绘制设备 (Widget)
QPainter p ( this );
//设置画笔颜色
p . setPen ( QColor ( 255 , 0 , 0 , 200 ));
//设置字体
//p.setFont(QFont(QStringLiteral("黑体"), 30));
//这样设置之后,我们在字体选中控件中选择字体后,界面的绘制的字体没有改变
//我们需要调用update这个槽函数,来刷新界面
QFont font = ui . fontComboBox -> currentFont ();
font . setPixelSize ( 30 );
p . setFont ( font );
//绘制文本
p . drawText ( 100 , 100 , QStringLiteral ( "测试文字" ));
}
注意
我们通过字体选择控件选择字体后,需要调update这个槽函数来刷新界面.
绘制线:
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
//声明
public :
//重载这个虚函数
void paintEvent ( QPaintEvent * event );
//实现
void LuoPaint :: paintEvent ( QPaintEvent * event )
{
//设置绘制设备 (Widget)
QPainter p ( this );
//绘制线
//设置画笔样式
QPen pen ;
//实线
pen . setStyle ( Qt :: SolidLine );
//线粗
pen . setWidth ( 30 );
//线刷子
pen . setBrush ( Qt :: red );
//结尾端样式
pen . setCapStyle ( Qt :: RoundCap );
//连接处样式
pen . setJoinStyle ( Qt :: RoundJoin );
p . setPen ( pen );
QVector < QLine > lines ;
lines . push_back ( QLine ( 0 , 0 , 350 , 350 ));
lines . push_back ( QLine ( 350 , 350 , 0 , 450 ));
lines . push_back ( QLine ( 0 , 450 , 550 , 550 ));
p . drawLines ( lines );
p . end ();
}
Qt配置
VS2019dark.xml
将上述黑色方案放到Qt目录\Tools\QtCreator\share\qtcreator\styles .
在QtCreator中工具->选项->环境->theme,选择dark.
在QtCreator中工具->选项->文本编辑器,选择VS2019.
控制台:
方便调试,看输出信息.
QtCreator:
VS:
VS番茄插件设置:
环境变量:
添加环境变量: Qt_INCLUDEPATH_ = D:\QT\5.12.10\msvc2017_64\include
按上述设置后,可解决某些情况下在VS中写Qt代码不提示,工程标红等现象.
VS工程标红:
右键.ui文件,编译.
右键解决方案,重新扫描解决方案.
Qss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//声明
public slots :
//设置皮肤样式
static void SetStyle ( const QString & styleName );
//实现
void luoQt :: SetStyle ( const QString & styleName )
{
QFile file ( QString ( "./image/%1.qss" ). arg ( styleName ));
bool b = file . open ( QFile :: ReadOnly );
QString qss = QLatin1String ( file . readAll ());
qApp -> setStyleSheet ( qss );
qApp -> setPalette ( QPalette ( QColor ( "#F0F0F0" )));
}
Qss.7z
Qt程序打包
将Qt程序单独放到一个文件夹中,cmd到该文件夹,执行下面的命令.