QT基础三

摘要:
QTableWidgetItem类并不是widget,而是一个纯粹的dataclass。Qt还提供了一个QTextStream类用于专门读写文本文件。Qt的内置Widget如QLabel、QPushButton、QTabelWidget等,就是以这种方式实现的。宏Q_PROPERTY()用来为widget声明和添加自定义属性。对于包含自定义属性的类,Q_OBJECT和Q_PROPERTY()这两个宏都是必备的。在实现pluginclass的源文件尾部,必须使用Q_EXPORT_PLUGIN2()宏使得该plugin对QtDesigner可见、可用。Chatper6LayoutManagement6.1LayingOutWidgetsonaFormQt提供的的基本的LayoutManager包括:QHBoxLayout,QVBoxLayout,QGridLayout和QStackLayout。Qt中管理childwidget的layout共有三种方式:absolutepositioning,manuallayout和layoutmanagers。

4.1The Central Widget

QMainWindow的中央区域可以被任何类型的widget占据。

4.2Subclassing QTableWidget

QTableWidget会自动创建QTableWidgetItem来存储用户的输入。

QTableWidgetItem类并不是widget,而是一个纯粹的data class。

QTabeWidget::setItermProtype()可以设置在获得用户输入的情况下自动创建哪种cllass。

4.3Loading and Saving

QFile & QDataStream

QFile的析构函数负责将打开的文件关闭。

QDataStream类具有很强的通用性,可作用于QFile,QBuffer,QProcess,QTcpSocket,QUdpSocket。

Qt还提供了一个QTextStream类用于专门读写文本文件。

4.6Subclassing QTableWidgetItem

每个QTableWidgetIterm中可存储若干数据,这是通过个QVariant来实现的。每一个QVariant对象都以某个role来存储某一类数据,常用的role有Qt::EditRole和Qt::DiaplayRole。

QVarinant对象可以存放多种类型的变量值,并提供向其他类型转型的函数接口。

使用默认构造函数创建的QVariant对象被视为invalid variant。

Chapter 5. Creating Custom Widgets

用户自定义的控件可以通过继承现有的Qt控件实现,也可以直接从QWidget继承来实现。

5.1Customizing Qt Widgets

5.2Subclassing QWidget

通过对QWidget进行派生,并重新编写其部分event handler来进行绘图和响应用户操作,程序员可以实现对widget的外观和行为的完全控制。

Qt的内置Widget如QLabel、QPushButton、QTabelWidget等,就是以这种方式实现的。

宏Q_PROPERTY()用来为widget声明和添加自定义属性。

每个属性的定义都对应一个数据类型(任何被QVarinat支持的类型都可以),一个read function以及可选的write function。

对于包含自定义属性的类,Q_OBJECT和Q_PROPERTY()这两个宏都是必备的。

QImage类以一种硬件无关的方式存储图像信息。

Qt中提供了两个类型用于存储色彩信息:QRgb和QColor。

QRgb其实是一个typedef,用于存放32-bit的像素信息。
QColor则是一个提供了许多接口函数的类,在Qt中广泛的用于存储色彩。

QWidget::update()函数用于对widget进行强制性的重绘。
QWidget::updateGeometry()用于告知包含该widget的layout:该widget的size hint已发生变化,layout会自动进行调整。

通过调用QWidget::update()和QWidget::repaint(),可以强制性的产生一个 paint event,两者的却别在于repaint()导致立即重绘,而update()只是将一个paint event放入event queue中。

如果对update()进行连续多次调用,Qt会将连续的paint event压缩合并为一个paint event,以防止图像抖动。

每个widget都拥有一个palette,用于设置widget中在什么情况下使用什么色彩,如背景色、文本色等。

widget的palette由三个color group组成:active ,inactive ,disabled。

QWidget::palette()以QPalette的形式返回widget的palette,而clolor group则通过枚举类型QPalette::ColorGroup指定。

5.3IntergratingCustom Widgets with Qt Designer

要像在Qt Designer中使用自定义widget的话,必须要让Qt Designer能够了解到它们的存在。

有两种机制:promotion approach &plugin approach

promotion approach 很容易也很省时,但缺点是自定义widget的自定义属性在Qt Designer中是不可见和不可访问的,而使用plugin approach时则不存在这些问题。

plugin approach要求创建一个Qt Designer 可以在运行时加载的plugin library,以用于创建widget的实例。由于Qt的MOC机制,Qt Designer可以动态获取widget的property list。

