[Basic] Qt Notes
Qt
简单来说,Qt是一个跨平台的 C++ 开发库,它提供了一系列的工具、类库和开发环境,使开发者能够轻松地创建图形界面应用程序、嵌入式应用程序和其他各种类型的软件。
从图形界面框架角度来看,Qt并不是唯一的存在。对我来说,最早接触的应该是win32api(《Windows程序设计第五版珍藏版》),包括类似的button,dialog的内置组件,图形绘制的GDI,window底层支持的多媒体等,当时是用c语言编写的,编程相对较为复杂。然后是java的java swing(《java核心技术卷》),拥有类似的框架结构,基于MVC的数据交互,继承Abstract组件拓展功能,基于java3d的图形渲染,但基于java便意味着性能的受限,以至于很少有人用于商业。然后是win32api后来衍生的mfc和wpf(《深入浅出wpf》),可以基于c#和微软提供的一系列生态圈完成更高效的开发,但这意味着只适用于windows系统。而说回Qt,相对于上述的框架,其最大的优势便是跨平台和其完整的生态,包括IDE、工具和大量的文档。当然,随着Electron类似的基于nodejs的跨平台桌面应用程序的开源框架的兴起,Qt的优势也许只剩下性能一条。
从Qt本身的学习路线来看,主要包括Qt Widget传统组件UI、Qt Quick声明性界面设计、Qt生态圈三大部分。如果拥有其他图形界面框架的基础,Qt Widget会相对简单,一般都包括:事件系统、组件系统、3d画布等核心部分,Qt本身可能还需要注意自定义的一套容器、文件读取、多线程、网络实现。而Qt Quick的核心理念类似于HTML5的语义化编程,在某些人看来,和WPF的xaml一样,也许只是对html的拙劣模仿。学习时注意qml的语法和qml解析即可。至于Qt生态圈,更多的是qmake(Qt6转向cmake)和qt creater、qt designer的学习。当然,如果需要更加深入地学习,最佳实践和性能优化是绕不开的话题。
本文是Qt的学习笔记,旨在随时翻阅,仅代表个人看法,持续更新。
Qt Widget
Qt框架中用于创建传统桌面应用程序图形界面的一组C++类库。
MVC
MVC在各种UI框架中十分常见,与MVC 设计模式类似,Qt引入了模型/视图结构用于完成数据与界面的分离,即 InterView框架 。但不同的是,Qt的InterView框架把视图和控制器部件结合在一起,使得框架更为简洁。为了灵活地处理用户输入,InterView框架引入了代理(delegate)。通过使用代理,能够自定义数据条目的显示和编辑方式。 Qt的模型/视图结构分为三部分:模型(Model)、视图(View)和代理(Delegate)。其中,模型与数据源通信,并为其他部件提供接口。而视图从模型中获得用来引用数据条目的模型索引(Model Index)。在视图中,代理负责绘制数据条目,当编辑条目时,代理和模型直接进行通信。模型/视图/代理之间通过信号和槽进行通信。它们之间的关系如下:
- 数据发生改变时,模型发出信号通知视图。
- 用户对界面进行操作,视图发出信号。
- 代理发出信号告知模型和视图编辑器目前的状态。
Model
InterView框架中的所有模型都基于抽象基类QAbstractItemModel类,此类由QProxyModel、QAbstractListModel、 QAbstractTableModel、QAbstractProxyModel、QDirModel、QFileSystemModel、QHelpContentModel和 QStandardItemModel类继承。其中,QAbstractListModel类和QAbstractTableModel类是列表和表格模型的抽象基类,如果需要实现列表或表格模型,则应从这两个类继承。完成 QStringList存储的QStringListModel继承自QAbstractListModel类,而与数据库有关的QSqlQueryModel类继承自 QAbstractTableModel类。QAbstractProxyModel类是代理模型的抽象类。QDirModel类是文件和目录的存储模型。
View
InterView框架中的所有视图都基于抽象基类QAbstractItemView 类,此类由QColumnView、QHeaderView、QListView、QTableView和QTreeView类继承。其中,QListView类由 QUndoView类和 QListWidget类继承。QTableView类由QTableWidget类继承。QTreeView类由QTreeWidget类继承。而QListWidget类、QTableWidget类和 QTreeWidget类实际上已经包含了数据,是模型/视图集成在一起的类。
Delegate
InterView框架中的所有代理都基于抽象基类QAbstractItemDelegate类,此类由QItemDelegate和 QStyledltemDelegate类继承。其中,QItemDelegate类由表示数据库中关系代理的QSqlRelationalDelegate类继承。
Components
Qt Widget提供了许多预定义的UI组件,这些组件可用于创建应用程序的不同界面元素。
Widget
区域划分:
Buttons
继承关系:
Input Widgets
继承关系:
QDateTime
Date/Time Edit对应于QDateTime类,在Qt 5中可以使用它来获得系统时间。通过QDateTime:currentDateTime()来获取本地系统的时间和日期信息。可以通过date()和time(来返回 datetime中的日期和时间部分,典型代码如下:
QDebug() << (new QDateTime(QDateTime::currentDateTime()))->date().toString();
Display Widgets
Label
setFrameStyle(QFramePanel|QFrame::Sunken): 设置控件的风格。setFrameStyle()是 QFrame的方法,参数以或()的方式设定控件的面板风格,由形状(QFrame:Shape)和阴影(QFrame::shadow)两项配合设定。其中,形状包括六种,分别是NoFrame、Panel、Box、HLine、VLine 及WinPanel;阴影包括三种,分别是Plain、Raised和 Sunken。
Text Browser
Text Browser对应于QTextBrowser类。QTextBrowser类继承自QTextEdit,而且仅是只读的,对里面的内容并不能进行更改,但是相对于QTextEdit来讲,它还具有链接文本的作用。
Spacers
Containers
Item Views
继承关系:
Item Widgets
View和Widget区别:
QPalette
在实际应用中,经常需要改变某个控件的颜色外观,如背景、文字颜色等。Qt提供的调色板类 QPalette专门用于管理对话框的外观显示。QPalette类相当于对话框或控件的调色板,它管理着控件或窗体的所有颜色信息。每个窗体或控件都包含一个QPalette对象,在显示时,按照它的 QPalette对象中对各部分各状态下的颜色的描述进行绘制。
ColorGroup 颜色状态。
- QPalette::Active:获得焦点的状态。
- QPalette::Inactive:未获得焦点的状态。
- OPalette::Disable:不可用状态。
其中,Active状态与 Inactive状态在通常情况下,颜色显示是一致的,也可以根据需要设置为不一样的颜色。
ColorRole ColorRole指的是颜色主题,即对窗体中不同部位颜色的分类。例如,QPalette:: Window是指背景色,QPalette::WindowText指的是前景色,等等。QPalette类使用最多、最重要的函数是setColor()函数,其原型如下:
void QPalette::setColor (ColorGroup group, ColorRole role, const QColor&color);
对主题颜色进行设置的同时,还区分了状态,即对某个主题在某个状态下的颜色进行了设置:
void QPalette::setcolor(ColorRole role, const QColor & color);
只对某个主题的颜色进行设置,并不区分状态。
SetBrush
QPalette类同时还提供了setBrush()函数,通过画刷的设置对显示进行更改,这样就有可能使用图片而不仅是单一的颜色来对主题进行填充。Qt之前的版本中有关背景色设置的函数如setBackgroundColor()或前景色设置的函数如setForegroundColor()在 Qt 5中都被废止,统一由QPalette类进行管理。例如,setBackgroundColor()函数可由以下语句代替:
XXX->setAutoFillBackground(true);
QPalette p=XXX->palette();
p.setColor(QPalette::Window,color);
xxx->setPalette(p);
Timer
QTime的currentTime()函数用于获取当前的系统时间。QTime的 toString()函数用于将获取的当前时间转换为字符串类型。为便于显示,toString()函数的参数需指定转换后时间的显示格式。
- H/h:小时(若使用H表示小时,则无论何时都以24小时制显示小时;若使用h表示小时,则当同时指定AM/PM时,采用12小时制显示小时,其他情况下仍采用24小时制进行显示)。
- m:分钟。
- s:秒钟。
- AP/A:显示AM或PM。
- Ap/a:显示 am 或 pm。
可根据实际显示需要进行格式设置。QTime 的 toString()函数也可直接利用Qt::DateFormat作为参数指定时间显示的格式,如 Qt::TextDate、Qt::ISODate、Qt::LocaleDate等。
Dialog
-QFileDialog
文件对话框。相关操作函数:
最简单的点击和获取文件信息:
void Dialog::showFile(){
Qstring s = QFileDialog::get0penFileName (this, "open file dialog", "/",
"C++ files (*.cpp);;C files(*.c);;Head files(*.h)");
fileLineEdit->setText (s);
getOpenFileName
获取用户选择的文件名。
QString QFileDialog::getOpenFileName
Qwidget* parent=0, //标准文件对话框的父窗口
const QString & caption=QString(),//标准文件对话框的标题名
const QString & dir=QString(),
const QString &filter=QString(),
Ostring * selectedFilter=0,//用户选择的过滤器通过此参数返回
Options options=0 //选择显示文件名的格式,默认是同时显示目录与文件名
-QColorDialog
颜色选择对话框。
getColor
获得用户选择的颜色值。
QColor getColor
const QColor& initial=Qt::white,
Qwidget* parent=0//标准颜色对话框的父窗口
-QFontDialog
getFont
getFont()函数是标准字体对话框 QFontDialog类的一个静态函数,该函数返回用户所选择的字体,下面是getFont()函数形式:
QFont getFont
bool* ok,
Qwidget* parent=0//标准字体对话框的父窗口
注:若用户选择“OK”,则该参数*ok将设为true,函数返回用户所选择的字体;否则,将设为false,此时函数返回默认字体。
-QInputDialog
输入对话框。
getText
标准字符串输入对话框通过QInputDialog类的静态函数getText()完成,getText()函数形式如下:
QString getText
Owidget* parent,//标准输入对话框的父窗口
const QString& title,//标准输入对话框的标题名
const QString& label,//标准输入对话框的标签提示
QLineEdit: :EchoMode mode=QLineEdit::Normal,//指定标准输入对话框中 QLineEdit控件的输入模式
const oString& text=QString(O,//标准字符串输入对话框弹出时 QLineEdit控件中默认出现的文字
bool* ok=0,
Qt::WindowFlags flags=0//指明标准输入对话框的窗体标识
注:指示标准输入对话框的哪个按钮被触发,若为 true,则表示用户单击了“OK”(确定)按钮;若为false,则表示用户单击了“Cancle”(取消)按钮。
geItem
标准条目选择对话框:
QString getItem
QWidget* parent,//标准输入对话框的父窗口
const QString& title,//标准输入对话框的标题名const QString& label,//标准输入对话框的标签提示const QStringList& items,//注(1)
int current=0,
bool editable=true,//指定QComboBox控件中显示的文字是否可编辑
bool* ok=0,
Qt: :windowFlags flags=0//指明标准输入对话框的窗体标识
注: (1)指定标准输入对话框中QComboBox控件显示的可选条目为一个 QStringList对象。 (2)标准条目选择对话框弹出时QComboBox控件中默认显示的条目序号。 (3)指示标准输入对话框的哪个按钮被触发,若ok为true,则表示用户单击了“OK”(确定)按钮;若ok为false,则表示用户单击了“Cancle”(取消)按钮。
getDouble
标准 double类型输入对话框是通过QInputDialog类的静态函数 getDouble()来完成的,getDouble()函数形式如下:
double getDouble
Qwidget* parent,//标准输入对话框的父窗口
const Qstring& title,//标准输入对话框的标题名
const QString& label,//标准输入对话框的标签提示
double value=0,//指定标准输入对话框中 QSpinBox控件默认的显示值
double min=-2147483647,//指定 QSpinBox控件的数值范围
double max=2147483647,
int decimals-1,//指定QSpinBox控件的步进值
bool* ok=0,
Qt::WindowFlags flags=0 //指明标准输入对话框的窗口标识
注:用于指示标准输入对话框的哪个按钮被触发,若ok为true,则表示用户单击了“OK”(确定)按钮;若 ok为false,则表示用户单击了“Cancel”(取消)按钮。
-QMessageBox
常用的消息对话框包括 Question消息框、Information消息框、Warning消息框、Critical消息框、About(关于)消息框、About(关于)Qt消息框及Custom(自定义消息框。其中,Question消息框、Information消息框、Warning消息框和Critical消息框的用法大同小异。这些消息框通常都包含为用户提供一些提醒或一些简单询问用的一个图标、一条提示信息及若干个按钮。Question消息框为正常的操作提供一个简单的询问。Information消息框为正常的操作提供一个提示。Warning消息框提醒用户发生了一个错误。Critical消息框警告用户发生了一个严重错误。
Question
Question消息框使用QMessageBox::question()函数完成,此函数形式如下:
StandardButton QMessageBox: : question
Qwidget* parent, //消息框的父窗口指针
const QString & title, //消息框的标题栏
const QString& text, //消息框的文字提示信息
StandardButtons buttons=Ok,
StandardButton defaultButton=NoButton
注:(1)填写希望在消息框中出现的按钮,可根据需要在标准按钮中选择,用“I”连写,默认为QMessageBox::Ok。QMessageBox类提供了许多标准按钮,如QMessageBox::Ok、QMessageBox::Close、QMessageBox:Discard等。虽然在此可以选择,但并不是随意选择的,应注意按常规成对出现。例如,通常Save与 Discard成对出现,而Abort、Retry、Ignore则一起出现。 (2)默认按钮,即消息框出现时,焦点默认处于哪个按钮上。
Information
Information消息框使用QMessageBox::information()函数完成,函数形式如下:
StandardButton QMessageBox::information
QWidget*parent,//消息框的父窗口指针
const Qstring& title,//消息框的标题栏
const QString & text,//消息框的文字提示信息
StandardButtons buttons=Ok,//同 Question消息框的注释内容
StandardButton defaultButton=NoButton //同Question消息框的注释内容
Warning
Warning消息框使用QMessageBox::warning()函数完成,函数形式如下:
StandardButton QMessageBoX:: warning
QNidget* parent,
//消息框的父窗口指针
const Qstring& title,
//消息框的标题栏
const QString& text,
//消息框的文字提示信息
StandardButtons buttons=Ok,
//同 Question消息框的注释内容
StandardButton defaultButton=NoButton //同Question消息框的注释内容
Critical
Critical消息框使用OMessageBox::critical()函数完成,函数形式如下:
StandardButton QMessageBox: :critical
Qwidget* parent,
//消息框的父窗口指针
const QString& title,
//消息框的标题栏
const QString& text,
//消息框的文字提示信息
StandardButtons buttons=Ok,
//同Question消息框的注释内容
StandardButton defaultButton=NoButton//同Question消息框的注释内容
About
About消息框使用QMessageBox::about()函数完成,函数形式如下:
void QMessageBox::about
Qwidget* parent,
//消息框的父窗口指针
const QString& title,
//消息框的标题栏
const QString& text
//消息框的文字提示信息
ToolBox
Window
QMainWindow是一个为用户提供主窗口程序的类,包含一个菜单栏(menu bar)、多个工具栏( toolbars)、多个锚接部件( dock widgets)、一个状态栏(status bar)及一个中心部件(central widget),是许多应用程序的基础,如文本编辑器、图片编辑器等。
menu bar
菜单是一系列命令的列表。为了实现菜单、工具栏按钮、键盘快捷方式等命令的一致性,Qt使用动作(Action)来表示这些命令。Qt的菜单就是由一系列的QAction动作对象构成的列表,而菜单栏则是包容菜单的面板,它位于主窗口顶部、主窗口标题栏的下面。一个主窗口最多只有一个菜单栏。
toolbars
状态栏通常显示GUI应用程序的一些状态信息,它位于主窗口的底部。用户可以在状态栏上添加、使用Ot窗口部件。一个主窗口最多只有一个状态栏。
tool bars
工具栏是由一系列的类似于按钮的动作排列而成的面板,它通常由一些经常使用的命令(动作)组成。工具栏位于菜单栏的下面、状态栏的上面,可以停靠在主窗口的上、下、左、右四个方向上。一个主窗口可以包含多个工具栏。
Layout
Qt组件布局,依靠widget自身布局的splitter、dock、stack继承于QFrame,而QLayout继承于QObject。
QSplitter
灵活分割窗口布局。
核心代码:
//主分割窗口
QSplitter *splitterMain =new QSplitter(Qt::Horizontal,0); //(a)
QTextEdit *textLeft =new QTextEdit(QObject::tr("Left Widget"), splitterMain);//(b)
textLeft->setAlignment(Qt::AlignCenter); //(c)
//右部分分割窗口 //(d)
QSplitter *splitterRight =new QSplitter(Qt::Vertical,splitterMain);
splitterRight->setOpaqueResize(false); //(e)
QTextEdit *textUp =new QTextEdit(QObject::tr("Top Widget"), splitterRight);
textUp->setAlignment(Qt::AlignCenter);
QTextEdit *textBottom =new QTextEdit(QObject::tr("Bottom Widget"), splitterRight);
textBottom->setAlignment(Qt::AlignCenter);
splitterMain->setStretchFactor(1,1);
Splitter自适应分割区域,添加多个Splitter就分多次区域。
setOpaqueResize
调用setOpaqueResize(bool)方法用于设定分割窗口的分割条在拖曳时是否为实时更新显示,若设为true则实时更新显示,若设为false则在拖曳时只显示一条灰色的粗线条,在拖曳到位并释放鼠标后再显示分割条。默认设置为true。
setStretchFactor
调用setStretchFactor方法用于设定可伸缩控件,它的第1个参数用于指定设置的控件序号,控件序号按插入的先后次序从0起依次编号。第2个参数为大于0的值,表示此控件为可伸缩控件。此实例中设定右部分分割窗口为可伸缩控件,当整个对话框的宽度发生改变时,左部的文件编辑框宽度保持不变,右部的分割窗口宽度随整个对话框大小的改变进行调整。
QDockWidget
停靠窗口布局也是经典布局之一。
核心代码:
//停靠窗口1
QDockWidget *dock=new QDockWidget(tr("DockWindow1"),this);
//可移动
dock->setFeatures(QDockWidget::DockWidgetMovable); //(a)
dock->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea); //(b)
QTextEdit *te1 =new QTextEdit();
te1->setText(tr("Window1,The dock widget can be moved between docks by the user" ""));
dock->setWidget(te1);
addDockWidget(Qt::RightDockWidgetArea,dock);
//停靠窗口2
dock=new QDockWidget(tr("DockWindow2"),this);
dock->setFeatures(QDockWidget::DockWidgetClosable|QDockWidget::DockWidgetFloatable); //可关闭、可浮动
QTextEdit *te2 =new QTextEdit();
te2->setText(tr("Window2,The dock widget can be detached from the main window,""and floated as an independent window, and can be closed"));
dock->setWidget(te2);
addDockWidget(Qt::RightDockWidgetArea,dock);
//停靠窗口3
dock=new QDockWidget(tr("DockWindow3"),this);
dock->setFeatures(QDockWidget::AllDockWidgetFeatures); //全部特性
QTextEdit *te3 =new QTextEdit();
te3->setText(tr("Window3,The dock widget can be closed, moved, and floated"));
dock->setWidget(te3);
addDockWidget(Qt::RightDockWidgetArea,dock);
setFeatures
设置Dock配置。
void setFeatures (DockWidgetFeatures features)
参数ODockWidget::DockWidgetFeatures指定停靠窗体的特性,包括以下几种参数。
- QDockWidget:DockWidgetClosable:停靠窗体可关闭。
- QDock Widget::DockWidgetMovable:停靠窗体可移动。
- QDock Widget::DockWidgetFloatable:停靠窗体可浮动。
- QDockWidget::AllDockWidgetFeatures:此参数表示拥有停靠窗体的所有特性。
- QDockWidget::NoDockWidgetFeatures:不可移动、不可关闭、不可浮动。
此参数可采用或|的方式对停靠窗体进行特性的设定。
setAllowedAreas
方法设置停靠窗体可停靠的区域,原型如下:
void setAllowedAreas (Qt::DockWidgetAreas areas)
参数Qt::Dock WidgetAreas指定了停靠窗体可停靠的区域,包括以下几种参数。
- Qt::LeftDock WidgetArea:可在主窗口的左侧停靠。
- Qt::RightDockWidgetArea:可在主窗口的右侧停靠。
- Qt::TopDockWidgetArea:可在主窗口的顶端停靠。
- Qt::BottomDock WidgetArea:可在主窗口的底部停靠。
- Qt:AllDockWidgetArea:可在主窗口任意(以上四个)部位停靠。
- Qt::NoDockWidgetArea:只可停靠在插入处。
QStackedWidget
堆栈窗体,组件依次叠加。
核心代码:
list =new QListWidget(this); //新建一个QListWidget控件对象
//在新建的QListWidget控件中插入三个条目,作为选择项
list->insertItem(0,tr("Window1"));
list->insertItem(1,tr("Window2"));
list->insertItem(2,tr("Window3"));
//创建三个QLabel标签控件对象,作为堆栈窗口需要显示的三层窗体
label1 =new QLabel(tr("WindowTest1"));
label2 =new QLabel(tr("WindowTest2"));
label3 =new QLabel(tr("WindowTest3"));
stack =new QStackedWidget(this);
//新建一个QStackedWidget堆栈窗体对象
//将创建的三个QLabel标签控件依次插入堆栈窗体中
stack->addWidget(label1);
stack->addWidget(label2);
stack->addWidget(label3);
QHBoxLayout *mainLayout =new QHBoxLayout(this);
mainLayout->addWidget(list);
mainLayout->addWidget(stack,0,Qt::AlignHCenter);
connect(list,SIGNAL(currentRowChanged(int)),stack,SLOT(setCurrentIndex(int)));//(b)
左边是label,connect建立model和view的关系即可。
QLayout
Ot提供了QHBoxLayout类、QVBoxLayout类及 QGridLayout类等的基本布局管理,分别是水平排列布局、垂直排列布局和网格排列布局。它们之间的继承关系如:
混合实现一个登录界面:
核心布局代码:
//向布局中加入需要布局的控件
LeftLayout->addWidget(UserNameLabel,0,0); //用户名
LeftLayout->addWidget(UserNameLineEdit,0,1);
LeftLayout->addWidget(NameLabel,1,0); //姓名
LeftLayout->addWidget(NameLineEdit,1,1);
LeftLayout->addWidget(SexLabel,2,0); //性别
LeftLayout->addWidget(SexComboBox,2,1);
LeftLayout->addWidget(DepartmentLabel,3,0); //部门
LeftLayout->addWidget(DepartmentTextEdit,3,1);
LeftLayout->addWidget(AgeLabel,4,0); //年龄
LeftLayout->addWidget(AgeLineEdit,4,1);
LeftLayout->addWidget(OtherLabel,5,0,1,2); //其他
LeftLayout->setColumnStretch(0,1); //(c)
LeftLayout->setColumnStretch(1,3);
/*********右侧*********/
HeadLabel =new QLabel(tr("头像: ")); //右上角部分
HeadIconLabel =new QLabel;
QPixmap icon("312.png");
HeadIconLabel->setPixmap(icon);
HeadIconLabel->resize(icon.width(),icon.height());
UpdateHeadBtn =new QPushButton(tr("更新"));
//完成右上侧头像选择区的布局
TopRightLayout =new QHBoxLayout();
TopRightLayout->setSpacing(20); //设定各个控件之间的间距为20
TopRightLayout->addWidget(HeadLabel);
TopRightLayout->addWidget(HeadIconLabel);
TopRightLayout->addWidget(UpdateHeadBtn);
IntroductionLabel =new QLabel(tr("个人说明:")); //右下角部分
IntroductionTextEdit =new QTextEdit;
//完成右侧的布局
RightLayout =new QVBoxLayout();
RightLayout->setMargin(10);
RightLayout->addLayout(TopRightLayout);
RightLayout->addWidget(IntroductionLabel);
RightLayout->addWidget(IntroductionTextEdit);
/*--------------------- 底部 --------------------*/
OkBtn =new QPushButton(tr("确定"));
CancelBtn =new QPushButton(tr("取消"));
//完成下方两个按钮的布局
ButtomLayout =new QHBoxLayout();
ButtomLayout->addStretch(); //(d)
ButtomLayout->addWidget(OkBtn);
ButtomLayout->addWidget(CancelBtn);
/*---------------------------------------------*/
QGridLayout *mainLayout =new QGridLayout(this); //(e)
mainLayout->setMargin(15); //设定对话框的边距为15
mainLayout->setSpacing(10);
mainLayout->addLayout(LeftLayout,0,0);
mainLayout->addLayout(RightLayout,0,1);
mainLayout->addLayout(ButtomLayout,1,0,1,2);
mainLayout->setSizeConstraint(QLayout::SetFixedSize); //(f)
BoxLayout
GridLayout
setSizeConstraint(QLayout::SetFixedSize):
设定最优化显示,并且使用户无法改变对话框的大小。所谓最优化显示,即控件都按其sizeHint()的大小显示。
QClass
Qt自定义的一些基础类。
QVariant
Src:5.12.12\msvc2017_64\include\QtCore\qvariant.h QVariant类类似于C++的联合(union)数据类型,它不仅能够保存很多Qt类型的值,包括 QColor、QBrush、QFont、QPen、QRect、QString和 QSize等,也能够存放Qt的容器类型的值。Qt的很多功能都是建立在QVariant 基础上的,如Qt的对象属性及数据库功能等。
常见形式:
QVariant v(709);
QVariant w("How are you");
qDebug() << w.toString() << v.toInt();
QString
Src:5.12.12\msvc2017_64\include\QtCore\qstring.h qt自定义的string类,其基本使用方法和stl string类似,但也有一些自己的运行方式。
隐式共享
隐式共享又称为回写复制(copy on write)。当两个对象共享同一份数据时(通过浅拷贝实现数据块的共享),如果数据不改变,则不进行数据的复制。而当某个对象需要改变数据时,则执行深拷贝。 程序在处理共享对象时,使用深拷贝和浅拷贝这两种方法复制对象。所谓深拷贝,就是生成对象的一个完整的复制品;而浅拷贝则是一个引用复制(如仅复制指向共享数据的指针)。显然,执行一个深拷贝的代价是比较昂贵的,要占用更多的内存和 CPU资源;而浅拷贝的效率则很高,它仅需设置一个指向共享数据块的指针及修改引用计数的值。隐式共享可以降低对内存和CPU 资源的使用率,提高程序的运行效率。它使得在函数中(如参数、返回值)使用值传递更有效率。 Qstring类采用隐式共享技术,将深拷贝和浅拷贝有机地结合起来。
内存分配策略
QString在一个连续的内存块中保存字符串数据。当字符串的长度不断增长时,QString需要重新分配内存空间,以便有足够的空间保存增加的字符串。QString使用的内存分配策略如下。
- 每次分配4个字符空间,直到大小为20。
- 在20~4084之间,OString 分配的内存块大小以2倍的速度增长。
- 从4084开始,每次以2048个字符大小(4096字节,即4KB)的步长增长。
QString::arg():
独特的字符串组合方式,类型安全,完全支持Unicode,其形式如下:
QString str = QString("%1 am %2").arg("i").arg(250);
类似于sprintf(QString也有QString::sprintf(),但类型不安全)。
QString::toInt():
类型转换,包括toDouble(),toFloat(),toLong(),toLongLong()
QByteArray
QList、QLinkedList、QVector
Src:5.12.12\msvc2017_64\include\QtGui\qevent.h Qt中容器只能储存基本类型,不能储存QObject及其他子类,应该储存它们的指针。
QList
QList不仅提供了可以在列表中进行追加的QList:.append()和 Qlist::prepend()函数,还提供了在列表中间完成插入操作的函数QList::insert()。相对于任何其他的Qt容器类,为了使可执行代码尽可能少,QList被高度优化。 QList维护了一个指针数组,该数组存储的指针指向QList存储的列表项的内容。因此,QList提供了基于下标的快速访问。 对于不同的数据类型,QList采取不同的存储策略,存储策略有以下几种。
- 如果T是一个指针类型或指针大小的基本类型(即该基本类型占有的字节数和指针类型占有的字节数相同),QList会将数值直接存储在它的数组中。
- 如果QList存储对象的指针,则该指针指向实际存储的对象。
QLinkedList
QLinkedList是一个链式列表,它以非连续的内存块保存数据。 QLinkedList不能使用下标,只能使用迭代器访问它的数据项。与QList相比,当对一个很大的列表进行插入操作时,QLinkedList具有更高的效率。
QVector
QVector在相邻的内存中存储给定数据类型T的一组数值。在一个QVector的前部或者中间位置进行插入操作的速度是很慢的,这是因为这样的操作将导致内存中的大量数据被移动,这是由QVector存储数据的方式决定的。 QVector既可以使用下标访问数据项,也可以使用迭代器访问数据项。继承自OVector类的子类有QPolygon、QPolygonF和 QStack。
Iterator
QT提供两种风格的迭代器。
Java风格: Java风格迭代器的迭代点(Java-style iterators point)位于列表项的中间,而不是直接指向某个列表项。因此,它的迭代点或者在第一个列表项的前面,或者在两个列表项之间,或者在最后一个列表项之后。
QList<int> list;
list << 1 << 2;
QListIterator<int> i(list);
for (;i.hasNext();)
qDebug()<<i.next();
return a.exec();
CPP风格:
STL风格迭代器的API是建立在指针操作基础上的。例如,“++”操作运算符移动迭代器到下一个项(item),而“*”操作运算符返回迭代器指向的项。
QList<int>::iteator i;
for (i = list.begin(); i!=list.end();++i){
qDebug() << (*i);
*i = (*i)*10;
QHash、QMap
Src:5.12.12\msvc2017_64\include\QtCore\qmap.h QMap类和 QHash类具有非常类似的功能,它们的差别仅在于:QHash具有比 QMap,更快的查找速度。 QHash 以任意的顺序存储数据项,而QMap总是按照键Key的顺序存储数据。QHash 的键类型Key 必须提供 operator==()和一个全局的qHash(Key)函数,而QMap的键类型 Key必须提供operator<()函数。
QMap
QMap<Key,T>提供了一个从类型为Key的键到类型为T的值的映射。 通常,QMap存储的数据形式是一个键对应一个值,并且按照键Key的顺序存储数据。为了能够支持一键多值的情况,QMap提供了QMap<Key,T>::insertMulti()和QMap<Key,T>::values()函数。存储一键多值的数据时,也可以使用 QMultiMap<Key,T>容器,它继承自QMap。
QHash
QHash<Key,T>具有与QMap几乎完全相同的API。QHash维护着一张哈希表(HashTable),哈希表的大小与 QHash的数据项的数目相适应。 QHash以任意的顺序组织它的数据。当存储数据的顺序无关紧要时,建议使用QHash作为存放数据的容器。QHash也可以存储一键多值形式的数据,它的子类QMultiHash<Key,T>实现了一键多值的语义。
迭代器 关联容器迭代器类似:
QRegExp
Src:5.12.12\msvc2017_64\include\QtCore\qregexp.h 使用正则表达式可以方便地完成处理字符串的一些操作,如验证、查找、替换和分割等。Qt的QRegExp类是正则表达式的表示类,它基于Perl的正则表达式语言,完全支持Unicode。 正则表达式由表达式 ( expressions)、量词(quantifiers)和断言(assertions)组成。 (1)最简单的表达式是一个字符。字符集可以使用表达式如“[AEIOU]”,表示匹配所有的大写元音字母;使用“[^AEIOU]”则表示匹配所有非元音字母,即辅音字母;连续的字符集可以使用表达式如“[a-z]”,表示匹配所有的小写英文字母。 (2)量词说明表达式出现的次数,如“x[1,2]”表示“x”可以至少有一个,至多两个。
Event
QMouseEvent
鼠标事件包括鼠标的移动、鼠标键按下、松开、单机、双击等。处理鼠标事件只需要监听window的mousePressEvent等事件即可。
setMouseTracking 设置窗体追踪鼠标。函数setMouseTracking(O)设置窗体是否追踪鼠标,默认为false,不追踪,在此情况下应至少有一个鼠标按键按下时才响应鼠标移动事件。
QKeyEvent
同理,监听window对应事件,处理时判断类型,Qt::KeyboardModifier定义了一系列修饰键,如下所示:
- Qt::NoModifier:没有修饰键按下。
- Qt::ShiftModifier: 【Shift】键按下。
- Qt::ControlModifier: 【Ctrl】键按下。
- Qt::AltModifier: 【Alt】键按下。
- Qt::MetaModifier:Meta键按下。
- Qt::KevpadModifier:小键盘按键按下。
File
Qt自实现的文件操作。
QFile
用QFile读写文本文件:
QFile file("textFile1.txt");
if(file.open(QIODevice::ReadOnly))
char buffer[2048];
qint64 lineLen = file.readLine(buffer,sizeof(buffer)); //(c)
if(lineLen!=-1)
qDebug()<<buffer;
可以通过构造函数读入,也可以通过setFileName设置文件名。
QTextStream
QTextStream提供了更为方便的接口来读写文本,它可以操作 QIODevice ,QByteArray 和 QString。使用QTextStream的流操作符,可以方便地读写单词、行和数字。为了产生文本,OtextStream还提供了填充、对齐和数字格式化的选项。 用QTextStream读写文本文件:
QFile data("data.txt");
if(data.open(QFile::WriteOnly|QFile::Truncate)) //(a)
QTextStream out(&data);
out<<QObject::tr("score:")<<qSetFieldWidth(10)<<left<<90<< endl; //(b)
格式化函数:
流操作符:
QDataStream
QDataStream类提供了将二进制文件串行化的功能,用于实现C++基本数据类型,如 char、short、int、char *等的串行化。更复杂的串行化操作则是通过将数据类型分解为基本类型来完成的。 使用QDataStrem读取二进制文件:
/*将二进制数据写到数据流 */ //(a)
QFile file("binary.dat");
file.open(QIODevice::WriteOnly | QIODevice::Truncate);
QDataStream out(&file); //将数据序列化
out << QString(tr("汉字:")); //字符串序列化
out << QDate::fromString("1996/09/25", "yyyy/MM/dd");
out << (qint32)23; //整数序列化
file.close();
/*从文件中读取数据 */ //(b)
file.setFileName("binary.dat");
if(!file.open(QIODevice::ReadOnly))
qDebug()<< "error!";
return;
QDataStream in(&file); //从文件中读出数据
QString name;
QDate birthday;
qint32 age;
in >> name >> birthday >> age; //获取字符串和整数
qDebug() << name << birthday << age;
file.close();
QDir
QDir 类具有存取目录结构和内容的能力,使用它可以操作目录、存取目录或文件信息、操作底层文件系统,而且还可以存取Qt的资源文件。 Qt使用“/”作为通用的目录分隔符和 URL 路径分隔符。如果在程序中使用“”作为目录分隔符,Qt会将其自动转换为符合底层操作系统的分隔符(如 Linux使用“1”,Windows使用“\”)。 QDir可以使用相对路径或绝对路径指向一个文件。isRelative()和 isAbsolute()函数可以判断QDir对象使用的是相对路径还是绝对路径。如果需要将一个相对路径转换为绝对路径,则使用makeAbsolute()函数。 目录的路径可以通过 path()函数返回,通过setPath()函数设置新路径。绝对路径使用absolutePath()返回,目录名可以使用dirName()获得,它通常返回绝对路径中的最后一个元素,如果 QDir 指向当前目录,则返回“.”。目录的路径可以通过 cd()和 cdUp()改变。可以使用mkdir)创建目录,使用rename()改变目录名。 判断目录是否存在可以使用exists(),目录的属性可以使用isReadable()、isAbsolute()、isRelative()和 isRoot()来获取。目录下有很多条目,包括文件、目录和符号连接,总的条目数可以使用count()来统计。entryList()返回目录下所有条目组成的字符串链表。可以使用remove(函数删除文件,用rmdir)删除目录。
entryInfoList
QDir的entryInfoList()方法是按照某种过滤方式获得目录下的文件列表。其函数原型如下:
QFileInfoList QDir: :entryInfoList
const QStringList &nameFilters,
//此参数指定了文件名的过滤方式,如“*”,“.tar.gz”
Filters filters=NoFilter,
//此参数指定了文件属性的过滤方式,如目录、文件、读写属性等
SortFlags sort=NoSort
//此参数指定了列表的排序情况
)const
过滤方式:
排序方式:
QFileInfo
QFileInfo类提供了对文件进行操作时获得的文件相关属性信息,包括文件名、文件大小、创建时间、最后修改时间、最后访问时间及一些文件是否为目录、文件或符号链接和读写属性等。
QString file = fileNameLineEdit->text();
QFileInfo info(file); //根据输入参数创建一个QFileInfo对象
qint64 size = info.size(); //获得QFileInfo对象的大小
QDateTime created = info.created();
//获得QFileInfo对象的创建时间
QDateTime lastModified = info.lastModified();
//获得QFileInfo对象的最后修改时间
QDateTime lastRead = info.lastRead();
//获得QFileInfo对象的最后访问时间
/* 判断QFileInfo对象的文件类型属性 */
bool isDir = info.isDir(); //是否为目录
bool isFile = info.isFile(); //是否为文件
bool isSymLink = info.isSymLink(); //(a)
bool isHidden = info.isHidden(); //判断QFileInfo对象的隐藏属性
bool isReadable = info.isReadable(); //判断QFileInfo对象的读属性
bool isWritable = info.isWritable(); //判断QFileInfo对象的写属性
bool isExecutable = info.isExecutable();
QFileSystemWatcher
在Qt中可以使用QFileSystemWatcher类监视文件和目录的改变。使用addPath()函数监视指定的文件和目录时,如果需要监视多个目录,则可以使用addPaths()函数加入监视。若要移除不需要监视的目录,则可以使用removePath()和 removePaths()函数。 当监视的文件被修改或删除时,产生一个 fileChanged()信号。如果所监视的目录被改变或删除,将产生 directoryChanged()信号。
NetWork
暂无需求,占坑。
Painter
画布,类似于js中的Canvas。
QPainter
Qt为开发者提供了丰富的绘制基本图形的 draw函数。除此之外,QPainter类还提供了一个 drawPixmap()函数,可以直接将图片画到刻画控件上。
QPainterPath
利用QPainterPath 绘制简单图形,QPainterPath类为QPainter类提供了一个存储容器,里面包含了所要绘制的内容的集合及绘制的顺序,如长方形、多边形、曲线等各种任意图形。当需要绘制此预先存储在QPainterPath对象中的内容时,只需调用QPainter类的 drawPath()函数即可。 QPainterPath类提供了许多函数接口,可以很方便地加入一些规则图形。例如,addRect()加入一个方形,addEllipse()加入一个椭圆形,addText()加入一个字符串,addPolygon()加入一个多边形等。同时,QPainterPath类还提供了addPath()函数,用于加入另一个QPainterPath对象中保存的内容。 QPainterPath 对象的当前点自动处在上一部分图形内容的结束点上,若下一部分图形的起点不在此结束点,则需调用moveTo()函数将当前点移动到下一部分图形的起点。
QPainterPath path;
path.addRect(150,150,100,100);
path.moveTo(100,100);
path.cubicTo(300,100,200,200,300,300);
path.cubicTo(100,300,200,200,100,100);
path.setFillRule(fillRule);
QPen
Qt::PenStyle style = Qt::PenStyle(A);
Qt::PenCapStyle cap = Qt::PenCapStyle(B);
Qt::PenJoinStyle join=Qt::PenJoinStyle(C);
paintArea->setPen(QPen(color,value,style,cap,join));
Qt::PenStyle表示画笔的风格,有如下选择:
Qt::PenCapStyle表示画笔顶帽的风格,有如下选择:
Qt::PenJoinStyle表示画笔连接点的风格:
其中,Qt::BevelJoin风格连接点是指两条线的中心线顶点相汇,相连处依然保留线条各自的方形端;Qt:MiterJoin风格连接点是指两条线的中心线顶点相汇,相连处线条延长到线的外侧汇集至点,形成一个尖顶的连接;Qt.RoundJoin风格连接点是指两条线的中心线顶点相汇,相连处以圆弧形连接。
FilleRule
填充规则。
Qt::FillRule rule = Qt::FillRule(A);
paintArea->setFillRule(rule);
Qt为QPainterPath类提供了两种填充规则,分别是Qt:OddEvenFill和 Qt:WindingFill。这两种填充规则在判定图形中某一点是处于内部还是外部时,判断依据不同。 其中,Qt::OddEvenFill填充规则判断的依据是从图形中某一点画一条水平线到图形外。若这条水平线与图形边线的交点数目为奇数,则说明此点位于图形的内部;若交点数目为偶数,则此点位于图形的外部:
而Q::WindingFill填充规则的判断依据则是从图形中某一点画一条水平线到图形外,每个交点外边线的方向可能向上,也可能向下,将这些交点数累加,方向相反的相互抵消,若最后结果不为0则说明此点在图形内,若最后结果为0则说明在图形外:
QBrush
笔刷,实现不同形式的笔刷控制。
//获得画刷的颜色
QColor color = brushColorFrame->palette().color(QPalette:: Window);
Qt::BrushStyle style = Qt::BrushStyle(brushStyleComboBox-> itemData(
value,Qt::UserRole).toInt()); //(a)
if(style == Qt::LinearGradientPattern) //(b)
QLinearGradient linearGradient(0,0,400,400);
linearGradient.setColorAt(0.0,Qt::white);
linearGradient.setColorAt(0.2,color);
linearGradient.setColorAt(1.0,Qt::black);
linearGradient.setSpread(spread);
paintArea->setBrush(linearGradient);
else if(style == Qt::RadialGradientPattern) //(c)
QRadialGradient radialGradient(200,200,150,150,100);
radialGradient.setColorAt(0.0,Qt::white);
radialGradient.setColorAt(0.2,color);
radialGradient.setColorAt(1.0,Qt::black);
radialGradient.setSpread(spread);
paintArea->setBrush(radialGradient);
else if(style == Qt::ConicalGradientPattern) //(d)
QConicalGradient conicalGradient(200,200,30);
conicalGradient.setColorAt(0.0,Qt::white);
conicalGradient.setColorAt(0.2,color);
conicalGradient.setColorAt(1.0,Qt::black);
paintArea->setBrush(conicalGradient);
else if(style == Qt::TexturePattern)
paintArea->setBrush(QBrush(QPixmap("butterfly.png")));
paintArea->setBrush(QBrush(color,style));
QLinearGradient的Spread控制铺展效果:
BrushStyle控制笔刷的风格:
Graphics View
Graphics View框架结构的主要特点如下。
- Graphics View框架结构中,系统可以利用Qt绘图系统的反锯齿、OpenGL工具来改善绘图性能。
- Graphics View支持事件传播体系结构,可以使图元在场景(scene)中的交互能力提高1倍,图元能够处理键盘事件和鼠标事件。其中,鼠标事件包括鼠标按下、移动、释放和双击,还可以跟踪鼠标的移动。
- 在 Graphics View框架中,通过二元空间划分树(Binary Space Partitioning,BSP)提供快速的图元查找,这样就能够实时地显示包含上百万个图元的大场景。
框架结构主要包括三个类:
QGraphicsScene
它是一个用于放置图元的容器,本身是不可见的,必须通过与之相连的视图类来显示及与外界进行互操作。通过 QGraphicsScene:.addItem()可以添加一个图元到场景中。图元可以通过多个函数进行检索。QGraphicsScene::items()和一些重载函数可以返回和点、矩形、多边形或向量路径相交的所有图元。QGraphicsScene:.itemAt()返回指定点的顶层图元。 场景类主要完成的工作包括提供对它包含的图元的操作接口和传递事件、管理各个图元的状态(如选择和焦点处理)、提供无变换的绘制功能(如打印)等。 事件传播体系结构将场景事件发送给图元,同时也管理图元之间的事件传播。如果场景接收到了在某一点的鼠标单击事件,场景会将事件传给这一点的图元。 管理各个图元的状态(如选择和焦点处理)。可以通过 QGraphicsScene::setSelectionArea()函数选择图元,选择区域可以是任意的形状,使用QPainterPath表示。若要得到当前选择的图元列表,则可以使用函数QGraphicsScene:: selectedItems()。可以通过QGraphicsScene:: setFocusItem()函数或QGraphicsScene:: setFocus()函数来设置图元的焦点,获得当前具有焦点的图元使用函数QGraphicsScene::focusltem()。 如果需要将场景内容绘制到特定的绘图设备,则可以使用QGraphicsScene:; render()函数在绘图设备上绘制场景。
QGraphicsView
它提供一个可视的窗口,用于显示场景中的图元。在同一个场景中可以有多个视图,也可以为相同的数据集提供几种不同的视图。 QGraphicsView是可滚动的窗口部件,可以提供滚动条来浏览大的场景。如果需要使用OpenGL,则可以使用QGraphicsView::setViewport()将视图设置为QGLWidget。[视图接收键盘和鼠标的输入事件,并将它们翻译为场景事件(将坐标转换为场景的坐标)。使用变换矩阵函数QGraphicsView:matrix()可以变换场景的坐标,实现场景缩放和旋转。QGraphicsView提供 QGraphicsView::map ToScene()和 QGraphicsView;:mapFromScene)用于与场景的坐标进行转换。
QGraphicsItem
它是场景中各个图元的基类,在它的基础上可以继承出各种图元类,Qt已经预置的包括直线(QGraphicsLineItem)、椭圆(QGraphicsEllipseItem)、文本图元(QGraphicsTextItem)、矩形(QGraphicsRectItem)等。当然,也可以在 QGraphicsItem类的基础上实现自定义的图元类,即用户可以继承QGraphicsItem实现符合自己需要的图元。 QGraphicsItem主要有以下功能:
- 处理鼠标按下、移动、释放、双击、悬停、滚轮和右键菜单事件。处理键盘输入事件。
- 处理拖曳事件。
- 分组。
- 碰撞检测。
此外,图元有自己的坐标系统,也提供场景和图元。图元还可以通过QGraphicsItem::matrix(来进行自身的交换,可以包含子图元。
Opengl3d
待更。
Multi Thread
QThread\QMutex\QMutexLocker\QWaitCondition
待更。
Multi platform
待更。
Qt Quick\QML
QML (Qt Meta Language,Qt元语言)是一个用来描述应用程序界面的声明式脚本语言,最早自Qt 4.7引入。QML具有良好的易读性,它以可视化组件及其交互和相互关联的方式来描述界面,使组件能在动态行为中互相连接,并支持在一个用户界面上很方便地复用和定制组件。 Ot Quick是Qt为QML提供的一套类库,由QML标准类型和功能组成,包括可视化类型、交互类型、动画类型、模型和视图、粒子系统和渲染效果等,编程时只需要一条import 语句,程序员就能够访问所有这些功能。使用Qt Quick,设计和开发人员能很容易地用QML构建出高品质、流畅的UI界面,从而开发出具视觉吸引力的应用程序。 一个简单的QML文件如下:
import QtQuick 2.7
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
MainForm {
anchors.fill: parent
mouseArea.onClicked: {
console.log(qsTr('Clicked on background. Text: "' + textEdit.text + '"'))
采用级联元素的形式表现层次结构,类似json格式表示属性及其值,一目了然不用太多解释。 链接主程序时,只需要在main.cpp中加载:
int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
Elements
QML中的基本元素。
Rectangle
基本元素-矩形:Qt Quick提供了Rectangle类型来绘制矩形,矩形可以使用纯色或渐变色来填充,可以为它添加边框并指定颜色和宽度,还可以设置透明度、可见性、旋转和缩放等效果。
Rectangle {
id: topRect //id标识符
opacity: 0.6 //设置透明度 60%
scale: 0.8 //缩小为原尺寸的 80%
x: 135
y: 60
width: 100
height: 100
radius: 8 //绘制圆角矩形
gradient: Gradient { //(a)
GradientStop { position: 0.0; color: "aqua" }
GradientStop { position: 1.0; color: "teal" }
border { width: 3; color: "blue" } //为矩形添加一个3像素宽的蓝色边框
Image
基本元素-图片:Qt Quick提供了Image类型来显示图像,Image类型有一个source属性。该属性的值可以是远程或本地URL,也可以是嵌入已编译的资源文件中的图像文件URL。
Image {
//图像在窗口的位置坐标
x: 20
y: 20
//宽和高均为原图1/4
width: 980/4;height: 751/4 //(a)
source: "images/长白山天池.jpg" //图片路径URL
fillMode: Image.PreserveAspectCrop //(b)
clip: true //避免所要渲染的图片超出元素范围
Text
为了用QML显示文本,要使用Text元素,它提供了很多属性,,包括颜色、字体、字号、加粗和倾斜等,这些属性可以被设置应用于整块文本段,获得想要的文字效果。Text元素还支持富文本显示、文本样式设计以及长文本省略和换行等功能。
Text { //换行的文本
width:200 //限制文本宽度
y:30
color:"green"
font.family: "Helvetica"
font.pointSize: 24
horizontalAlignment:Text.AlignLeft
wrapMode:Text.WrapAnywhere
text: "Hello Qt Quick!"
Custom
自定义组件,只需要添加qrc文件,在自定义qml中设置其属性,如Button.qml:
import QtQuick 2.0
Rectangle { //将Rectangle自定义成按钮
id:btn
width: 100;height: 62 //按钮的尺寸
color: "teal" //按钮颜色
border.color: "aqua" //按钮边界色
border.width: 3 //按钮边界宽度
Text { //Text元素作为按钮文本
id: label
anchors.centerIn: parent
font.pointSize: 16
text: "开始"
MouseArea { //MouseArea对象作为按钮单击事件响应区
anchors.fill: parent
onClicked: { //响应单击事件代码
label.text = "按钮已按下!"
label.font.pointSize = 11 //改变按钮文本和字号
btn.color = "aqua" //改变按钮颜色
btn.border.color = "teal" //改变按钮边界色
具体使用时就可以复用:
Button { //复用Button组件
x: 25; y: 25
}
Layout
Row
Row {….}: Row将被其定位的元素成员都放置在一行的位置,所有元素之间间距相等(由spacing属性设置),顶端保持对齐。layoutDirection属性设置元素的排列顺序,可取值Qt.LeftToRight(默认,从左向右),Qt.RightToLeft(从右向左)。
Row { //(a)
x:25
y:25
spacing: 10 //元素间距为10像素
layoutDirection:Qt.RightToLeft //元素从右向左排列
//以下添加被Row定位的元素成员
RedRectangle { }
GreenRectangle { }
BlueRectangle { }
Column
Column {...}:Column将元素成员按照加入的顺序从上到下在同一列排列出来,同样由spacing属性指定元素间距所有元素靠左对齐。
Column { //(b)
x:25
y:120
spacing: 2
//以下添加被Column定位的元素成员
RedRectangle { }
GreenRectangle { }
BlueRectangle { }
Grid
Grid {.}: Grid将其元素成员排列为一个网格,默认从左向右排列,每行4个元素。可通过设置rows 和 columns属性来自定义行和列的数值,如果二者有一个不显式设置,则另一个会根据元素成员的总数计算出来。例如,本例中columns 设置为3,一共放入5个蓝色矩形,行数就会自动计算为2。
Grid { //(c)
x:140
y:120
columns: 3 //每行3个元素
spacing: 5
//以下添加被Grid定位的元素成员
BlueRectangle { }
BlueRectangle { }
BlueRectangle { }
BlueRectangle { }
BlueRectangle { }
Flow
Flow{.….}:顾名思义,Flow会将其元素成员以流的形式显示出来,它既可以从左向右横向布局,也可以从上向下纵向布局,或反之。但与Row、Column等定位器不同的是,添加到Flow里的元素,会根据显示区(窗体)尺寸变化动态地调整其布局。以本程序为例,初始运行时,窗体狭窄,无法横向编排元素,故三个矩形都纵向排列,在用鼠标将窗体拉宽过程中,其中矩形由纵排逐渐转变成横排显示。
Flow {
anchors.fill: parent
anchors.margins: 15 //元素与窗口左上角边距为15像素
spacing: 5
//以下添加被Flow定位的元素成员
RedRectangle { }
BlueRectangle { }
GreenRectangle { }
Repeater
Repeater{.….}:重复器,作为Grid的数据提供者,它可以创建任何QML 基本的可视元素。Repeater 会按照其model属性定义的个数循环生成子元素,故上面代码重复生成16个Rectangle。 Repeater会为每一个子元素注入一个index属性,作为当前的循环索引。可以在子元素定义中直接使用这个属性。
Grid { //Grid定位器
x:25;y:25
spacing: 4
//用重复器为Grid添加元素成员
Repeater { //(a)
model: 16 //要创建元素成员的个数
Rectangle { //成员皆为矩形元素
width: 48; height: 48
color:"aqua"
Text { //显示矩形编号
anchors.centerIn: parent
color: "black"
font.pointSize: 20
text: index //(b)
Anchor
除了的Row、Column和 Grid等外,QML还提供了一种使用Anchor(锚)来进行元素布局的方法。每一个元素都可以认为有一组无形的“锚线”:left、horizontalCenter、right、top、verticalCenter和 bottom,Text元素还有一个 baseline锚线(对于没有文本的元素,它与top相同)。 这些锚线分别对应了元素中的anchors.left、anchors.horizontalCenter等属性,所有的可视元素都可以使用锚来布局。锚系统还允许为一个元素的锚指定边距(margin)和偏移(offset)。边距指定了元素锚到外边界的空间量,而偏移允许使用中心锚线来定位。一个元素可以通过leftMargin、rightMargin、topMargin和 bottomMargin来独立地指定锚边距,也可以使用anchor.margins来为所有的4个锚指定相同的边距。
/* 使用Anchor对三个矩形元素进行横向布局 */ //(b)
BlueRectangle { //蓝矩形
id:blueRect
anchors.left: parent.left //与窗口左锚线锚定
anchors.top: parent.top //与窗口顶锚线锚定
anchors.leftMargin: 25 //左锚边距(即与窗口左边距)
anchors.topMargin: 25 //顶锚边距(即与窗口顶边距)
GreenRectangle { //绿矩形
id:greenRect
anchors.left: blueRect.right //绿矩形左锚线与蓝矩形的右锚线锚定
anchors.top: blueRect.top //绿矩形顶锚线与蓝矩形的顶锚线锚定
anchors.leftMargin: 40 //左锚边距(即与蓝矩形的间距)
RedRectangle { //红矩形
id:redRect
anchors.left: greenRect.right //红矩形左锚线与绿矩形的右锚线锚定
anchors.top: greenRect.top //红矩形顶锚线与绿矩形的顶锚线锚定
anchors.leftMargin: 40 //左锚边距(即与绿矩形的间距)
Event
QML中事件系统。
MouseAera
与以前的窗口部件不同,在QML 中如果一个元素想要处理鼠标事件,就要在其上放置一个MouseArea元素,也就是说,用户只能在MouseArea确定的范围内进行鼠标的动作。
MouseArea { //定义MouseArea元素处理鼠标事件
anchors.fill: parent //事件响应区充满整个矩形
/* 拖曳属性设置 */ //(a)
drag.target: parent
drag.axis: Drag.XAxis
drag.minimumX: 0
drag.maximumX: 360 - parent.width
acceptedButtons: Qt.LeftButton|Qt.RightButton //(b)
onClicked: { //处理鼠标事件的代码
if (mouse.button == Qt.RightButton) { //(c)
/* 设置矩形为蓝色并缩小尺寸 */
parent.color = "blue";
parent.width -= 5;
parent.height -= 5;
KeyEvent
当一个按键被按下或释放时,会产生一个键盘事件,并将其传递给获得了焦点的QML元素。在QML 中,Keys属性提供了基本的键盘事件处理器,所有可视元素都可以通过它来进行按键处理。
Rectangle {
focus: true //初始时选中“音乐”图标
KeyNavigation.tab: play //(a)
/* 移动图标位置 */ //(b)