Qt6.0开发 第四章 常用界面组件的使用
第四章 常用界面组件的使用
在Qt类库中,所有界面组件类的字节或间接父类都是QWidget.
QWidget的父类是QObject与QPaintDevice.所以QWidget是多重继承的类.
QObject支持元对象系统,其信号与槽机制为编程中对象间通信提供了极大便利.
QPaintDevice是能使用QPainter类在绘图设备上绘图的类.
所有从QWidget继承而来的界面组件被称为widget组件,他们是构成GUI应用程序的窗口界面基本元素.
界面组件可以从窗口系统接收鼠标事件,键盘事件和其他事件,然后在屏幕上绘制自己.
常用的界面组件
按钮类组件
按钮类继承关系:
- QAbstractButton:抽象类,提供按钮共有特性
- QPushButton:普通按钮
- QCommandLinkButton:单选按钮,多个互斥项间选择.
- QToolButton:工具按钮
- QRadioButton:单选按钮
- QCheckBox:复选框
- QPushButton:普通按钮
- QDialogButttonBox:复合组件类,可设置为多个按钮组合
输入类组件
输入类组件继承关系:
- QComboBox:下拉列表框,也称组合框
- QFontComboBox:字体下拉列表框,自动从系统获取字体
- QLineEdit:编辑框,用于输入单行文字
- QFrame:基本控件的基类
- QAbstractScrollArea:抽象类
- QTextEdit:文本编辑框,支持富文本格式,包括markdown.
- QPlainTextEdit:纯文本编辑器,支持多段落纯文本.
- QAbstractScrollArea:抽象类
- QAbstractSpinBox:抽象类
- QSpinBox:整数输入框,用于输入整数或离散型数据.
- QDoubleSpinBox:浮点数输入框.
- QDateTimeEdit:允许用户编辑日期与时间
- QDateEdit:日期编辑框
- QTimeEdit:时间编辑框
- QAbstractSlider:抽象类
- QDial:表盘,用于在设定的范围内输入和显示数值.
- QScrollBar:卷滚条,用于在大的显示区域内滑动.
- QSlider:滑动条,具有设定的数值范围.
- QKeySequenceEdit:按键序列编辑器,一般用于处理快捷键
显示类组件
显示类组件继承关系:
- QFrame:基本控件的基类
- QLabel:标签,用于显示文字,图片等
- QAbstractScrollArea:抽象类
- QTextEdit:文本编辑框,支持富文本格式,包括markdown.
- QTextBrowser:文本浏览器,用于显示富文本格式内容
- QGraphicsView:图形视图组件,图形/视图架构中的视图组件
- QTextEdit:文本编辑框,支持富文本格式,包括markdown.
- QLCDNumber:LCD数字显示组件,模仿LCD显示效果的组件
- QCalendarWidget:日历组件,用于显示日历
- QProgressBar:进度条,用于表示某个操作的进度
- QOpenGLWidget:OpenGL显示组件,用于在Qt程序启动OpenGL图形
- QQuickWidget:QML显示组件,用于自动加载QML文件
容器类组件
容器类组件继承关系:
- QGroupBox:分组框,具有标题和边框的容器组件
- QFrame:框架组件,是具有边框的界面组件的父类
- QAbstractScrollArea:抽象类
- QScrollArea:卷滚区域,具有水平和垂直滚动条的容器
- QMdiArea:MDI工作区组件,在MDI应用程序中用于管理多文档窗口
- QToolBox:工具箱,垂直方向的多页容器组件
- QStackedWidget:堆叠多页组件,没有标签栏的多页组件
- QAbstractScrollArea:抽象类
- QTabWidget:带标签栏的多页组件
- QDockWidget:停靠组件,可以停靠在QMainWindow窗口的停靠区域,也可以浮动
- QAxWidget:ActiveX显示组件,用于显示ActiveX控件
Item组件
Item组件继承关系:
- QAbstractItemView
- QListView
- QUndoView
- QListWidget
- QTreeView
- QTreeWidget
- QTableView
- QTableWidget
- QColumnView
- QListView
Item Views组件大多是用于模型/视图结果,每一种视图组件需要相应的一种模型用于存储数据.
Item Widgets组件类是相应Item Views组件类的子类,它们直接使用项(item)存储数据,称为相应视图类的便利类(convenience class)
其他界面类
还有一些界面组件并没有出现在组件面板里,例如常用的菜单栏(QMenuBar类),菜单(QMenu类),工具栏(QToolBar类),状态栏(QStatusBar类)等组件.
QWidget类的主要属性和接口函数
QWidget作为界面组件时的属性
属性名称 | 属性值类型 | 功能 |
---|---|---|
enabled | bool | 组件的使能状态 |
geometry | QRect | 组件的几何形状 |
sizePolicy | QSizePolicy | 组件默认的布局特性 |
minimumSize | QSize | 组件最小尺寸 |
maximumSize | QSize | 组件最大尺寸 |
palette | QPalette | 组件的调色板 |
font | QFont | 组件使用的字体 |
cursor | QCursor | 鼠标光标移到组件上的形状 |
mouseTracking | bool | 组件是否响应鼠标移动 |
tabletTracking | bool | 组件是否响应平板追踪 |
focusPolicy | Qt::FocusPolicy | 组件的焦点策略 |
contextMenuPolicy | Qt::ContextMenuPolicy | 组建的上下文菜单策略 |
acceptDrops | bool | 组件是否接收拖动来的其他对象 |
toolTip | QString | 鼠标移动到组件上时,显示简短提示 |
statusTip | QString | 鼠标移动到组件上时,主窗口状态栏显示提示文字 |
autoFillBackground | bool | 组件背景是否自动填充 |
styleSheet | QString | 组建的样式表 |
组件负责默认布局特性的sizePolicy是QSizePolicy类型,定义了组件在水平和垂直方向的尺寸变化策略.
为了访问组件的sizePolicy,应当通过其Widget内部的sizePolicy()方法访问.
QSizePolicy是一个枚举类型,因而有以下枚举常量:
- QSizePolicy::Fixed:固定尺寸,组件大小不改变
- QSizePolicy::Minimum:最小尺寸,使用sizeHint()的返回值或minimumuSize作为最小尺寸.
- QSizePolicy::Maximum:最大尺寸,使用sizeHint()的返回值或maximumuSize作为最大尺寸.
- QSizePolicy::Preferred:首选尺寸,组件仍然可以调整,但是放大时不会超过sizeHint()返回的尺寸.
- QSizePolicy::Expanding:可扩展尺寸,组件可扩展.
- QSizePolicy::MinimumExpanding:最小可扩展尺寸,综合了可扩展尺寸与最小尺寸.
- QSizePolicy::Ignored:忽略尺寸,sizeHint()函数的返回值被忽略,组件占据尽可能大的空间.
在使用QSizePolicy的时候,QWidget的sizeHint()函数会起到很大作用.
在组件的父组件尺寸发生变化时,sizeHint()返回组件的建议尺寸.
一般不需要修改组件的sizePolicy属性,使用其默认值即可.
部分部件的尺寸策略还进一步细分为水平策略与垂直策略
水平延伸因子与垂直延伸因子都是整数值,其取值范围在0~255.
QWidget作为窗口时的属性
属性 | 属性值类型 | 功能 |
---|---|---|
windowTitle | QString | 窗口标题栏的文字 |
windowIcon | QIcon | 窗口标题上的图表 |
windowOpacity | qreal | 窗口的不透明度(范围0.0~1.0) |
windowFilePath | QString | 窗口相关的含路径文件名 |
windowModified | bool | 显示窗口内文档是否被修改(*) |
windowModality | Qt::WindowModality | 窗口的模态,表示窗口是否在上层 |
windowFlags | Qt::WindowFlags | 窗口的标志,是其一些值的组合 |
QWidget作为独立的窗口时,实际上还有一些与窗口显示有关的共用槽函数.
名称 | 功能 |
---|---|
close() | 关闭窗口 |
hide() | 隐藏窗口 |
show() | 显示窗口 |
showFullScreen() | 以全屏方式显示窗口 |
showMaximized() | 窗口最大化 |
showMinimized() | 窗口最小化 |
showNormal() | 恢复正常窗口 |
布局管理
在Qt Designer的组件面板里有用于布局管理的两组组件,Layouts与Spacers.
QLayout继承自QObject与QLayoutItem.是Layouts中所有组件的基类.QLayout不是从QWidget继承来的.
从QLayout继承而来的几个类是常用的布局管理类:
- QVBoxLayout:垂直布局
- QHBoxLayout:水平布局
- QGridLayout:网格布局,使组件按行与列网格状布局
- QFormLayout:表单布局,与Grid相似,但只有两列
- QStackedLayout:堆叠布局,用于管理多个页面
任何布局类对象在可视化设计时都有layoutLeftMargin,layoutTopMargin,layoutRightMargin和layoutBottomMargin这个4个边距属性用于设置布局组件与父容器的4个边距的最小值.
下面是一个调整边距属性值及layoutSpacing的例子:
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
this->windowTitle().clear();
this->setWindowTitle(QString("this is my window"));
QVBoxLayout* total_layout;
total_layout= new QVBoxLayout;
QGroupBox *btn_group;
btn_group= new QGroupBox(this);
btn_group->setGeometry(QRect(260,310,341,43));
QPushButton* btn_1,*btn_2,*btn_3;
btn_1= new QPushButton("button_1",btn_group);
btn_2= new QPushButton("button_2",btn_group);
btn_3= new QPushButton("button_3",btn_group);
QHBoxLayout* btn_layout;
btn_layout= new QHBoxLayout;
btn_layout->setSpacing(10);
btn_layout->setContentsMargins(15,25,5,5);
btn_layout->addWidget(btn_1);
btn_layout->addWidget(btn_2);
btn_layout->addWidget(btn_3);
total_layout->addLayout(btn_layout);
this->setLayout(total_layout);
}
在上面的例子中,所有的QPushButton都以QGroupBox为父对象.
使用QGroupBox::setGeometry()设置了组件的几何形状.
使用QHBoxLayout::setSpacing()设置了组件间的最小间距.
使用QHBoxLayout::setContentMargins()设置了四个边距的值.
网格布局
可视化设计网格布局时一般是在一个容器组件内先摆放组件,使各组件的位置和大小与期望的效果大致相同,然后点击工具栏上的网格布局按钮进行网格布局.
除了4个边距属性,网格布局还有几个特有的属性:
- layoutHorizontalSpacing:水平方向上组件最小间距
- layoutVerticalSpacing:垂直方向上组件最小间距
- layoutRowStretch:各行的延展因子
- layoutColumnStretch:各列的延展因子
- layoutRowMinimumHeight:各行的最小高度,单位为像素
- layoutColumnMinimumWidth:各列的最小宽度,单位为像素
- layoutSizeConstraint:布局的尺寸限制方式
下面是应用网格布局应用的一个例子:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QGroupBox *groupBox=new QGroupBox(this);
groupBox->setGeometry(QRect(290,160,200,230));
QGridLayout *gridLayout=new QGridLayout(groupBox);
gridLayout->setHorizontalSpacing(7);
gridLayout->setVerticalSpacing(12);
gridLayout->setContentsMargins(10,10,-1,-1);
QPushButton *pushButton=new QPushButton(groupBox);
gridLayout->addWidget(pushButton,0,0,1,1);
QPushButton *pushButton_2=new QPushButton(groupBox);
gridLayout->addWidget(pushButton_2,0,1,1,1);
QComboBox *comboBox=new QComboBox(groupBox);
comboBox->addItem(QString());
gridLayout->addWidget(comboBox,1,0,1,2);
QPlainTextEdit *plainTextEdit=new QPlainTextEdit(groupBox);
gridLayout->addWidget(plainTextEdit,2,0,1,2);
this->setLayout(gridLayout);
}
其中,下面的语句表示将表格添加至0行0列,占据1行1列的位置.
gridLayout->addWidget(pushButton,0,0,1,1);
其他语句以此类推.
分割条布局
实现分割条功能的类是QSplitter,分隔条可以实现水平分割或垂直分割.一般是在两个可以自由改变大小的组件间分割.
分割条主要有以下几个属性:
- orientation:方向,即水平分割或垂直分割
- opaqueResize:如果值为true,则拖动分割条时,组件是动态改变大小的.
- handleWidth:进行分割操作的拖动条的宽度,单位为像素.
- childrenCollapsible:表示进行分割操作时,子组件大小是否可以为0.
下面是一个使用分割条的例子:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QSplitter *splitter=new QSplitter(this);
splitter->setOrientation(Qt::Horizontal);
splitter->setOpaqueResize(true);
splitter->setHandleWidth(8);
splitter->setMinimumSize(QSize(350,200));
splitter->setChildrenCollapsible(true);
QGroupBox *groupBox=new QGroupBox(splitter);
groupBox->setMinimumSize(QSize(10,0));
splitter->addWidget(groupBox);
QPlainTextEdit *plainTextEdit;
plainTextEdit=new QPlainTextEdit;
splitter->addWidget(plainTextEdit);
}
QChar字符
QChar是一个类,用于处理Qt中的字符.可以将其理解为一个加强版的char.
QChar有很多接口函数,常用的有:
- isDigital():是否为数字
- isLetter():是否为字母
- isLetterOrNumber():是否为字母或数字
- isLower():是否为小写数字
- isUpper():是否为大写数字
- isMark():是否为记号
- isNonCharacter():是否为非文字字符
- isNull():是否为'\0'
- isNumber():判断字符是否为一个数,包括①之类的序号
- isPrint():判断字符是否为可打印字符
- isPunct():判断字符是否为标点符号
- isSpace():判断字符是否为分割符号,如空格,制表符
- isSymbol():判断字符是否为符号
- toLower():返回小写形式
- toUpper():返回大写形式
- (char16_t)unicode():返回16位编码数值
其中值得注意的是一个静态函数QChar::fromLatin1(),其用于将Latin1字符转换为QChar字符.
与之对应的,QChar有一个toLatin1()函数用于将QChar字符转换为Latin1字符.
提供一个使用例子:
QString str="String";
QChar ch=QChar::fromLatin1('Q');
str[0]=ch;
与之相似的,在QChar与UTF-16值转换方面有unicode()方法与QChar::fromUsc2(char16_t c)函数.
QString字符串
QString是Qt中的一个类,用于存储字符串.一般来说,Qt使用到字符串的地方都使用QString.
而一般的std::string与QString互转需要通过QString::fromStdString(str)与qstr.toStdString().
QString是由QChar组成的一个串,QChar使用的是UTF-16编码.
QString使用隐式共享来减少内存占用.这意味着只有在修改一个字符串的时候,这个字符串才会复制.
QString的创建与初始化
QString可以直接通过const char*初始化.
QString str="Hello World";
QString在被创建与初始化后,其存储的就是一个QChar的字符数组.可以对其进行索引.
QString str="Hello";
QChar ch0=str[0];
QString字符串常用操作
可以使用加法运算符进行字符串拼接.
QString str1="Hello ";
QString str2="World";
Qstring str3=str1+str2;
也可以通过append()在字符串后添加字符串,通过prepend()在字符串前添加字符串.
QString str1="igg";
str1.preend(QString("n"));
str1.append(QString("a"));
front()返回第一个字符,back()返回最后一个字符.
left(n)返回前n个字符,right(n)返回后n个字符.注意:转义符视为一个字符处理.
mid(pos,n)返回字符串中的字符数,pos为起始位置,n为返回字符的个数.
sliced()与mid()功能相同,但是其不判断是否在边界内.
函数section()用于从字符串中提取sep作为分隔符,从start段到end段的字符串.
例如:
QString str1="学生姓名,男,2004-09-15,汉族,湖南",str2;
str2=str1.section(",",0,0);//学生姓名
str2=str1.section(",",1,1);//男
str2=str1.section(",",1,2);//男,2004-09-15
str2=str1.section(",",4,4);//湖南
isNull()和isEmpty()作用相似,但是isNull()会对'\0'进行判定,而isEmpty()判定'\0'为true.
QString str1="",str2;
str1.isNull();//false
str1.isEmpty();//true
str2.isNull();//true
str2.isEmpty();//true
count(),若带有参数,可以统计某个字符在字符串中出现的次数.若不带参数,count(),size()与length()都返回字符串长度.
clear()函数清空当前字符串,使字符串为NULL.
resize()用于改变字符串长度,但如果长度短于当前字符串则会截断;长度长于当前字符串则会导致未初始化的内存.
如果resize内含有参数,那么则使用该QChar填充字符串填充部分.
与resize()不同,函数fill()则将字符串中每个字符都用一个新字符替换.其同样可以通过参数调整字符串长度.
indexOf()与lastIndexOf()的功能是在字符串内查找某个字符串首次与最后一次出现的位置.
contains()判断当前字符串是否包含某个字符串.可通过Qt::CaseInsensitive表示是否分辨大小写.
endsWith()和startWith()判断字符串是否以某个字符串开头或结尾.
count()用于统计当前字符串中某个字符串出现的次数.可以设置Qt::CaseInsensitive是否分辨大小写.
函数toUpper()和toLower()用于将字符串内的字母全部转换为大写字母或小写字母.
trimmed()和simplified(),trimmed()会去掉字符串首尾的空格,函数simplified()不仅去掉首尾空格,还会将中间的连续空格用单个空格替换.
chop(n)去掉字符串末尾的n个字符,如果n大于实际意义,字符串内容就变为空.
insert(pos,str),函数insert用于在某个位置插入一个字符串.如果pos大于实际意义,字符串会自动补充空格填充.
replace(pos,n,after)用于从某个位置开始替换n个字符.
其还有一种形式replace(before,after)用于替换所有before字符串为after.可以指定Qt::CaseInsensitive分辨大小写.
remove(pos,n)的功能为从字符串pos开始的位置移出n个字符.若超出实际意义,则把pos后面的字符都移除.
同样的,其还有另一种参数模式,remove(ch),即移除字符串中某个字符出现的所有实例.
QString字符串与数值转换
QString有一些接口函数用于将字符串转换为整数:
参数ok用于获取返回值,表示转换是否成功.
- toInt(bool* ok,int base=10)
- toUInt(bool* ok,int base=10)
- toLong(bool* ok,int base=10)
- toUInt(bool* ok,int base=10)
- toShort(bool* ok,int base=10)
- toUShort(bool* ok,int base=10)
- toLongLong(bool* ok,int base=10)
- toULongLong(bool* ok,int base=10)
其也还有两个接口函数用于将字符串转换为浮点数:
- toFloat(bool* ok)
- toDouble(bool* ok)
函数setNum()则用于将整数或浮点数转换为字符串.
- setNum(int n,int base=10)
- setNum(float n,char format='g',int precision=6)
格式字符 | 格式字符含义 | 精度位数含义 |
---|---|---|
e,E | 科学计数法 | 基数小数点后位数 |
f | 自然计数法 | 小数点后的有效位数 |
g,G | 根据情况自动调节 | 小数点前后的数字位数之和 |
QString还有一个静态函数number(),其与setNum类似,但是是静态函数形式
- QString::number(long n,int base)
- QString::number(double n,char format,precision)
静态函数asprintf()用于构造格式化输出字符串.
- QString QString::asprintf(const char cformat*,...)
但是注意,asprintf输出%s会导致乱码,只能使用UTF-8编码的const char*字符串来作为参数.
也就是说,QString型的字符串应当通过QString::data()来表现.
例如:
QString str1=QString::asprintf("Year=%d,Month=%02d",2024,04);
QString str2="哈尔滨工程大学 拓荒者学社"
QString str3=QString::asprintf("欢迎来到%s",str2.toLocal8Bit().data());
QString str4=QString::asprintf("PI=%.10f",M_PI);//3.1415926536
arg()函数是QString的成员函数,用于格式化输出各种数据的字符串,其功能与asprintf类似.
但是arg函数通过形式为%n的占位符来对应实参,这与一般printf不同.
int year=2024,month=2,day=23;
QString str=QString("%1年,%2月,%3日").arg(year).arg(month).arg(day);
QSpinBox和QDoubleSpinBox
属性名称 | 功能 |
---|---|
prefix | 数字显示的前缀 |
suffix | 数字现实的后缀 |
buttonSysbols | 右侧调节按钮的符号 |
text | 只读属性,SpinBox内的所有文字 |
cleanText | 只读属性,不带前后缀的所有文字 |
minimum | 数值范围的最小值 |
maximum | 数值范围的最大值 |
singleStep | 单步步长改变值 |
stepType | 步长类型,单一步长或自适应步长 |
value | 当前显示的值 |
displayIntegerBase | QSpinBox使用的进制 |
decimals | QDoubleSpinBox显示的小数位数 |
对于默认值value的相关操作,存在两个相关的函数:
- int QSpinBox::value()
- void QSpinBox::setValue(int val)
对于相关的读写范围,还有一个函数setRange(),用于同时设置最小值与最大值.
- void QSpinBox::setRange(int minimum,int maximum)
QSpinBox还有两个特有的信号,信号定义如下:
- void QSpinBox::valueChanged(int i)
- void QSpinBox::textChanged(const QString &text)
信号valueChanged()在value变化时被发射,传递的参数为变化之后的数值.
信号textChanged()在显示的文字发生变化的时候被发射.
下面是使用QSpinBox的一个实例:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
//ui->setupUi(this);
lbTest1= new QLabel(QString("电源电动势"));
lbTest2= new QLabel(QString("反应物浓度"));
lbTest3= new QLabel(QString("十六进制值测试"));
sbTest1= new QSpinBox;
sbTest2= new QSpinBox;
sbTest3= new QSpinBox;
sbTest1->setSuffix(QString("mV"));
sbTest1->setValue(10);
sbTest2->setSuffix(QString("mod/L"));
sbTest2->setValue(1);
sbTest3->setSuffix(QString("值"));
sbTest3->setValue(28);
sbTest3->setDisplayIntegerBase(16);
txlTest= new QLineEdit;
txlTest->setText(QString("这里会显示内容"));
connect(sbTest1,SIGNAL(valueChanged(int)),this,SLOT(SpinBoxToLineEdit(int)));
QGridLayout* gridTest= new QGridLayout;
gridTest->addWidget(lbTest1,0,0,1,1);
gridTest->addWidget(lbTest2,1,0,1,1);
gridTest->addWidget(lbTest3,3,0,1,1);
gridTest->addWidget(sbTest1,0,1,1,1);
gridTest->addWidget(sbTest2,1,1,1,1);
gridTest->addWidget(sbTest3,3,1,1,1);
gridTest->addWidget(txlTest,2,0,1,2);
this->setLayout(gridTest);
}
void Widget::SpinBoxToLineEdit(int i)
{
this->txlTest->clear();
this->txlTest->insert(QString("电源电动势改变后:%1").arg(i));
return;
}
常用的按钮控件
按钮是界面上常用的组件,常用的4种按钮控件是:普通按钮(QPushButton),工具按钮(QToolButton),单选按钮(QRadioButton),复选框(QCheckBox)
这四种按钮都是继承于QAbstractButton类的.
属性 | 属性值类型 | 功能 |
---|---|---|
text | QString | 按钮的显示文字 |
icon | QIcon | 按钮的图标 |
shortcut | QKeySequence | 按钮的快捷键 |
checkable | bool | 按钮是否可复选 |
checked | bool | 按钮是否复选状态 |
autoExclusive | bool | 在一个布局或容器组件内的同类按钮是否互斥 |
autoRepeat | bool | 是否自动重复发射信号 |
- QPushButton的checkable默认为false
- QRadioButton和QCheckBox的checkable属性默认为true
- QCheckBox的autoExclusive属性默认为false
- QRadioButton的autoExclusive属性默认为true
属性 | 属性值类型 | 功能 |
---|---|---|
autoDefault | bool | 按钮是否为自动默认按钮 |
default | bool | 按钮是否为默认按钮 |
flat | bool | 按钮是否没有边框 |
QCheckBox新增了一个tristate属性,QRadioButton没有新的属性.
QAbstractButton定义的新信号:
- void clicked(bool checked)//点击按钮时
- void pressed()//按下空格或左键
- void released()//释放空格或左键
- void toggled(bool checked)//按钮的checked属性变化
QPushButton和QRadioButton没有定义新信号.
QCheckBox定义了一个新信号:
- void QCheckBox::stateChanged(int state)
下面提供了一个使用button的例子:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
private slots:
void on_btnLeft();
void on_btnMiddle();
void on_btnRight();
void on_btnBF();
void on_btnIT();
void on_btnUL();
void on_chkRead(bool checked);
void on_chkEnabled(bool checked);
void on_chkClean(bool checked);
void on_radBlack();
void on_radBlue();
void on_radRed();
signals:
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->btnLeft,SIGNAL(clicked(bool)),this,SLOT(on_btnLeft()));
connect(ui->btnRight,SIGNAL(clicked(bool)),this,SLOT(on_btnRight()));
connect(ui->btnMiddle,SIGNAL(clicked(bool)),this,SLOT(on_btnMiddle()));
connect(ui->btnBF,SIGNAL(clicked(bool)),this,SLOT(on_btnBF()));
connect(ui->btnIT,SIGNAL(clicked(bool)),this,SLOT(on_btnIT()));
connect(ui->btnUL,SIGNAL(clicked(bool)),this,SLOT(on_btnUL()));
connect(ui->radBlack,SIGNAL(clicked(bool)),this,SLOT(on_radBlack()));
connect(ui->radBlue,SIGNAL(clicked(bool)),this,SLOT(on_radBlue()));
connect(ui->radRed,SIGNAL(clicked(bool)),this,SLOT(on_radRed()));
connect(ui->chkClean,SIGNAL(clicked(bool)),this,SLOT(on_chkClean(bool)));
connect(ui->chkEnabled,SIGNAL(clicked(bool)),this,SLOT(on_chkEnabled(bool)));
connect(ui->chkRead,SIGNAL(clicked(bool)),this,SLOT(on_chkRead(bool)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_btnLeft()
{
ui->pltEdit->setAlignment(Qt::AlignLeft);
}
void MainWindow::on_btnMiddle()
{
ui->pltEdit->setAlignment(Qt::AlignCenter);
}
void MainWindow::on_btnRight()
{
ui->pltEdit->setAlignment(Qt::AlignRight);
}
void MainWindow::on_btnBF()
{
static bool flag=true;
QFont font= ui->pltEdit->font();
font.setBold(flag);
ui->pltEdit->setFont(font);
flag=!flag;
}
void MainWindow::on_btnIT()
{
static bool flag=true;
QFont font= ui->pltEdit->font();
font.setItalic(flag);
ui->pltEdit->setFont(font);
flag=!flag;
}
void MainWindow::on_btnUL()
{
static bool flag=true;
QFont font= ui->pltEdit->font();
font.setUnderline(flag);
ui->pltEdit->setFont(font);
flag=!flag;
}
void MainWindow::on_chkRead(bool checked)
{
ui->pltEdit->setReadOnly(checked);
}
void MainWindow::on_chkEnabled(bool checked)
{
ui->pltEdit->setEnabled(checked);
}
void MainWindow::on_chkClean(bool checked)
{
ui->pltEdit->setClearButtonEnabled(checked);
}
void MainWindow::on_radBlack()
{
QPalette plet= ui->pltEdit->palette();
plet.setColor(QPalette::Text,Qt::black);
ui->pltEdit->setPalette(plet);
}
void MainWindow::on_radBlue()
{
QPalette plet= ui->pltEdit->palette();
plet.setColor(QPalette::Text,Qt::blue);
ui->pltEdit->setPalette(plet);
}
void MainWindow::on_radRed()
{
QPalette plet= ui->pltEdit->palette();
plet.setColor(QPalette::Text,Qt::red);
ui->pltEdit->setPalette(plet);
}
QSlider和QProgressBar
QAbstractSlider是QSlider,QScrollBar和QDial的父类,它定义了这几个类共有的一些属性和接口函数.
属性 | 属性值类型 | 功能 |
---|---|---|
minimum | int | 数据范围的最小值 |
maximum | int | 数据范围的最大值 |
singleStep | int | 变化最小步长 |
pageStep | int | 按PgUp与PgDn变化的数值 |
value | int | 组件的当前值 |
sliderPosition | int | 滑块的位置 |
tracking | bool | 改变value是否改变slider位置 |
orientation | Qt::Orientation | 滑动条的方向,水平或垂直 |
invertedAppearance | bool | 显示方式是否反向 |
invertedControls | bool | 反向按键控制 |
QAbstractSlider的接口函数主要是属性的读写函数,还有一个常用函数setRange()用于设置最大值与最小值.
- void QAbstractSlider::setRange(int min,int max)
QAbstractSlider类的信号主要有:
- void actionTriggered(int action)//滑动条触发一些动作
- void rangeChanged(int min,int max)//minimum或maximum值变化时
- void sliderMoved(int value)//用户按住鼠标拖动滑块时
- void sliderPressed()//在滑块上按下鼠标时
- void sliderReleased()//在滑块上释放鼠标时
- void valueChanged(int value)//value值改变时
action表示动作的类型,用枚举类型QAbstractSlider::SliderAction的值表示.如SliderToMinimum表示拖动到最小值.
如果tracking属性被设置为false时,valueChanged()仅在鼠标拖动结束时发射.
QSlider一般用于滑动输入数值数据的组件,其新定义的属性有两个:
- tickPosition:标尺刻度的显示位置,属性值为枚举类型QSlider::TickPosition.
- tickInterval:标尺刻度的间隔值.
QScrollBar没有新定义的属性,一般与文本编辑器或容器组件组合使用.起滚卷条的作用.
QDial表示表盘式组件,通过旋转表盘获得输入值.QDial定义了3个新的属性:
- notchesVisible:表盘外围的刻度线是否可见.
- notchTarget:表盘刻度间的间隔像素值.
- wrapping:表盘上首尾刻度是否连贯.
QProgressBar表示进度条组件,一般以百分比数据来显示进度.其父类为QWidget.
其几个不易理解的属性如下:
- textDirection:文字的方向.
- format:显示文字的格式.
QProgressBar类的接口函数主要是属性的读写函数.QProgressBar还有两个常用的与属性无关的函数:
- void QProgressBar::setRange(int minimum,int maximum)
- void QProgressBar::reset()
下面是一个使用滚动条的实例:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->dial,SIGNAL(valueChanged(int)),this,SLOT(do_valueChange(int)));
connect(ui->progressBar,SIGNAL(valueChanged(int)),this,SLOT(do_valueChange(int)));
connect(ui->scrollBar,SIGNAL(valueChanged(int)),this,SLOT(do_valueChange(int)));
connect(ui->slider,SIGNAL(valueChanged(int)),this,SLOT(do_valueChange(int)));
connect(ui->spinBox,SIGNAL(valueChanged(int)),this,SLOT(do_valueChange(int)));
ui->dial->setNotchesVisible(true);
do_valueChange(10);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::do_valueChange(int value)
{
ui->dial->setValue(value);
ui->progressBar->setValue(value);
ui->scrollBar->setValue(value);
ui->slider->setValue(value);
ui->spinBox->setValue(value);
}
日期时间数据
日期和时间是经常遇到的数据类型.Qt提供了三个类用于表示和处理数据类型:
- QTime:表示时间数据的类.
- QDate:表示日期数据的类.
- QDateTime:表示时间和日期数据的类.
这三个类都没有父类.为了在界面上输入和现实日期时间的数据,Qt定义了几个用于日期时间数据处理的界面类:
- QTimeEdit:编辑和显示时间的组件类
- QDateEdit:编辑和显示日期的组件类
- QDateTimeEdit:编辑和显示日期的组件类.
- QCalendarWidget:一个用日历形式显示和选择日期的组件类.
QTime类适用于存储与操作时间数据的类,时间数据包含小时,分钟,秒,毫秒.QTime总是24小时制,不区分AM/PM.
QTime初始化时间数据的函数定义如下:
- QTime::QTime(int h,int m,int s=0,int ms=0)
还可以使用静态函数QTime::currentTime()创建一个QTime对象,并将其初始化为系统当前时间.
函数原型 | 功能 |
---|---|
int hour() | 返回当前时间的小时 |
int minute() | 返回当前时间的分钟 |
int second() | 返回当前时间的秒 |
int misec() | 返回当前时间的毫秒 |
bool setHMS(int h,int m,int s,int ms=0) | 设置当前时间的数据 |
int msecSinceStartOfDay() | 返回时间从00:00:00开始的毫秒数 |
QTime addSecs(int s) | 当前时间延后s秒后的时间 |
int secsTo(QTime t) | 返回一个与当前时间相差t秒的秒数 |
QString toString(const QString& format) | 将当前时间按照format格式转换为字符串 |
QDate是用于存储和操作日期数据的类,日期数据包含年月日数据.
与QTime类似,可以在初始化时为其提供数据,也可以使用静态函数QDate::currentDate()获取系统当前日期.
函数原型 | 功能 |
---|---|
int year() | 返回当前日期年数据 |
int month() | 返回当前日期月数据 |
int day() | 返回当前日期日数据 |
int dayOfWeek() | 返回当前日期在一周中的日期 |
int dayOfYear() | 返回当前日期在一年中是第多少天 |
bool setDate(int year,int month,int day) | 设置日期的年日月数据 |
void getDate(int* year,int* month,int* day) | 通过指针变量,返回年日月数据 |
QDate addYears(int nyears) | 返回一个较时间迟n年的QDate变量 |
QDate addMonths(int nmonths) | 返回一个较时间迟n月的QDate变量 |
QDate addDays(qint64 ndays) | 返回一个较时间迟n天的QDate变量 |
qint64 daysTo(QDate d) | 返回一个与当前日期差d天的天数 |
QString toString(const QString&format) | 将当前日期按照format格式转换为字符串 |
此外,QDate还有一个静态函数isLeapYear()可以判断某年是否为闰年:
- bool QDate::isLeapYear(int year)
函数原型 | 功能 |
---|---|
QDate date() | 返回当前日期时间数据的日期数据 |
QTime time() | 返回当前日期时间数据的时间数据 |
qint64 toMSecsSinceEpoch() | 返回与UTC时间1970-01-01T00:00:00:00.000相差的毫秒数 |
void setMSecsSinceEpoch(qint64 msecs) | 设置与UTC时间1970-01-01T00:00:00:00.000相差的毫秒数 |
qint64 toSecsSinceEpoch() | 返回与UTC时间1970-01-01T00:00:00:00.000相差的秒数 |
void setSecsSinceEpoch(qint64) | 设置与UTC时间1970-01-01T00:00:00:00.000相差的秒数 |
QString toString(const QString& format) | 将当前日期时间按照format设置的格式转换为字符串 |
QDateTime toUTC() | 将当前时间转换为UTC时间 |
QDateTime有两个静态函数用于返回系统当前时间:
- QDateTime QDateTime::currentDateTime()
- QDateTime QDateTime::currentDateTimeUtc()
QTime,QDate,QDateTime都有一个函数toString(),用于将当前的日期时间数据转换为字符串.
同样的,QTime,QDate,QDateTime都有一个静态函数fromString().用于将字符串转换为相应类的对象.
- QString QDateTime::toString(const QString&format,QCalendar cal=QCalendar())
- QDateTime QDateTime::fromString(const QString&string,const QString&format,QCalendar cal=QCalendar())
格式字符 | 含义 |
---|---|
d | 天1~31 |
dd | 天01~31 |
M | 月1~12 |
MM | 月01~12 |
yy | 年00~99 |
yyyy | 年0000~9999 |
h | 小时023或112 |
hh | 小时0023或0112 |
H | 小时0~23 |
HH | 小时00~23 |
m | 分钟0~59 |
mm | 分钟00~59 |
s | 秒0~59 |
ss | 秒00~59 |
z | 毫秒0~999 |
zzz | 毫秒000~999 |
AP或A | 使用AM/PM显示 |
ap或a | 使用am/pm显示 |
而且上述字符仅作为一个占位符使用,其其他内容不影响其字符串format.
QtDesigner有3个用于编辑日期时间数据的界面组件,如QTimeEdit,QDateEdit,QDateTimeEdit.
而QDateTimeEdit是QDateEdit和QTimeEdit的父类,而QDateTimeEdit的父类是QAbstractSpinBox.
所以其实日期时间编辑框的特性与QSpinBox的有些相似.
QDateTimeEdit的主要属性有:
- currentSection:光标所在的输入段,是枚举类型QDateTimeEdit::Section.
- currentSecitonIndex:用序号表示的光标所在的段.
- calendarPopup:是否允许弹出一个日历选择框.会将上下调节按钮变成一个下拉按钮.
- displayFormat:日期时间数据的显示格式.
QDateTimeEdit常用的接口函数就是读取或设置日期时间数据的函数:
- QDateTime dateTime()
- void setDateTime(const QDateTime&dateTime)
- QDate date()
- void setDate(QDate date)
- QTime time()
- void setTime(QTime time)
QDateTimeEdit有3个信号:
- void dateChanged(QDate date)
- void timeChanged(QTime time)
- void dateTimeChanged(const QDateTime& datetime)
QCalendarWidget则是一个用于选择日期的日历组件.
QCalendarWidget的几个常见接口函数有:
- void showToday()
- void showSelectedDate()
- QDate selectedDate()
- void setSelectedDate(QDate date)
QCalendarWidget有4个信号:
- void activated(QDate date)
- void clicked(QDate date)
- void currentPageChanged(int year,int month)
- void selectionChanged()
选择的日期变化时,QCalendarWidget会发射selectionChanged信号.
下面给出了一个使用QDateTime,QCalendarWidget等的例子:
mainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
private slots:
void on_btnReset();
void on_btnClear();
void on_btnTime();
void on_btnDate();
void on_btnDateTime();
void on_btnChange();
void on_timeEdit();
void on_dateEdit();
void on_dateTimeEdit();
void on_calendar();
};
#endif // MAINWINDOW_H
mainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->btnClear,SIGNAL(clicked(bool)),this,SLOT(on_btnClear()));
connect(ui->btnReset,SIGNAL(clicked(bool)),this,SLOT(on_btnReset()));
connect(ui->btnTime,SIGNAL(clicked(bool)),this,SLOT(on_btnTime()));
connect(ui->btnDate,SIGNAL(clicked(bool)),this,SLOT(on_btnDate()));
connect(ui->btnDateTime,SIGNAL(clicked(bool)),this,SLOT(on_btnDateTime()));
connect(ui->btnChange,SIGNAL(clicked(bool)),this,SLOT(on_btnChange()));
connect(ui->dateEdit,SIGNAL(dateChanged(QDate)),this,SLOT(on_dateEdit()));
connect(ui->timeEdit,SIGNAL(timeChanged(QTime)),this,SLOT(on_timeEdit()));
connect(ui->dateTimeEdit,SIGNAL(dateTimeChanged(QDateTime)),this,SLOT(on_dateTimeEdit()));
connect(ui->calendar,SIGNAL(selectionChanged()),this,SLOT(on_calendar()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_btnReset()
{
ui->calendar->clearFocus();
ui->dateEdit->clear();
ui->timeEdit->clear();
ui->dateTimeEdit->clear();
ui->pltEdit->clear();
ui->lineEdit->clear();
}
void MainWindow::on_btnClear()
{
ui->lineEdit->clear();
ui->pltEdit->clear();
}
void MainWindow::on_btnTime()
{
QTime TM1(13,24,5);
QString str=TM1.toString("HH:mm:ss");
ui->pltEdit->appendPlainText(QString("Time1:%1").arg(str));
QTime TM2= TM1.addSecs(150);
str= TM2.toString("HH:mm:ss");
ui->pltEdit->appendPlainText(QString("Time1 add 150secs:%1").arg(str));
TM2= QTime::currentTime();
str=TM2.toString("HH:mm:ss zzz");
ui->pltEdit->appendPlainText(QString("Current Time:%1").arg(str));
}
void MainWindow::on_btnDate()
{
QDate DT1(2021,7,6);
QString str=DT1.toString("yyyy-MM-dd");
ui->pltEdit->appendPlainText(QString("Date1:%1").arg(str));
QDate DT2;
DT2.setDate(2021,8,25);
str=DT2.toString("yyyy-MM-dd");
ui->pltEdit->appendPlainText(QString("Date2:%1").arg(str));
DT2=QDate::currentDate();
str=DT2.toString("yyyy-MM-dd");
ui->pltEdit->appendPlainText(QString("Current Date:%1").arg(str));
}
void MainWindow::on_btnDateTime()
{
QDateTime DT1=QDateTime::currentDateTime();
QString str=DT1.toString("yyyy-MM-dd hh:mm:ss zzz");
ui->pltEdit->appendPlainText(QString("Current DateTime:%1").arg(str));
QDate dt= DT1.date();
str=dt.toString("yyyy-MM-dd");
ui->pltEdit->appendPlainText(QString("DT1 Date:%1").arg(str));
QTime tm=DT1.time();
str=tm.toString("hh:mm:ss zzz");
ui->pltEdit->appendPlainText(QString("DT1 Time:%1").arg(str));
qint64 MS=DT1.toSecsSinceEpoch();
ui->pltEdit->appendPlainText(QString("Secs Since:%1").arg(MS));
MS+=120;
DT1.setSecsSinceEpoch(MS);
str=DT1.toString("yyyy-MM-dd hh:mm:ss zzz");
ui->pltEdit->appendPlainText(QString("DT1 After120s:%1").arg(str));
}
void MainWindow::on_btnChange()
{
static bool calendar_flag=true;
ui->dateTimeEdit->setCalendarPopup(calendar_flag);
calendar_flag=!calendar_flag;
}
void MainWindow::on_timeEdit()
{
QTime tm= ui->timeEdit->time();
ui->dateTimeEdit->setTime(tm);
}
void MainWindow::on_dateEdit()
{
QDate dt= ui->dateEdit->date();
ui->lineEdit->setText(QString("%1").arg(dt.toString("yyyy-MM-dd")));
ui->dateTimeEdit->setDate(dt);
ui->calendar->setSelectedDate(dt);
ui->calendar->showSelectedDate();
}
void MainWindow::on_dateTimeEdit()
{
QDateTime datetime= ui->dateTimeEdit->dateTime();
ui->lineEdit->setText(QString("%1").arg(datetime.date().toString("yyyy-MM-dd")));
ui->dateEdit->setDate(datetime.date());
ui->timeEdit->setTime(datetime.time());
ui->calendar->setSelectedDate(datetime.date());
ui->calendar->showSelectedDate();
ui->pltEdit->appendPlainText(QString("Now Time:%1").arg(datetime.toString("yyyy-MM-dd hh:mm:ss zzz")));
}
void MainWindow::on_calendar()
{
QDate dt=ui->calendar->selectedDate();
ui->dateEdit->setDate(dt);
ui->dateTimeEdit->setDate(dt);
ui->lineEdit->setText(dt.toString("yyyy-MM-dd"));
}
QTimer和QElapsedTimer
QTimer是软件计时器,其父类是QObject.其主要功能是设置以毫秒为单位的定时周期.
当定时器启动后,定时溢出时QTimer发射timeout()信号.
QTimer类的主要属性如下:
属性 | 属性值类型 | 功能 |
---|---|---|
interval | int | 定时周期,单位是毫秒 |
singleShot | bool | 定时器是否为单次计时 |
timerType | Qt::TimerType | 定时器精度类型 |
active | bool | 返回定时器是否正在运行 |
remainingTime | int | 到发生定时溢出的剩余时间 |
属性timeType表示定时器的精度类型,设置函数setTimerType()的原型定义如下:
- void QTimer::setTimerType(Qt::TimerType atype)
参数atype是枚举类型Qt::TimerType,有以下几个枚举值,默认为Qt::CoarseTimer:
- Qt::PreciseTimer:精确计时器,精度保持在毫秒级
- Qt::CoarseTimer:粗糙计时器,定时误差保持在周期值的5%内
- Qt::VeryCoarseTimer:非常粗糙的定时器,精度保持在秒级.
QTimer有几个公有槽函数用于启动和停止定时器:
- void QTimer::start()//启动定时器
- void QTimer::start(int msec)//启动定时器,并设置定时周期
- void QTimer::stop()//停止定时器
QTimer只有一个timeout()信号,其原型如下:
- void QTimer::timeout()
QTimer还有一个静态函数singleShot(),用于创建和启动单次定时器,并且将定时器的timeout()信号与指定的槽函数关联.
这个函数有多种参数形式,其中一种函数原型定义如下:
- void QTimer::singleShot(int msec,Qt::TimerType,const QObject* receiver,const char* member)
QElapsedTimer则用于快速计算两个时间的间隔时间,它没有父类,不支持Qt的元对象系统,所以只有接口函数.
QElapsedTimer的接口函数有:
- void start()
- qint64 elapsed()
- qint64 nsecsElapsed()
- qint64 restart()
函数elapsed()的返回值是自上次start()之后计时器的运行时间,单位是毫秒.
函数nsecsElapsed()的返回值也是指上次start()之后计时器的运行时间,但单位是纳秒.
函数restart()返回从上次启动计时器到现在的时间,单位是毫秒,然后重启计时器.
下面是一个使用QTimer的实例:
mainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTime>
#include <QTimer>
#include <QElapsedTimer>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QTimer* m_timer;
QElapsedTimer m_counter;
private slots:
void do_timer_timeout();
void do_timer_shot();
void do_btnStart();
void do_btnStop();
void do_btnOneShot();
};
#endif // MAINWINDOW_H
mainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_timer= new QTimer(this);
m_timer->stop();
m_timer->setTimerType(Qt::CoarseTimer);
ui->radCoarse->setChecked(true);
connect(m_timer,SIGNAL(timeout()),this,SLOT(do_timer_timeout()));
connect(ui->btnStart,SIGNAL(clicked(bool)),this,SLOT(do_btnStart()));
connect(ui->btnStop,SIGNAL(clicked(bool)),this,SLOT(do_btnStop()));
connect(ui->btnOneShot,SIGNAL(clicked(bool)),this,SLOT(do_btnOneShot()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::do_timer_timeout()
{
QApplication::beep();
QTime curTime= QTime::currentTime();
ui->LCDHour->display(curTime.hour());
ui->LCDMin->display(curTime.minute());
ui->LCDSec->display(curTime.second());
if(m_timer->isSingleShot()){
int tmMsec= m_counter.elapsed();
QString str=QString("流逝的时间:%1毫秒").arg(tmMsec);
ui->labelTime->setText(str);
ui->btnStop->setEnabled(false);
}
}
void MainWindow::do_timer_shot()
{
QApplication::beep();
int tmMsec= m_counter.elapsed();
QString str=QString("流逝的时间:%1毫秒").arg(tmMsec);
ui->labelTime->setText(str);
ui->btnOneShot->setEnabled(true);
}
void MainWindow::do_btnStart()
{
m_timer->setInterval(ui->spinBox->value());
if(ui->radCoutinue->isChecked())
m_timer->setSingleShot(false);
else
m_timer->setSingleShot(true);
if(ui->radPrecise->isChecked())
m_timer->setTimerType(Qt::PreciseTimer);
else if(ui->radCoutinue->isChecked())
m_timer->setTimerType(Qt::CoarseTimer);
else
m_timer->setTimerType(Qt::VeryCoarseTimer);
m_timer->start();
m_counter.start();
ui->btnStart->setEnabled(false);
ui->btnOneShot->setEnabled(false);
ui->btnStop->setEnabled(true);
}
void MainWindow::do_btnStop()
{
m_timer->stop();
int tmMsec= m_counter.elapsed();
int ms= tmMsec%1000;
int sec= tmMsec/1000;
QString str= QString("流逝的时间:%1秒%2毫秒").arg(sec).arg(ms,3,10,QChar('0'));
ui->labelTime->setText(str);
ui->btnStart->setEnabled(true);
ui->btnOneShot->setEnabled(true);
ui->btnStop->setEnabled(false);
}
void MainWindow::do_btnOneShot()
{
int intv= ui->spinBox->value();
QTimer::singleShot(intv,Qt::PreciseTimer,this,&MainWindow::do_timer_shot);
m_counter.start();
ui->btnOneShot->setEnabled(false);
}
QComboBox
QComboBox是下拉列表框组件,它可以提供下拉列表供用户选择输入,也可以提供编辑框用于输入文字.
所以QComboBox也被称为组合框.
属性 | 属性值类型 | 功能 |
---|---|---|
editable | bool | 是否可编辑,若为false则只可使用下拉栏 |
currentText | QString | 当前显示的文字 |
currentIndex | int | 当前选中项的序号 |
maxVisibleItems | int | 下拉列表中显示最大条数,若超过将出现卷滚条 |
maxCount | int | 下拉列表中最大项数 |
insertPolicy | InsertPolicy | 用户编辑的新文字插入列表的方式,为枚举类型QComboBox::InsertPolicy |
placeholderText | QString | 占位文字 |
duplicatesEnabled | bool | 是否允许列表中出现重复的项 |
modelColumn | int | 下拉列表中的数据在数据模型中的列编号 |
QComboBox使用模型/视图结构存储和显示下拉列表的数据,下拉列表的数据实际上存储在QStandardItemModel模型里.下拉列表使用QListView的子类组件显示.modelColumn属性表示下拉列表现实的数据在模型中的列编号.
QComboBox的几个信号原型如下:
- void activated(int index)
- void currentIndexChanged(int index)
- void currentTextChanged(const QString &text)
- void editTextChanged(const QString &text)
- void highlighted(int index)
- void textActivated(const QString &text)
- void textHighlighted(const QString &text)
下面是使用QComboBox的一个实例:
mainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
private slots:
//void on_btnSimpleInit();
void on_pushButton_5_clicked(bool checked);
void on_btnSimpleInit_clicked(bool checked);
void on_chkEditable_clicked(bool checked);
void on_btnClearList_clicked(bool checked);
void on_btnDataInit_clicked(bool checked);
void comChanged(const QString& arg1);
void on_comData_currentIndexChanged(int index);
void on_chkReadOnly_clicked(bool checked);
};
#endif // MAINWINDOW_H
mainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_5_clicked(bool checked)
{
ui->pltEdit->clear();
}
void MainWindow::on_btnSimpleInit_clicked(bool checked)
{
QIcon icon;
icon.addFile(":/img/icon.jpg");
ui->comSimple->clear();
for(int i=0;i<20;i++)
ui->comSimple->addItem(icon,QString("城市%1").arg(i));
}
void MainWindow::on_chkEditable_clicked(bool checked)
{
ui->comSimple->setEditable(checked);
}
void MainWindow::on_btnClearList_clicked(bool checked)
{
ui->comSimple->clear();
}
void MainWindow::on_btnDataInit_clicked(bool checked)
{
ui->comData->clear();
QMap<QString,int>city_zone;
city_zone.insert(QString("北京"),10);
city_zone.insert(QString("上海"),20);
city_zone.insert(QString("广州"),30);
city_zone.insert(QString("长沙"),40);
city_zone.insert(QString("成都"),50);
for(auto iter:city_zone.keys())
ui->comData->addItem(iter,city_zone.value(iter));
}
void MainWindow::comChanged(const QString &arg1)
{
ui->pltEdit->appendPlainText(arg1);
}
void MainWindow::on_comData_currentIndexChanged(int index)
{
Q_UNUSED(index);
QString str= ui->comData->currentText()+ui->comData->currentData().toString();
ui->pltEdit->appendPlainText(str);
}
void MainWindow::on_chkReadOnly_clicked(bool checked)
{
ui->pltEdit->setEnabled(!checked);
}
QMainWindow和QAction
QMainWindow是主窗口类,具有菜单栏,工具栏,状态栏等主窗口常见的界面元素.
要设计主窗口上的菜单栏,工具栏,按钮的下拉菜单,组建的快捷菜单等需要用到QAction类.
窗口界面可视化设计
创建一个GUI项目,在向导中选择窗口基类为QMainWindow,新建窗口类的名称会被自动设置为MainWindow.
QAction的父类是QObject,所以支持Qt的元对象系统.在UI可视化设计时就可以创建Action,使用设计好的Action可以创建菜单项和工具按钮.
Qt Designer界面下方有一个Action编辑器,可以在这个编辑器里可视化设计Action.
在Action编辑器中,编辑Action的对话框,包括以下一些设置内容:
- Text:Action的显示文字
- Object name:Action的对象名称
- ToolTip:当鼠标光标停留时的提示
- Icon:Action的图标
- Checkable:Action是否可被复选
- ShortCut:Action的快捷键.
在Action编辑器中创建一个Action后,属性编辑器就会显示这几个Action的属性.一些属性说明如下:
- text:用Action创建菜单项时显示的文字.
- iconText:这是用Action创建工具按钮时按钮上显示的文字.
- statusTip:这是鼠标移到Action上时的提示.
- shortcutContext:这是Action快捷键的有效响应范围.
- autoRepeat:当快捷键一直按下时,Action是否自动重复执行.
- menuRole:在macOS上才有作用的功能.
- iconVisibleInMenu:表示菜单项上是否需显示Action图标.
- shortcutVisuableInContextMenu:表示使用Action创建右键快捷菜单时,是否显示快捷键.
- priority:表示Action在UI上的优先级.
工具栏对应QToolBar类,选择一个工具栏后,在属性编辑器中可对其属性进行设置.
属性名称 | 属性值类型 | 含义与作用 |
---|---|---|
movable | bool | 工具栏是否可移动 |
allowedAreas | Qt::ToolBarAreas | 工具栏可以放置的窗口区域 |
orientation | Qt::Orientation | 工具栏的方向 |
iconSize | QSize | 图标的大小 |
toolButtonStyle | Qt::ToolButtonStyle | 工具按钮样式 |
floatable | bool | 工具栏是否可浮动 |
属性toolButtonStyle的取值决定了工具按钮显示的样式,属性值Qt::ToolButtonStyle有以下几种枚举值.
- Qt::ToolButtonIconOnly:只显示图标
- Qt::ToolButtonTextOnly:只显示文字
- Qt::ToolButtonTextBesideIcon:文字显示在图标旁边
- Qt::ToolButtonTextUnderIcon:文字显示在图标下面
- Qt::ToolButtonFollowStyle:由QStyle样式定义
QAction的类大部分接口函数是用于属性读写的函数.
QAction还定义了一些信号和公有槽.QAction主要的信号有:
- void changed()//Action的text等属性发生改变时
- void checkableChanged(bool checkable)//checkable的属性变化时
- void enabledChanged(bool enabled)//enabled属性值变化时
- void hovered()//鼠标移动至该Action上时
- void toggled(bool checked)//checked属性值变化时
- void triggered(bool checked=false)//点击此Action时
- void visibleChanged()//visible属性值变化时
当我们点击Action创建的菜单项/工具按钮或按下Action的快捷键时,QAction属性发射triggered()信号.
当Action的checked属性变化时,Action会发射toggled(bool)信号.
QAction定义了一些公有槽,这些公有槽可以在程序中直接调用或connect.
- void hover()//触发hovered()信号
- void trigger()//触发triggered()信号
- void resetEnabled()//复位enabled为默认值
- void setChecked(bool)//设置checked属性的值
- void setDisabled(bool b)//设置enabled属性的值
- void setVisible(bool)//设置visible属性的值
- void toggle()//反转checked属性的值
在UI可视化设计时,可以用Action可视化地创建工具栏上的按钮,但是不能可视化地在工具栏上放置其他组件.
QToolBar提供了接口函数,可以通过代码在工具栏上添加组件,从而灵活地设计工具栏.
- void addAction(QAction *action)//添加一个Action
- QAction *addWidget(QWidget *widget)//添加一个界面组件
- QAction *insertWidget(QAction *before,QWidget *widget)//插入一个界面组件
- QAction *addSeparator()//添加一个分隔条
- QAction *insertSeparator(QAction *before)//插入一个分隔条
主窗口上的状态栏对应的是QStatusBar类,在UI可视化设计时,不能在状态栏上放置任何组件,而只能通过其接口函数向状态栏添加组件.
QStatusBar有两个函数用于添加组件,其原型如下:
- void addWidget(QWidget *widget,int stretch=0)//添加正常组件
- void addPermanentWidget(QWidget *widget,int strech=0)//添加永久组件
QStatusBar类有两个公有槽,可以显示和清楚临时消息,定义如下:
- void showMessage(const QString &message,int timeout=0)//显示临时消息
- void clearMessage()//清除临时消息
如果一个Action的statusTip属性不为空,当鼠标移到这个Action创建的菜单或按钮上时,状态栏就会自动显示这个Action的statusTip属性的内容:当鼠标移出时,临时消息就会被自动清除.
下面是一个使用QAction,QToolBar,QStatusBar的综合例子:
mainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QActionGroup>
#include <QLabel>
#include <QFontComboBox>
#include <QSpinBox>
#include <QProgressBar>
#include <QTextCharFormat>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
QLabel* lbFile;
QProgressBar* progressBar;
QSpinBox* spinFontSize;
QLabel* lbFontSize;
QFontComboBox* fcomFont;
private slots:
void on_actNewFile_triggered();
void on_actOpenFile_triggered();
void on_actSaveFile_triggered();
void on_pltEdit_copyAvailable(bool b);
void on_pltEdit_selectionChanged();
void on_actBlod_triggered(bool checked);
void on_actItalian_triggered(bool checked);
void on_actUnderline_triggered(bool checked);
void on_spinFontSize(int fontSize);
void on_fcomCombo(QFont font);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
//中英界面互斥
ui->setupUi(this);
QActionGroup *acgLanguage = new QActionGroup(this);
acgLanguage->addAction(ui->actChinese);
acgLanguage->addAction(ui->actEnglish);
acgLanguage->setExclusive(true);
//创建一些无法通过GUI界面设计的组件
spinFontSize=new QSpinBox(this);
spinFontSize->setMinimum(5);
spinFontSize->setMaximum(50);
spinFontSize->setValue(ui->pltEdit->font().pointSize());
spinFontSize->setMinimumWidth(50);
QLabel* lbSpinFont= new QLabel(QString("字号"),this);
QLabel* lbFontComboBoxFont= new QLabel(QString("字体"),this);
fcomFont= new QFontComboBox(this);
fcomFont->setMaximumWidth(80);
fcomFont->setFont(ui->pltEdit->font());
ui->toolBar->addWidget(lbSpinFont);
ui->toolBar->addWidget(spinFontSize);
ui->toolBar->addWidget(lbFontComboBoxFont);
ui->toolBar->addWidget(fcomFont);
ui->toolBar->addSeparator();
ui->toolBar->addAction(ui->actClose);
ui->toolBar->addSeparator();
//状态栏相关
lbFile= new QLabel(this);
lbFile->setMaximumWidth(150);
lbFile->setText(QString("文件名:"));
ui->statusbar->addWidget(lbFile);
progressBar= new QProgressBar(this);
progressBar->setMinimum(5);
progressBar->setMaximum(50);
progressBar->setValue(ui->pltEdit->font().pointSize());
ui->statusbar->addWidget(progressBar);
lbFontSize= new QLabel(QString("Permanent"),this);
ui->statusbar->addPermanentWidget(lbFontSize);
//信号与槽
connect(spinFontSize,SIGNAL(valueChanged(int)),this,SLOT(on_spinFontSize(int)));
connect(fcomFont,SIGNAL(currentFontChanged(QFont)),this,SLOT(on_fcomCombo(QFont)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actNewFile_triggered()
{
ui->pltEdit->clear();
ui->pltEdit->document()->setModified(false);
lbFile->setText("文件名:新建文件");
}
void MainWindow::on_actOpenFile_triggered()
{
lbFile->setText(QString("正在打开文件"));
for(int i=1;i<99;i++){
progressBar->setValue(i);
_sleep(1);
}
lbFile->setText(QString("文件名:新建文件"));
progressBar->setValue(ui->pltEdit->font().pointSize());
}
void MainWindow::on_actSaveFile_triggered()
{
ui->pltEdit->clear();
ui->pltEdit->document()->setModified(false);
QString str= lbFile->text();
lbFile->setText("文件已保存");
_sleep(2);
lbFile->setText(str);
}
void MainWindow::on_pltEdit_copyAvailable(bool b)
{
ui->actCopy->setEnabled(b);
ui->actCut->setEnabled(b);
ui->actPaste->setEnabled(ui->pltEdit->canPaste());
}
void MainWindow::on_pltEdit_selectionChanged()
{
QTextCharFormat fmt= ui->pltEdit->currentCharFormat();
ui->actBlod->setChecked(fmt.font().bold());
ui->actItalian->setChecked(fmt.font().italic());
ui->actUnderline->setChecked(fmt.font().underline());
spinFontSize->setValue(fmt.font().pointSize());
fcomFont->setCurrentFont(fmt.font());
}
void MainWindow::on_actBlod_triggered(bool checked)
{
QTextCharFormat fmt= ui->pltEdit->currentCharFormat();
if(checked)
fmt.setFontWeight(QFont::Bold);
else
fmt.setFontWeight(QFont::Normal);
ui->pltEdit->setCurrentCharFormat(fmt);
}
void MainWindow::on_actItalian_triggered(bool checked)
{
QTextCharFormat fmt= ui->pltEdit->currentCharFormat();
fmt.setFontItalic(checked);
ui->pltEdit->setCurrentCharFormat(fmt);
}
void MainWindow::on_actUnderline_triggered(bool checked)
{
QTextCharFormat fmt= ui->pltEdit->currentCharFormat();
fmt.setFontUnderline(checked);
ui->pltEdit->setCurrentCharFormat(fmt);
}
void MainWindow::on_spinFontSize(int fontSize)
{
QTextCharFormat fmt=ui->pltEdit->currentCharFormat();
fmt.setFontPointSize(fontSize);
progressBar->setValue(fontSize);
ui->pltEdit->setCurrentCharFormat(fmt);
}
void MainWindow::on_fcomCombo(QFont font)
{
QTextCharFormat fmt=ui->pltEdit->currentCharFormat();
fmt.setFont(font);
ui->pltEdit->setCurrentCharFormat(fmt);
lbFontSize->setText(QString("字体:%1").arg(font.family()));
}
在此还需要补充QPlainTextEdit相关的一些使用.
QPlainTextEdit组件定义了许多用于编辑操作的槽函数,其也有一些信号函数:
- void blockCountChanged(int newBlockCount)//段落数变化时
- void copyAvailable(bool yes)//有文字被选择或取消选择时
- void cursorPositionChanged(bool changed)//光标位置变化时
- void modificationChanged(bool changed)//文档的修改状态变化时
- void redoAvailable(bool available)//redo操作状态变化时
- void selectionChanged()//选择的内容变化时
- void textChanged()//文档内容变化时
- void undoAvailable(bool available)//undo操作状态变化时
- void updateRequest(const QRect &rect,int dy)//需要更新显示时
QToolButton和QListWidget
Qt中用于处理项数据(item data)的组件有两类:
一类是Item Views组件,包括QListView,QTreeView,QTableView等;
另一类是Item Widgets组件,包括QListWidget,QTreeWidget,QTableWidget等.
Item Widgets组件直接将数据存储在每一个项里,一个项存储了文字,文字的格式定义,图标,用户数据等内容.
QToolBox是工具箱组件类,工具箱是一种垂直分页的多页容器组件.在UI可视化设计时,在工具箱组件上点击鼠标右键调出快捷菜单,可以分别使用Insert Page和Delete Page菜单项添加和删除页面.
工具箱的每一个页面都是一个QWidget组件,在页面的工作区可以放置任何其他界面组件.
QToolBox有一个信号,其中index是当前页面序号:
- void QToolBox::currentChanged(int index)
对于QListWidget,其有的QListWidgetItem有一个标识变量flags,用于设置列表项的特性.
flags是枚举类型Qt::ItemFlag的枚举值的组合:
- Selectable:列表项可被选择,Qt::ItemIsSelectable
- Editable:列表项可被编辑,Qt::ItemIsEditable
- DragEnabled:列表项可以被拖动,Qt::ItemIsDragEnabled
- DropEnabled:列表项可以接收拖放的项,Qt::ItemIsDropEnabled
- UserCheckable:列表项可以被复选,Qt::ItemIsUserCheckable
- Enabled:列表项可用,Qt::ItemIsEnabled
- Tristate:自动改变列表项复选状态,Qt::ItemIsAutoTristate
QToolButton继承于一般的QAbstractButton,并在此基础上有新增的属性:
- popupMode属性:属性值为QToolButton::ToolButtonPopupMode.这个属性决定了弹出菜单的模式.
- QToolButton::DelayedPopup:按钮上没有任何附加的显示内容.如果按钮有下拉菜单,则按下按钮并延时一会儿后才显示下拉菜单.
- QToolButton::MenuButtonPopup:会在按钮右侧显示一个带箭头的下拉按钮.
- QToolButton::InstantPopup:会在按钮右下角显示一个很小的下拉箭头图标.
- toolButtonStyle属性:属性值是枚举类型Qt::ToolButtonTextBesideIcon.比欧仕工具按钮上文字标的显式方式.
- autoRaise属性:如果设置为true,按钮就没有边框,鼠标移动到按钮上才显示边框.
- arrowType属性:属性值是枚举类型Qt::ArrowType,默认值Qt::NoArrow.不会在上面显示内容.
除了与读写相关的一些接口函数,QToolButton类还有两个主要的函数:
- setDefaultAction()函数:这个函数用于为工具按钮设置关联的Action
- void QToolButton::setDefaultAction(QAction*action)
- setMenu()函数:这个函数用于为工具按钮设置下拉菜单,其函数原型定义如下:
- void QToolButton::setMenu(QMenu*menu)
QMenu是菜单类,它直接从QWidget继承而来.在Qt Designer中我们可以通过Action窗口创建菜单栏.
QMenu是管理菜单的类,它的父类是QWidget,菜单实际上是一种窗口.创建菜单主要会用到一下几个函数:
- void QWidget::addAction(QAction*action)//添加Action
- QAction *QMenu::addMenu(QMenu *menu)//添加菜单
- QAciton *QMenu::addSeparator()//添加一个分隔条
显示菜单可以使用exec()函数,其函数原型定义如下:
- QAction *QMenu::exec(const QPoint&p,QAction*action=nullptr)
参数p表示菜单左上角坐标,显示鼠标右键快捷菜单时,通常使用鼠标光标的当前位置QCursor::pos()作为参数p的值.
QListWidget组件的列表项是QListWidgetItem对象.QListWidgetItem没有父类,所以没有属性,但是它有一些读取函数与设置函数:
读取函数 | 设置函数 | 数据类型 | 设置函数的功能 |
---|---|---|---|
text() | setText() | QString | 设置项的文字 |
icon() | setIcon() | QIcon | 设置项的图标 |
data() | setData() | QVariant | 为项的不同角色设置数据 |
flags() | setFlags() | Qt::ItemFlag | 设置项的特性,是Qt::ItemFlag的组合 |
checkState() | setCheckState() | Qt::CheckState | 设置项的复选状态 |
isSelected() | setSelected() | bool | 设置为当前项 |
QListWidget的主要接口函数则见下:
分组 | 函数名 | 功能 |
---|---|---|
添加或删除项 | void addItem() | 添加一个项 |
void addItems() | 一次添加多个项 | |
void insertItem() | 在某一行前面插入一个项 | |
void insertItems() | 在某一行前面一次插入多个项 | |
QListWidgetItem *takeItem() | 从列表组件中移除一个项,并返回这个项 的对象指针,但不从内存中删除这个项 |
|
void clear() | 移除列表中所有的项,并从内存中删除 | |
项的访问 | QListWidgetItem *currentItem() | 返回当前项 |
void setCurrentItem() | 设置当前项 | |
QListWidgetItem *item() | 根据行号返回一个项 | |
QListWidgetItem *itemAt() | 根据屏幕坐标返回项 | |
int currentRow() | 返回当前行的行号 | |
void setCurrentRow() | 设置当前行 | |
int row() | 返回一个项所在行号 | |
int count() | 返回列表组件中项的个数 | |
排序 | void setSortingEnabled() | 设置列表是否可排序 |
bool isSortingEnabled() | 列表是否可排序 | |
void sortItems() | 对列表按照指定方式排序 |
QListWidget组件中的每一行是一个QListWidgetItem对象.
QListWidgetItem的函数setFlags()用于设置项的一些特性.其函数原型定义如下:
- void QListWidgetItem::setFlags(Qt::ItemFlags flags)
QListWidget定义的信号比较多,各信号的定义如下:
- void currentItemChanged(QListWidget *current,QListWidgetItem *previous)
- void currentRowChanged(int currentRow)
- void currentTextChanged(const QString& currentText)
- void itemSelectionChanged()
- void itemChanged(QListWidgetItem *item)
- void itemActivated(QListWidgetItem *item)
- void itemEntered(QListWidgetItem *item)
- void itemPressed(QListWidgetItem *item)
- void itemClicked(QListWidget *item)
- void itemDoubleClicked(QListWidgetItem *item)
每个继承自QWidget的类都有customContexrMenuRequested()信号,在一个组件上点击鼠标右键时,组件发射这个信号,用于请求创建快捷菜单.
要是QWidget组件在点击鼠标右键时发射customContextMenuRequested()信号,还需要设置contextMenuPolicy属性:
- Qt::NoContextMenu:组件没有快捷菜单,由其父容器组件处理
- Qt::PreventContextMenu:阻止快捷菜单,并且点击鼠标右键事件也不会交给父容器组件处理.
- Qt::DefaultContextMenu:默认的快捷菜单,QWidget::contextMenuEvent()事件被自动处理.
- Qt::ActionsContextMenu:自动根据QWidget::actions()返回的Action列表创建并显示快捷菜单.
- Qt::CustomContextMenu::组件发射customContextMenuRequested()信号,由用户编程实现快捷菜单.
下面是一个综合使用QToolButton和QListWidget的例子:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->actQuit,SIGNAL(triggered(bool)),this,SLOT(close()));
ui->toolButton->setDefaultAction(ui->actInitList);
ui->toolButton_2->setDefaultAction(ui->actDeleteList);
ui->toolButton_3->setDefaultAction(ui->actAddItem);
ui->toolButton_5->setDefaultAction(ui->actInsertItem);
ui->toolButton_6->setDefaultAction(ui->actDeleteItem);
ui->tbnSelAll_2->setDefaultAction(ui->actSelectAll);
ui->tbnSelNone_2->setDefaultAction(ui->actSelectNone);
ui->tbnSelInv_2->setDefaultAction(ui->actSelectInv);
QMenu* menuSelection=new QMenu(this);
menuSelection->addAction(ui->actSelectAll);
menuSelection->addAction(ui->actSelectInv);
menuSelection->addAction(ui->actSelectNone);
ui->tbnSelItems->setPopupMode(QToolButton::MenuButtonPopup);
ui->tbnSelItems->setMenu(menuSelection);
ui->tbnSelItems->setDefaultAction(ui->actSelection);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actInitList_triggered()
{
ui->listWidget_2->clear();
QIcon icon(QString(":/img/img/redo.jpg"));
bool chk=ui->chkEditable_2->isChecked();
for(int i=0;i<10;i++){
QListWidgetItem* aItem= new QListWidgetItem();
aItem->setIcon(icon);
aItem->setText(QString("Item %1").arg(i));
aItem->setCheckState(Qt::Checked);
if(chk)
aItem->setFlags(Qt::ItemIsEditable|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
else
aItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
ui->listWidget_2->addItem(aItem);
}
}
void MainWindow::on_actDeleteList_triggered()
{
ui->listWidget_2->clear();
}
void MainWindow::on_actAddItem_triggered()
{
QIcon icon(QString(":/img/img/redo.jpg"));
bool chk=ui->chkEditable_2->isChecked();
QListWidgetItem* aItem= new QListWidgetItem();
aItem->setIcon(icon);
aItem->setText(QString("New Item"));
aItem->setCheckState(Qt::Checked);
if(chk)
aItem->setFlags(Qt::ItemIsEditable|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
else
aItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
ui->listWidget_2->insertItem(ui->listWidget_2->currentRow(),aItem);
}
void MainWindow::on_actDeleteItem_triggered()
{
int row= ui->listWidget_2->currentRow();
delete ui->listWidget_2->takeItem(row);
}
void MainWindow::on_actInsertItem_triggered()
{
QIcon icon(QString(":/img/img/redo.jpg"));
bool chk=ui->chkEditable_2->isChecked();
QListWidgetItem* aItem= new QListWidgetItem();
aItem->setIcon(icon);
aItem->setText(QString("New Item"));
aItem->setCheckState(Qt::Checked);
if(chk)
aItem->setFlags(Qt::ItemIsEditable|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
else
aItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
ui->listWidget_2->addItem(aItem);
}
void MainWindow::on_listWidget_2_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
QString str="";
if(current!=NULL){
str+="当前项:"+current->text();
if(previous!=NULL)
str+=" 前一项:"+previous->text();
ui->litItemEdit_2->setText(str);
}
ui->plainTextEdit->appendPlainText(QString("currentChanged()信号被发射"));
}
void MainWindow::on_checkBox_clicked(bool checked)
{
ui->listWidget_2->setSortingEnabled(checked);
ui->toolButton_7->setEnabled(checked);
ui->toolButton_8->setEnabled(checked);
}
void MainWindow::on_toolButton_7_clicked(bool checked)
{
ui->listWidget_2->sortItems(Qt::AscendingOrder);
}
void MainWindow::on_toolButton_8_clicked(bool checked)
{
ui->listWidget_2->sortItems(Qt::DescendingOrder);
}
void MainWindow::on_pushButton_clicked()
{
ui->plainTextEdit->clear();
}
void MainWindow::on_pushButton_2_clicked()
{
ui->plainTextEdit->appendPlainText(QString(""));
}
void MainWindow::on_listWidget_2_itemDoubleClicked(QListWidgetItem *item)
{
ui->plainTextEdit->appendPlainText(QString("doubleClicked信号发射")+item->text());
}
void MainWindow::on_listWidget_2_customContextMenuRequested(const QPoint &pos)
{
Q_UNUSED(pos);
QMenu* menuList= new QMenu(this);
menuList->addAction(ui->actInitList);
menuList->addAction(ui->actDeleteItem);
menuList->addAction(ui->actDeleteList);
menuList->addAction(ui->actInsertItem);
menuList->addAction(ui->actAddItem);
menuList->addSeparator();
menuList->addAction(ui->actSelectAll);
menuList->addAction(ui->actSelectNone);
menuList->addAction(ui->actSelectInv);
menuList->exec(QCursor::pos());
delete menuList;
}
void MainWindow::on_actSelectAll_triggered()
{
int cnt= ui->listWidget_2->count();
for(int i=0;i<cnt;i++){
QListWidgetItem *aItem=ui->listWidget_2->item(i);
aItem->setCheckState(Qt::Checked);
}
}
void MainWindow::on_actSelectNone_triggered()
{
int cnt= ui->listWidget_2->count();
for(int i=0;i<cnt;i++){
QListWidgetItem *aItem=ui->listWidget_2->item(i);
aItem->setCheckState(Qt::Unchecked);
}
}
void MainWindow::on_actSelectInv_triggered()
{
int cnt= ui->listWidget_2->count();
for(int i=0;i<cnt;i++){
QListWidgetItem *aItem=ui->listWidget_2->item(i);
if(aItem->checkState()==Qt::Checked)
aItem->setCheckState(Qt::Unchecked);
else if(aItem->checkState()==Qt::Unchecked)
aItem->setCheckState(Qt::Checked);
}
}
QTreeWidget
QTreeWidget简介
QTreeWidget是一种Item Widget组件.QTreeWidget组件被称为树形组件,它的项(item)被称为节点,一个树形组件内的所有节点组成的结构被称为目录树.
树形组件适合显示具有层级结构的数据,例如,Windows资源管理器中显示的文件系统.
- QTreeWidget树形组件:实例使用树形组件管理目录与图片文件,可以添加或删除节点.
- QDockWidget停靠组件:QDockWidget是可以在窗口上停靠或桌面上层浮动的组件.
- QLabel标签组件:窗口右侧是一个QScrollArea组件,在它上面放置一个标签,为标签设置一个QPixmap对象显示图片.通过QPixmap的接口函数可进行图片缩放.
QDockWidget的主要属性有:
- floating属性:表示停靠区组件是否处于浮动状态.
- features属性:停靠区组件的特性.其为Qt::DockWidgetAreas枚举值的组合.
- allowedAreas属性:允许停靠的区域,可以设置在窗口左侧,右侧,顶部,底部停靠,也可以设置不允许停靠.
- windowTitle属性:停靠区窗口的标题.
一个QTreeWidget组件的显示内容分为表头和目录树两部分,表头和目录树都是QTreeWidgetItem对象.
QTreeWidget可以使用QTreeWidgetItem或简单的文字作为表头.
如果只是简单地设置表头文字,可以使用函数setHeaderLabels()将字符串列表作为表头各列的标题.
- void QTreeWidget::setHeaderLabels(const QStringList &labels)
如果使用QTreeWidget作为表头,则可以使用函数setHeaderItem()设计表头,还可以使用headerItem()返回.
- void QTreeWidget::setHeaderItem(QTreeWidgetItem *item)
- QTreeWidgetItem *QTreeWidget::headerItem()
如果使用QTreeWidgetItem对象作为表头,就可以通过QTreeWidgetItem的接口函数设置表头属性.
目录树里一行就是一个节点,节点是QTreeWidgetItem对象.节点可以有直接点,子节点就是下一级的节点.
目录树里最上层的节点称为顶层节点,顶层节点没有父节点.目录树里可以有任意多个顶层节点.相关函数如下:
- int topLevelItemCount()//返回顶层节点个数
- void addTopLevelItem(QTreeWidgetItem *item)//添加一个顶层节点
- void insertTopLevelItem(int index, QTreeWidgetItem *item)//插入一个顶层节点
- int indexOfTopLevelItem(QTreeWidgetItem *item)//返回一个顶层节点的索引号
- QTreeWidgetItem *topLevelItem(int index)//根据index返回一个顶层节点
- QTreeWidgetItem *takeTopLevelItem(int index)//移除一个顶层节点,但是不删除
获得一个顶层节点后,就可以访问它的所有子节点.所有次级节点都直接或间接挂靠在某个顶层节点下面.
目录树中还有一个隐藏的根节点,其可以看作所有顶层节点的父节点.通过invisibleRootItem()可以访问它:
- QTreeWidgetItem *QTreeWidget::invisibleRootItem().
使用这个结点就可以通过QTreeWidgetItem类的接口函数访问所有顶层节点.
QTreeWidget也还有一些其他的常用函数:
- int columnCount()//返回表头列数
- void setColumnCount(int columns)//设置表头列数
- void sortItems(int columns,Qt::SortOrder order)//将目录树按照某一列排序
- int sortColumn()//返回用于排序的列的编号
- QTreeWidgetItem *currentItem()//返回当前节点
- QList<QTreeWidgetItem*> selectedItems()//返回选择的节点列表
如果树形组件允许多选,函数selectedItems()会返回选择的节点的列表.通过QTreeWidget的上层父类QAbstractItemView的selectionMode属性能够设置选择模式,可以设置为多选.
QTreeWidget有如下几个共有槽函数:
- void clear()//清除整个目录树
- void collapseItem(const QTreeWidgetItem *item)//折叠节点
- void expandItem(const QTreeWidget *item)//展开节点
- void scrollToItem(const QTreeWidget *item,QAbstractItemView::ScrollHint hint=EnsureVisible)
//用于保证节点item可见,必要时自动移动卷滚条
QTreeWidget类有如下几个信号:
- void currentItemChanged(QTreeWidgetItem *current,QTreeWidgetItem *previous)
//当选中项变化时发射 - void itemActivated(QTreeWidgetItem *item,int column)//双击节点或按下enter时
- 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()//用户选择的项改变
为了更好地理解,这里需要对几个信号的发射条件进行区分:
currentItemChanged()信号在当前节点发生变化时被发射,current是当前节点,previous是之前节点.
itemChanged()信号在某节点的某一列的属性发生变化时被发射.
itemClicked()信号在点击节点时被发射,不管当前节点的行和列有没有变化都会触发此信号.
itemSelectionChanged()信号在用户选择的节点发生变化时被发射.
下面给出一个测试程序说明这些差异:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
for(int i=0;i<10;i++){
QTreeWidgetItem* new_item=new QTreeWidgetItem();
new_item->setText(0,QString("编号"));
new_item->setTextAlignment(0,Qt::AlignHCenter);
new_item->setTextAlignment(0,Qt::AlignVCenter);
new_item->setCheckState(0,Qt::Checked);
new_item->setText(1,QString("姓名"));
new_item->setTextAlignment(1,Qt::AlignHCenter);
new_item->setTextAlignment(1,Qt::AlignVCenter);
new_item->setCheckState(1,Qt::Checked);
ui->treeWidget->addTopLevelItem(new_item);
}
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_treeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{
ui->plainTextEdit->appendPlainText(QString("currentItemChanged:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(current)));
return;
}
void MainWindow::on_treeWidget_itemActivated(QTreeWidgetItem *item, int column)
{
ui->plainTextEdit->appendPlainText(QString("itemActivated:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(item)));
return;
}
void MainWindow::on_treeWidget_itemChanged(QTreeWidgetItem *item, int column)
{
ui->plainTextEdit->appendPlainText(QString("itemChanged:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(item)));
return;
}
void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, int column)
{
ui->plainTextEdit->appendPlainText(QString("itemClicked:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(item)));
return;
}
void MainWindow::on_treeWidget_itemCollapsed(QTreeWidgetItem *item)
{
ui->plainTextEdit->appendPlainText(QString("itemCollapsed:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(item)));
return;
}
void MainWindow::on_treeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column)
{
ui->plainTextEdit->appendPlainText(QString("itemDoubleClicked:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(item)));
return;
}
void MainWindow::on_treeWidget_itemEntered(QTreeWidgetItem *item, int column)
{
ui->plainTextEdit->appendPlainText(QString("itemEntered:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(item)));
return;
}
void MainWindow::on_treeWidget_itemExpanded(QTreeWidgetItem *item)
{
ui->plainTextEdit->appendPlainText(QString("itemExpanded:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(item)));
return;
}
void MainWindow::on_treeWidget_itemPressed(QTreeWidgetItem *item, int column)
{
ui->plainTextEdit->appendPlainText(QString("itemPressed:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(item)));
return;
}
void MainWindow::on_treeWidget_itemSelectionChanged()
{
ui->plainTextEdit->appendPlainText(QString("itemSelectionChanged"));
return;
}
QTreeWidgetItem简介
QTreeWidget组件的表头和目录树节点都是QTreeWidgetItem类对象,对目录树节点的操作主要通过QTreeWidgetItem类的接口函数实现.
QTreeWidgetItem类没有父类,它只用来存储结点的数据和各种属性.绘制目录树由QTreeWidget实现.
QTreeWidgetItem类有多种参数形式的构造函数,较简单的一种定义如下:
- QTreeWidgetItem(int type=Type)
可以传递一个整数表示结点的类型,可以通过成员函数type()返回这个类型.
在创建节点时,还可以传递字符串列表作为节点各列的文字:
- QTreeWidgetItem(const QStringList &strings,int type=Type)
也可以在某个节点下创建子节点:
- QTreeWidgetItem(QTreeWidgetItem *parent,int type=Type)
还可以直接在树形组件里创建顶层节点:
- QTreeWidgetItem(QTreeWidget *parent,int type=Type)
创建一个节点后,可以通过一些函数对其进行操作:
- void setBackground(int column,const QBrush &brush)
- void setForeground(int column,const QBrush &brush)
- void setText(int column,const QString &text)
- void setTextAlignment(int column,const QString &toolTip)
- void setStatusTip(int column,const QString &statusTip)
- void setIcon(int column,const QIcon &icon)
- void setCheckState(int column,Qt::CheckState state)
- void setFont(int column,const QFont &font)
Qt::Alignment的取值有:
- Qt::AlignLeft:水平方向靠左
- Qt::AlignRight:水平方向靠右
- Qt::AlignTop:垂直方向靠顶部
- Qt::AlignButton:垂直方向靠底部
- Qt::AlignHCenter:水平方向居中
- Qt::AlignVCenter:垂直方向居中
- Qt::AlignCenter:水平垂直方向居中
- Qt::AlignJustify:水平方向调整间距两端对齐
上面设置函数当然有相应的读取函数,同样需要传递参数column.
QTreeWidgetItem还有一个函数setData()用于为节点中的某一列设置用户数据,这个数据是不显示在界面上的.
- void setData(int column,int role,const QVariant &value)
- QVariant data(int column,int role)
参数role是用户数据角色,可以使用常量Qt::UserRole定义第一个用户数据,使用Qt::UserRole+1定义第二个用户数据.
用户数据是QVariant类型,可以存储各种类型的数据.
QTreeWidgetItem的一些常用的接口函数有:
- int type()//返回创建节点时设置的type
- setFlags(Qt::ItemFlags flags)//设置结点的标志
- Qt::ItemFlags flags()//读取节点的标志
- void setExpanded(bool expand)
- bool isExpanded()
- void setDisabled(bool disabled)
- bool isDisabled()
- void setHidden(bool hide)
- bool isHidden()
- void setSelected(bool select)
- bool isSelected()
注意,函数type()所返回的是创建节点时传递的type参数,节点创建后就不能更改.
Qt::ItemFlags的取值有:
- Qt::NoItemFlags//没有标志
- Qt::ItemIsSelectable//节点可以被选中
- Qt::ItemIsEditable//节点可以编辑
- Qt::ItemIsDragEnabled//节点可以被拖动
- Qt::ItemIsDropEnabled//节点可以接收被拖动的对象
- Qt::ItemIsUserCheckable//节点可以被复选
- Qt::ItemIsEnabled//节点可用
- Qt::ItemIsAutoTristate//自动决定三种复选状态
- Qt::ItemIsUserTristate//用户决定三种复选状态
- Qt::ItemNeverHasChildren//不允许有子节点
而且这些节点可以用|组合.
一个节点可以有任意多个子节点,可以添加,插入或移除节点.
QTreeWidgetItem类中用于操作子节点的接口函数主要有以下几个:
- void addChild(QTreeWidgetItem *child)//添加一个子节点
- QTreeWidgetItem *child(int index)//根据序号返回一个子节点
- int childCount()//返回子节点的个数
- int indexOfChild(QTreeWidgetItem *child)//返回一个子节点的索引号
- void insertChild(int index,QTreeWidgetItem *child)//插入一个子节点
- void removeChile(QTreeWidget *child)//移除一个子节点
- QTreeWidgetItem *takeChild(int index)//移除一个子节点,并返回节点指针
- QTreeWidgetItem *parent()//返回父节点
QLabel和Qpixmap的使用
对于QPixmap类变量,QPixamp::load()直接从一个文件加载图片.
QPixmap类存储图片数据,它有以下几个函数可以用于缩放图片:
- scaledToHeight(int height):返回一个缩放后的图片副本,图片按height缩放
- scaledToWidth(int width):返回一个缩放后的图片副本,图片按width缩放
- scaled(int width,int height):返回一个缩放后的图片副本,默认不保持比例
设置图片到标签的,函数原型为:void QLabel::setPixmap(const QPixmap&)
将标签放在一个QScrollArea组件上,当图片过大时,QScrollArea将会出现卷滚条.
QDockWidget的操作
程序运行时,窗口上的QDockWidget组件可以被拖动.
QDockWidget类有如下几个信号:
- void allowedAreasChanged(Qt::DockWidgetAreas allowedAreas)//allowedAreas属性值变化时
- void dockLocationChanged(Qt::DockWidgetArea area)//移动到其他停靠区时
- void featuresChanged(QDockWidget::DockWidgetFeatures features)//features属性变化时
- void topLevelChanged(bool topLevel)//floating属性值变化时
- void visiblityChanged(bool visible)//visible属性值变化时
下面最终给出综合使用QTreeWidget与QPixmap的例子:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
#include <QSpinBox>
#include <QTreeWidgetItem>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void changeItemCaption(QTreeWidgetItem *item);
void displayImage(QTreeWidgetItem* item);
void on_actAddFolder_triggered();
void on_actAddFile_triggered();
void on_actDeleteNode_triggered();
void on_treeWidget_2_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
void on_actForeachNode_triggered();
void on_actSuitWidth_triggered();
void on_actSuitHeight_triggered();
void on_actReal_triggered();
void on_actBigger_triggered();
void on_actSmaller_triggered();
void on_actVisiable_triggered(bool checked);
void on_actFloating_triggered(bool checked);
private:
QLabel *lbFileName,*lbNodeText;
QSpinBox *spinRadio;
QPixmap m_pixmap;
float radio;
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->treeWidget_2->clear();
//header
QTreeWidgetItem *header=new QTreeWidgetItem();
header->setText(0,"目录与文件");
header->setText(1,"节点类型");
header->setText(2,"最后修改日期");
header->setTextAlignment(0,Qt::AlignHCenter|Qt::AlignVCenter);
header->setTextAlignment(1,Qt::AlignHCenter|Qt::AlignVCenter);
ui->treeWidget_2->setHeaderItem(header);
//root node
QIcon icon(QString(":/icons/img/close.jpg"));
QTreeWidgetItem *topItem= new QTreeWidgetItem();
topItem->setIcon(0,icon);
topItem->setText(0,"/...");
topItem->setText(1,"根目录");
topItem->setText(2,"");
topItem->setFlags(Qt::ItemIsSelectable|
Qt::ItemIsUserCheckable|
Qt::ItemIsEnabled|
Qt::ItemIsAutoTristate
);
topItem->setCheckState(0,Qt::Checked);
ui->treeWidget_2->addTopLevelItem(topItem);
//status bar
lbNodeText= new QLabel("节点标题",this);
lbNodeText->setMinimumWidth(200);
ui->statusbar->addWidget(lbNodeText);
spinRadio=new QSpinBox(this);
spinRadio->setRange(0,2000);
spinRadio->setValue(100);
spinRadio->setSuffix("%");
spinRadio->setReadOnly(true);
spinRadio->setButtonSymbols(QAbstractSpinBox::NoButtons);
ui->statusbar->addPermanentWidget(spinRadio);
lbFileName=new QLabel("文件名",this);
ui->statusbar->addPermanentWidget(lbFileName);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::changeItemCaption(QTreeWidgetItem *item)
{
QString str="*"+item->text(0);
item->setText(0,str);
if(item->childCount()>0)
for(int i=0;i<item->childCount();i++)
changeItemCaption(item->child(i));
else
return;
}
void MainWindow::displayImage(QTreeWidgetItem *item)
{
QString filename=item->data(0,Qt::UserRole).toString();
lbFileName->setText(filename);
lbNodeText->setText(item->text(0));
m_pixmap.load(filename);
ui->actSuitWidth->trigger();
ui->actSuitHeight->setEnabled(true);
ui->actSuitWidth->setEnabled(true);
ui->actBigger->setEnabled(true);
ui->actSmaller->setEnabled(true);
ui->actReal->setEnabled(true);
}
#include <QFileDialog>
#include <QVariant>
void MainWindow::on_actAddFolder_triggered()
{
QString dir= QFileDialog::getExistingDirectory();
if(dir.isEmpty())
return;
QTreeWidgetItem *parItem=ui->treeWidget_2->currentItem();
if(parItem==nullptr)
return;
if(parItem->text(1)!="图片"){
int cnt=dir.length();
int i=dir.lastIndexOf("/");
QString nodeName=dir.right(cnt-i-1);
QTreeWidgetItem *item=new QTreeWidgetItem();
QIcon icon(QString(":/icons/img/close.jpg"));
item->setIcon(0,icon);
item->setText(0,nodeName);
item->setText(1,"目录");
item->setText(2,"");
item->setFlags(Qt::ItemIsSelectable|
Qt::ItemIsUserCheckable|
Qt::ItemIsEnabled|
Qt::ItemIsAutoTristate
);
item->setData(0,Qt::UserRole,QVariant(dir));
item->setCheckState(0,Qt::Checked);
parItem->addChild(item);
}
}
void MainWindow::on_actAddFile_triggered()
{
QStringList files=QFileDialog::getOpenFileNames(this,"选择文件","","Images(*.jpg;*.png)");
if(files.isEmpty())
return;
QTreeWidgetItem *parItem,*item;
item=ui->treeWidget_2->currentItem();
if(item->text(1)!="图片")
parItem=item;
else
parItem=item->parent();
for(int i=0;i<files.size();i++){
QString fileName= files.at(i);
QFileInfo fileInfo(fileName);
QString nodeText=fileInfo.fileName();
QDateTime dateTime=fileInfo.lastModified();
QTreeWidgetItem *item=new QTreeWidgetItem();
QIcon icon(fileInfo.filePath());
item->setIcon(0,icon);
item->setText(0,nodeText);
item->setText(1,"图片");
item->setText(2,dateTime.toString("yyyy-MM-dd"));
item->setFlags(Qt::ItemIsSelectable|
Qt::ItemIsUserCheckable|
Qt::ItemIsEnabled|
Qt::ItemIsAutoTristate
);
item->setData(0,Qt::UserRole,QVariant(fileName));
item->setCheckState(0,Qt::Checked);
parItem->addChild(item);
}
parItem->setExpanded(true);
}
void MainWindow::on_actDeleteNode_triggered()
{
QTreeWidgetItem *item,*parItem;
item=ui->treeWidget_2->currentItem();
parItem=item->parent();
if(item!=nullptr){
parItem->removeChild(item);
delete item;
}
else
return;
}
void MainWindow::on_treeWidget_2_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{
if(current==nullptr||current==previous)
return;
QString itemType=current->text(1);
if(itemType=="根目录"){
ui->actAddFile->setEnabled(true);
ui->actAddFolder->setEnabled(true);
ui->actDeleteNode->setEnabled(false);
}
else if(itemType=="目录"){
ui->actAddFile->setEnabled(true);
ui->actAddFolder->setEnabled(true);
ui->actDeleteNode->setEnabled(true);
}
else if(itemType=="图片"){
ui->actAddFile->setEnabled(false);
ui->actAddFolder->setEnabled(true);
ui->actDeleteNode->setEnabled(true);
displayImage(current);
}
}
void MainWindow::on_actForeachNode_triggered()
{
QTreeWidgetItem *item,*parItem;
item=ui->treeWidget_2->currentItem();
changeItemCaption(item);
}
void MainWindow::on_actSuitWidth_triggered()
{
int width=ui->scrollArea->width()-30;
int realWidth=m_pixmap.width();
radio=float(width)/realWidth;
spinRadio->setValue(radio*100);
QPixmap pix=m_pixmap.scaledToWidth(width);
ui->label->setPixmap(pix);
}
void MainWindow::on_actSuitHeight_triggered()
{
int height=ui->scrollArea->height()-30;
int realHeight=m_pixmap.height();
radio=float(height)/realHeight;
spinRadio->setValue(radio*100);
QPixmap pix=m_pixmap.scaledToHeight(height);
ui->label->setPixmap(pix);
}
void MainWindow::on_actReal_triggered()
{
int height=ui->scrollArea->height()-30;
int realHeight=m_pixmap.height();
radio=float(height)/realHeight;
spinRadio->setValue(radio*100);
QPixmap pix=m_pixmap.scaledToHeight(realHeight);
ui->label->setPixmap(pix);
}
void MainWindow::on_actBigger_triggered()
{
radio*=1.2;
int width=radio*m_pixmap.width();
int height=radio*m_pixmap.height();
ui->label->setPixmap(m_pixmap.scaled(width,height));
spinRadio->setValue(radio*100);
}
void MainWindow::on_actSmaller_triggered()
{
radio*=0.8;
int width=radio*m_pixmap.width();
int height=radio*m_pixmap.height();
ui->label->setPixmap(m_pixmap.scaled(width,height));
spinRadio->setValue(radio*100);
}
void MainWindow::on_actVisiable_triggered(bool checked)
{
ui->dockWidget_2->setVisible(checked);
}
void MainWindow::on_actFloating_triggered(bool checked)
{
ui->dockWidget_2->setFloating(checked);
}
QTableWidget
QTableWidget是QTableView的便利类,类QTableWidget的属性和接口主要是父类中定义的.
QTableWidget还新增了两个属性,rowCount表示数据区行数,columnCount表示数据区列数.
QTableWidget还定义了如下的几个公有槽函数:
- void insertColumn(int column)//在列号column处插入空行
- void removeColumn(int column)//移除列号column的一列
- void insertRow(int row)//在行号row处插入空行
- void removeRow(int row)//移除行号row的一行
QTableWidget表格的一个单元格通常关联一个QTableWidgetItem对象.
要为表格的一个单元格设置项,一般是先创建一个QTableWidgetItem对象item,设置各种属性,然后通过setItem()将其设置至某个单元格.其函数原型如下:
- void setItem(int row,int column,QTableWidgetItem *item)
要移除一个单元格关联的项,可以使用含税takeItem()来实现,其函数原型如下:
- QTableWidgetItem *takeItem(int row,int column)
函数takeItem会移除单元格关联的项,并返回这个项的对象指针,但是不删除这个对象.
QTableWidget定义了两个公有槽:
- void clear()
- void clearContents()
QTableWidget表格数据区有一个当前单元格,也就是获得输入焦点的单元格.相关函数如下:
当前单元格关联的QTableWidgetItem对象就是当前项,可以返回当前项的对象指针.也可以设置某个QTableWidgetItem对象为当前项,以改变当前单元格的位置.
- int currentRow()//返回当前单元格的行号
- int currentColumn()//返回当前单元格的列号
- void setCurrentCell(int row,int column)//通过行号和列号设置当前单元格位置
- QTableWidgetItem *currentItem()//返回当前项
- void setCurrentItem(QTableWidgetItem *item)//设置当前项,改变当前单元格位置
- QTableWidgetItem *item(int row,int column)//通过行号和列号返回项
- int row(const QTableWidgetItem *item)//返回一个项的行号
- int column(const QTableWidgetItem *item)//返回一个项的列号
- void setHorizontalHeaderItem(int column)//为某列设置项
- QTableWidgetItem *horizontalHeaderItem(int column)//返回column列的表头项
- QTableWidgetItem *takeHorizontalHeaderItem(int column)//移除column列的表头项
- void setHorizontalHeaderLabels(const QStringList &labels)
//使用字符串列表的每一行作为水平表头每一列的标题 - setVerticalHeaderItem(int row,QTableWidgetItem *item)//设置row的表头项
- QTableWidgetItem *verticalHeaderItem(int row)//返回row的表头项
- QTableWidgetItem *takeVerticalHeaderItem(int row)//移除row的表头项
- void setVerticalHeaderLabels(const QStringList &labels)//用一个字符串列表设置表头标题
QTableWidget定义了较多的信号:
- void cellActivated(int row,int column)//单元格被激活时
- void cellChanged(int row,int column)//单元格的数据改变时
- void cellClicked(int row,int column)//在单元格上单击鼠标时
- void cellDoubleClicked(int row,int column)//在单元格上双击鼠标时
- void cellEntered(int row,int column)//鼠标移动到一个单元格上时
- void cellPressed(int row,int column)//在单元格上按下鼠标左键或右键时
- void currentCellChanged(int currentRow,int currentColumn,int previousRow,int previousColumn)
//当前单元格发生切换时 - void itemActivated(QTableWidgetItem *item)//项被激活时
- void itemChanged(QTableWidgetItem *item)//项内容改变时
- void itemClicked(QTableWidgetItem *item)//项被点击
- void itemDoubleClicked(QTableWidgetItem *item)//项被双击
- void itemEntered(QTableWidgetItem *item)//鼠标移动到一个项上时
- void itemPressed(QTableWidgetItem *item)//在项上按下鼠标左键或右键时
- void currentItemChanged(QTableWidgetItem *current,QTableWidgetItem *previous)
//当前项发生改变时 - void itemSelectionChanged()//选择的项发生变化时
QTableWidgeItem关联的每个单元格都需要关联一个QTableWidgetItem对象.
QTableWidgetItem有多种参数形式的构造函数,其中的三种构造函数定义如下:
- QTableWidgetItem(const QIcon &icon,const QString &text,int type=Type)
- QTableWidgetItem(const QString &text,int type=Type)
- QTableWidgetItem(int type=Type)
创建QTableWidgetItem对象后,通过QTableWidget::setItem()函数可以将其设置为某个单元格的项.
QTableWidgetItem对象有一些接口函数用于设置项的特性:
- void setText(const QString &text)//设置单元格显示文字
- void setTextAlignment(int alignment)//设置文字对其方式
- void setBackground(const QBrush &brush)//设置背景色
- void setForeground(const QBrush &brush)//设置前景色
- void setFont(const QFont &font)//设置字体
- void setIcon(const QIcon &icon)//设置图标
- void setCheckState(Qt::CheckState state)//设置复选状态
- void setToolTip(const QString &toolTip)//设置toolTip
- void setStatusTip(const QString &statusTip)//设置statusTip
- void setFlags(Qt::ItemFlags flags)//设置标志
- void setData(int role,const QVariant &value)//设置数据
- int row()//返回项所在单元格行号
- int column()//返回项所在单元格的列号
- void setSelected(bool select)//设置项的选中状态
- bool isSelected()//项是否被选中
- QTableWidget *tableWidget()//返回项所在的QTableWidget对象指针
后记:好长的一章,一章更比四章强( )