要使用plugin approach ,首先要对QDesignCustomWidgetInterface进行派生,并重写某些虚函数。

Q_INTERFACES()宏用于告知Qt该类实现了哪个interface。

在实现plugin class的源文件尾部,必须使用Q_EXPORT_PLUGIN2()宏使得该plugin对Qt Designer可见、可用。该宏的第一个参数是plugin的名字,第二个参数是实现该plugin的class name。

5.4Double Buffering

QWidget::style()返回用于绘制该widget时所使用的style。Qt中的style都是QStyle的派生类。同一应用程序中的 widget一般都使用相同的style,然而可以调用QWidget::setStyle()来进行widget层次的特别设置。

Chatper 6 Layout Management

6.1Laying Out Widgets on a Form

Qt提供的的基本的Layout Manager包括:QHBoxLayout,QVBoxLayout,QGridLayout和QStackLayout。

Qt中其它能完成Layout management功能的类包括 QSplitter,QScrollArea,QMainWindow和QWorkspace。

Qt中管理child widget的layout共有三种方式:absolute positioning, manual layout和layout managers。

Absolute positioning:即由程序员通过hard-coded的形式管理child widget的位置和尺寸。

Manual Layout:child widget的位置依然由程序员通过hard-coded的方式确定,而尺寸与父窗口的大小成一定比例,而不是完全的hard-coded。这种方式通过对form的resizeEvent()进行再实现来对child widget的定位。

最重要的三个Layout Manger是QHBoxLayout,QVBoxLayout,QGridLayOut,他们都是派生自QLayout

QGridLayout的使用略微有些复杂,它工作在一个由Cell组成的二维grid上。对于QGridLayout,为其添加widget的方式如下:

layout-> addWidget(widget,row ,colum,rowSpan,columnSpan)

其中widget为待添加的child widget, row和clomun确定该widget所占据空间中左上角那个Cell的位置坐标,rowSpan和columnSpan则指定widget的大小,这两个参数的的缺省值为1。

addStretch()向Layout Manager中添加“占位符”。

每个widget都有自己的size policy,由其告知layout 系统如何处理该widget外形上的stretch或是shrink。Qt中widget的size policy是通过QSizePolicy类来表示的。每个QSizePolicy由水平和竖直两组size policy组成,最常见的值包括:

FixedMinimumMaximumPreferedExpanding

除了上述两组size policy外,QSizePolicy中还存储水平和竖直方向的stretch factor,该值用来表明在form尺寸扩展时widget随之扩展的比率。

6.2Stacked Layouts

QStackLayout 类可以管理多个page,但每次只显示其中之一,而将其他page向用户隐藏。

QStackLayout类本身是不可见的。

为了方便起见,Qt中包含有QStackedWidget类,即一个内置了QStackedLayout的QWidget。

6.3Splitter

类QSplitter是一个能包含其他widget的widget。QSplitter中包含的widget按顺序排列,并被splitter handle相互分隔开。

QSplitter通过构造函数中的参数来来决定是水平方向还是竖直方向。

不同于前面介绍的Layout Mangener们只是负责处理widget的layout而自身没有可视化的表示,QSplitter派生自QWidget,因此可以同其它widget一样的被使用。

QSplitter类提供了存储自身状态的两个函数:savestate()和restorestate()。

6.4Scrolling Areas

QScrollArea类提供了1个可滑动的viewport和2个滑动条。

QScrollArea的使用方法是调用其提供的setWidget()函数,将希望为其添加滑动条的widget添加。QScrollArea自动将添加进来的widget的parent设定为其viewport,而其viewpoint可通过QScrollArea::viewport()进行访问。
QScrollArea的多数功能是通过继承QAbstraceScrollArea类而获得的。而诸如QTextEdit和 QAbstractIterView这样的类是派生自QAbstractScrollArea的,因此不需要将其用QScrollArea类包裹起来以获得scroll bar。

6.5Dock Widgets and Toolbars

在Qt中,dock widget是通过QDockWidget类来实现的。

每个dock widget都有自己的title bar。

从Qt4开始,toolbar拥有自己专属的显示空间,而不再是如之前的版本中允许dock widget与其分享。

对一个widget调用setAllowedArea()可以指定允许在那些dock areas上放置该widget。

6.6Multiple Document Interface

Qt中,编写MDI程序是通过使用QWorkspace类,将其作为程序的central widget,并把每个文档窗口都作为QWorkspace的child。

Qt程序的命令行参数中与Qt相关的参数,会由QApplication的构造函数负责自动移除掉,不会传递给Qt程序的main()函数。

Chapter 7 Event Processing

Qt中大多数event都是作为对用户操作的响应而产生的,但也有一些是系统内部独立生成的。

在使用Qt进行编程时,通常很少需要考虑event,因为Qt中的widget会在有重要事件发生时emit signal。Event在我们要编写自定义widget或是要修改现有Qt widget的特性时,则变得很重要。

不要在概念上将event和signal两个概念混淆。当程序员操纵使用widget时,signal是需要关注的对象;而当程序员需要实现一个widget时,event则是需要关注的对象。

例如,当使用QPushButton时,我们更关注其提供的clicked() signal 而不是导致该signal被QPushButton emit的低层次的鼠标或键盘event。但是如果我们要自己实现一个类似于QPushButton的类,那就轮到我们编写代码来处理鼠标和键盘操作,并在必要时emit clicked() signal。
7.1Reimplementing Event Handles

Qt中,每个event都是一个派生自QEvent的对象。Qt中包含超过100种的event,每种event有一个enum value进行标识。

QEvent::type()返回event type。

所有event都是通过其对应类中的event()函数,来向对象发送通告的;这个event()函数继承自QObject。QWidget中 event()的实现是将最常见类型的event转发给对应的event handlers,例如mousePressEvent(),keyPress-Event,painEvent()。

键盘event对应的event handler是keyPressEvent()和keyReleaseEvent()。

QKeyEvent::modifiers()

Tab键和Shift+Tab键的处理有些特殊,它们不是由keyPressEvent()负责处理,而是在QWidget::event()中进行处理,而且发生在调用keyPressEvent()之前,处理方式是将输入焦点按照链中的顺序向后或向前传递。

实现key binding的更高层次的实现方式是利用QAction。QAction类内部使用了QShortCut类来实现key binding。

QObject::startTimer() 用于创建定时器,并返回相应的ID。QObject支持多个定时器同时存在。
killTimer()用于销毁定时器,参数为定时器的ID。

Timer event位于底层,实现定时功能更简单的方式是使用QTimer类,QTimer会定期的emit timeout() siganl。

7.2Installing Event Filter

Qt的evnet model中很强大的一个特性,就是可以设定某个对象来监控另外一个对象,后者所有的event在对其可见前都要先通过前一个对象的监控和处理。

Qt中设置event filter涉及到两步操作:

1.在要被监控的对象中调用installEventFilter() 来完成对监控者的注册。
2在监控者的eventFilter() 中对被监控者的event进行处理。

Qt的event model中,一个event若未得到处理(event handler的返回值为false),则Qt会负责将该event向上传递,即交由其parent负责处理

Qt中对event的处理可以分为下面5个层次:

1.对某个特定的event handler进行重实现。
2.对Widget中的QObject::event()进行重实现,这样在event被传递给特定的event handler之前就得到了处理。
3.为某个对象安装event filter
4.为QApplication object安装filter,这样可以监控应用程序中所有对象收到的所有event,在进行debug是非常有用。
5.派生QAapplication的子类,并对notify()进行重实现。Qt调用notify()来发送event的。这是捕获所有event的唯一方法。

7.3Staying Responsive During Intensive Processing

在完成耗时操作的同时,还要保证程序能够对用户操作正常相应,常见的解决机制是多线程。

一种简单的解决方案是在耗时操作的过程中有规律的调用QApplication::processEvnets()。该函数通知Qt处理pending events,处理结束后再将控制权返回至调用者。

Qt中的进度对话框是由QProgressDialog类来实现的。

除了使用多线程和进度对话框外,还存在一种完全不同的处理耗时操作的方法:操作只在程序空闲(无用户交互)时再进行,而不是立刻开始执行。

这种方法可以利用0-milisecond timer来实现,每次定时器触发时,检查是否有pending event,若无则继续好事操作,若有则处理event,完成与用户的交互。

Chapter 9 Drag and Drop

9.1Enabling Drag and Drop

默认情况下,QTextEdit这个widget接受来自于其他程序的文本拖拽的;如果用户将一个文件拖拽至其上,它会将文件名插入显示文本。可以调用setAcceptDrops()来允许或禁止接受拖拽。

dragEnterEvent() ,该函数在用户将一个对象拖(drag)至widget之上时被调用,其参数为QDragEnterEvent类型的指针。
默认情况下,widget不接受用户的拖拽行为; 若对该指针调用acceptProposedAction(),则是告知Qt允许该widget接受用户的拖拽行为,Qt会通过改变鼠标形状来提示用户。

dropEvent() ,该函数在用户将一个对象拽(drop)至widget之上时被调用,参数为QDropEvent类型的指针。

QWidget类还提供了dragMoveMent()和dragLeaveEvent()这两个函数,但对于大多数应用而言不需要对其进行再实现。

mousePressEvent(): 鼠标被按下时该函数被调用

mouseMoveEvent() :鼠标保持按下的状态且移动时,该函数被调用。

QDrag类使用QMimeData类来存储与拖拽操作相关的信息。

9.2Supporting Custom Drag Types

可以从以下三种机制中进行选择:

1.在源这一边调用QMimeData::setData(),将信息存储在QByteArray中,而在接受者这一方,调用QMimeData::data()将信息提取出来。

2.对QMimeData进行派生,在子类中对formats()和retrieveData()这两个函数进行重新实现,来处理自定义数据。

3.如果拖拽动作发生在一个应用程序的内部,那么可以对QMimeData进行派生,将信息存储在该子类中。

QMimeData::formats()返回其支持的MIME类型列表。

QMimeData::retrieveData()将某个指定MIME类型的数据以QVariant的形式返回。QMimeData所提供 text()、html()、urls()、data()等接口函数,都是依靠retrieveData()来完成底层操作的。

9.3Clipboadr Handling

Qt中通过QApplication::clipboard()来获得对QClipboard的指针。对系统clipboard的写操作通过 setText(),setImage或setPixmap()完成,而读操作则通过text(),image()和pixmap()来完成。

QClipboard::setMimeData()

QClipboard::MimeData()
QClipboard::supportsSelection() 在X11平台下返回true,其他环境下返回fasle。

如果希望每当clipboard中的内容发生变动时收到通知,可以利用Qt提供的QClipboard::dataChanged()这个slot

Chapter 10Item View Classes

MVC机制:Model-View-Controller

Qt中提供一种模仿MVC的model/viewer机制。

Qt中的delegate这个抽象概念与Controller略微不同,它负责为item的生成和编辑提供良好的控制。
Qt为每种类型的view都提供了默认的delegate,这对于大多数应用程序已经足够了,通常情况下程序员不需要考虑delegatd的问题。

可以为一个model注册两个或更多的view,Qt自动保持多个view之间数据的同步和一致性,当数据在某个view中被修改后,会自动在其他相关view中反映出来。

大多数情况下,程序向用户提供的item的数量并不庞大,因此可以简单的使用Qt内置的item view clas(QListWidget,QTableWidget和QtreeView),而没有必要使用Qt提供的model/view 机制。但对于成员数量很大的数据集,采用model/view机制则是明智的选择。

10.1Using Item View Convenience Classes

QListWidget

QListWidget中包含多个roles,每个都与一个QVariant变量关联。最常用的roles由Qt::DisplayRole,Qt::EditRole,Qt::IconRole
对于上述role,Qt都提供了方便的接口函数用于读写数据。程序员还可以对role进行自定义,通过Qt::UserRole或更大的数值进行标识。

默认情况下QListWidget是只读的,需要调用QAbstractItemView::setEditTriggers()为其设定能引发编辑操作的动作。

QTableWidget

默认情况下QTableWidget是允许编辑的,可以调用QAbstractItemView::setEditTriggers(QAbstractItemView::NoEditTriggers)来禁止编辑。

QtreeWidget

默认情况下,QtreeWidget是只读的。

10.2Using Predefined Models

Qt提供的预定义model有以下几种:

QStringListModel存储一组字符串

QStandardItemModel存储任意层次结构的数据

QDirModel对文件系统进行封装

QSqlQueryModel对SQL的查询结果集进行封装

QSqlTableModel对SQL中的table进行封装

QSqlRelationalTableModel对带有foreign key的SQL table进行封装

QSortFilterProxyModel对另一个model执行sort and/or filter

model中存放的每项数据都有相应的" model index" ,由QModelIndex类来表示。

每个index由三个部分构成:row,column和表明所属model的指针。对于一维的list model,column部分永远为0。

在model/view 机制中,对数据的操作都是通过model执行的,而model负责保证在数据发生变动时view自动更新。

QDirModle::mkdir()--创建文件夹的工作可以通过QDir类来完成,不过QDirModel提供了工作于QModelIndex之上更方便的函数。
不同于其它model,QSortFilterProxyModel对一个已有的model进行封装,并完成数据在底层modle和view之间的传递。

setSourceModel()

10.3Implementing Custom Models

model中的每项数据都有对应的index和一组称为“role”的属性,其中最常用的有Qt::DisplayRole和Qt::EditRole。

对于list和table这两类model,其中每个元素的parent都是root,即表示为一个invalid QModelIndex。

而对于tree model,某些元素的parent为root,而有些元素的parent为model中的其它元素。

Qt中提供了几种model 基类,包括 QAbstractListModel,QAbstractTableModel和QAbstractItemModel ,其中QAbstractItemModel是另外两者的基类,用于支持范围很广的modles,包括具备递归层次结构的;而 QAbstractListModel用于支持一维数据集,QAbstractTableModel用于支持二维数据集。

实际上要创建只读的自定义model的话,并不是件困难的事情。

要自定义只读的table model的话, 需要重新实现rowCount(),columnCount()和data()这三个函数。

createIndex() 用于创建并返回一个model index

flags()被model用于表示可以对数据执行的操作(例如,是否可编辑),从QAbstractTableModel继承而来的默认实现是返回Qt::ItemSelectable | Qt::ItemIsEnabled

qDeleteALl()对一个含有指针的容器进行迭代,并对其中每个指针元素执行delete操作。

10.4Implementing Custom Delegates

view中的每个item是由delegate负责显示和编辑的,在大多数情况下,view默认的delegate足够满足用户需求。
setItemDelegate() 为view指定其delegate。

QItemDelegate & QAbstractItemDelegate

要提供一个允许编辑的自定义delegate,我们必须对createEditor(),setEditorData(),setModelData()进行重新实现,而且还必须重新实现paint()以改变item的显示。

QTimeEdit & QTime
当用户开始编辑操作时,view会调用createEditor()来创建一个Editor,然后调用setEditorData()来用item的当前值对Editor进行初始化。

免责声明:文章转载自《QT基础三》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇python 获取过去几天,过去几个月,过去几年的时间列表Fiddler Everywhere 安卓手机抓包配置下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

使用PSCI机制的SMP启动分析

    其他core的入口  文件:arch/arm64/kernel/head.S       secondary_entry: 在从bl31切到EL1上的Linux Kernel后: 第595行,在el2_setup中设置EL1和EL0为小端模式,然后将w0设置为BOOT_CPU_MODE_EL1,并返回 第596行,记录cpuX的启动模式到__b...

MFC中CWnd类及其派生类对话框、消息处理、窗口操作

http://hi.baidu.com/xiaorida21/blog/item/8d8eb77a22eedee52e73b39e.html CWnd类 我们在屏幕上看到的所有对象都和窗口有关,它们或者派生于CWnd,属继承关系,如对话框、工具栏、状态栏、子控件;或者被CWnd合成,属服务员与服务对象关系,如图标、菜单、显示设备。 CWnd类封装的窗口操...

μC/OS-III---I笔记13---中断管理

中断管理先看一下最常用的临界段进入的函数:进入临界段 OS_CRITICAL_ENTER() 退出临界段OS_CRITICAL_EXIT()他们两个的宏是这样的. 在使能中断延迟提交时: #if OS_CFG_ISR_POST_DEFERRED_EN > 0u /* Deferred ISR P...

全面总结:matlab怎么做漂亮的图

源地址:http://blog.csdn.net/ccxcau/article/details/7362764 MATLAB受到控制界广泛接受的一个重要原因是因为它提供了方便的绘图功能.本章主要介绍2维图形对象的生成函数及图形控制函数的使用方法,还将简单地介绍一 些图形的修饰与标注函数及操作和控制MATLAB各种图形对象的方法. 第一节 图形窗口与坐标系...

laravel Event执行顺序

  laravel一大特色就是event事件系统。一般首先要listen一个事件,随后fire那个事件,这时执行路径将会调用event handler,返回后继续执行。例如: Event::listen('user.login',function(KidsitUser $user){ var_dump($user); }); Route::g...

如何用BlazeDS更改图片

相信大家在实际应用中肯定会碰到这样的问题:如何动态更改网元图片或者Topo背景?本文用具体实例演示了如何从本地上传图片到服务器,并设置为Topo背景。 首先介绍一下本文用到的技术: 1. FileReferenceFileReference用于从本地打开文件,而且需要添加编译选项:-target-player=10.0.0。关于FileReference的...