2.QWidget类

简述:

  QWidget类是所有用户界面对象的基类。

  Widget是用户界面的基本单元:它从窗口系统接收鼠标,键盘和其他事件,并在屏幕上绘制自己。

  每个Widget都是矩形的,它们按照Z-order进行排序。 

 

注:Z-order是重叠二维对象的顺序,例如堆叠窗口管理器中的窗口。典型的GUI的特征之一是窗口可能重

叠,使得一个窗口隐藏另一个窗口的一部分或全部。 当两个窗口重叠时,它们的Z顺序确定哪个窗口出现在

另一个窗口的顶部。

理解:术语"z-order"指沿着z轴物体的顺序。三维坐标轴中x横轴,y数轴,z上下轴。可以将gui窗口视为平

行与显示平面的一系列平面。因此,窗口沿着z轴堆叠。所以z-order指定了窗口的前后顺序。就像你桌面上

的一堆纸一样,每张纸是一个窗口,桌面是你的屏幕,最上面的窗口z值最高。

 

  一个控件,没有被嵌入父类控件,被称为顶级窗口。一般情况下,窗口有一个框架和标题。可以创建没

有框架和标题的窗口,通过合适的window flags。在qt中QMainWindow和QDialog及其子类是最常见的

窗口类型。

  每一个widget的构造函数接收一个或两个标准参数:

1.QWidget *parent = 0。如果是0(默认),新建的控件是一个顶级窗口。如果不是0,它将是一个子

窗口,受父窗口的几何约束。(除非设置window flag为 Qt::Window)

2.Qt::WindowFlags f = 0 设置window flag。默认0,基本适合所有的窗口控件。但是如果没有Qt窗口

系统,新建一个窗口必须使用特殊的flag。

  QWidget有很多的成员函数,但是有些没有作用。比如QWidget有一个font属性,但是从不使用。

QWidget的一些子类,提供真的有作用的函数。比如 QLabel、QPushButton、QListWidget、

QTabWidget。

 

 Top-Level and Child Widgets

  没有父窗口的控件总是一个独立的窗口(顶级控件)。 对于这些小部件,setWindowTitle()和

setWindowIcon()分别设置标题栏和图标。

  非窗口控件是子窗口控件,显示在其父窗口控件中。Qt中的大多数widget主要用作子窗口控件。例如,

可以将按钮显示为顶级窗口,但大多数人喜欢将按钮放在其他widget,例如QDialog。

      

  上图显示了一个QGroupBox控件,用于在QGridLayout提供的布局中保存各种子窗口控件。

  如果要使用QWidget来容纳子窗口控件,则通常需要向父级QWidget添加布局。 有关详细信息,请

参阅布局管理。

 

Composite Widgets (组合控件)

  当一个控件用作容器来组织一些子窗口控件时,它被称为组合窗口小部件。例如上图中的QGroupBox。这种组合控件,

一般是构造函数创建一个有视觉属性的widget,比如QFrame。然后添加小控件,小控件用布局管理。

  复合窗口小部件也可以通过子类化标准窗口小部件(如QWidget或QFrame)以及在子类的构造函数中添加必要的布局

和子窗口小部件来创建。 Qt提供的许多示例使用这种方法,它也在Qt教程中介绍。 

  

Custom Widgets and Painting

  由于QWidget是QPaintDevice的子类,因此QWidget的子类来可以使用QPainter类的实例进行一系列绘图操作来显示自

定义内容。

  每个窗口小部件都在其paintEvent()函数内执行所有的绘画操作。 每当需要重新绘制小部件时,无论是由于某些外部更

改还是应用程序请求,都会调用此操作。

  

Size Hints and Size Policies

  实现新的widget时,重写sizeHint()几乎总是有用的,为窗口小部件提供合理的默认大小,并用setSizePolicy()

设置正确的大小策略。

  默认情况下,复合窗口不提供size Hint,而是根据其子窗口小部件的空间要求进行调整大小。

  SizePolicy允许您为布局管理系统提供良好的默认行为,以便其他小部件可以轻松地包含和管理您的内容。 默认

SizePolicy表示size Hint表示窗口小部件的首选大小,这对于许多窗口小部件通常是足够好的。

注意:顶级小部件的大小限制在桌面的高度和宽度的2/3。 如果这些边界不足,您可以手动调整()窗口小部件。

 

Event

  窗口小部件响应通常由用户操作引起的事件。 Qt传递事件给widget通过调用事件处理函数。事件处理函数的参数是一个

QEvent子实例。子实例告诉我们事件的基本信息。

  如果您的窗口小部件仅包含子窗口小部件,则可能不需要实现任何事件处理程序(默认函数足够)。 如果你想检测一个

鼠标单击在窗口中的一个子窗口事件:调用窗口的mousePressEvent()函数,mousePressEvent()函数中调用子窗口

的underMouse()函数。

  您将需要为自己的小部件提供行为和内容,但以下是与QWidget相关的事件的简要概述,以最常见的方式开始:

1.每当需要重绘时,都会调用paintEvent()。 自定义的窗口都必须实现这个函数。 使用QPainter绘制只能在

paintEvent()或paintEvent()调用的函数中进行。

2.当调整窗口部件大小时调用resizeEvent()。

3.当鼠标光标位于部件内部按下鼠标按钮时,或当部件使用grabMouse()抓住鼠标时,将会调用mousePressEvent()。

按下鼠标而不释放它与调用grabMouse()有相同的效果。

4.当鼠标按钮被释放时,mouseReleaseEvent()被调用。 当接收到相应的鼠标按压事件时,部件同时接收鼠标释放事件。

这意味着如果用户在您的部件中按下鼠标,然后将鼠标拖动到其他位置,在释放鼠标之前,部件将收到鼠标release事件。

有一个例外:如果在按住鼠标按钮的同时出现弹出菜单,则此弹出菜单会立即窃取鼠标事件。

5.当用户在窗口部件中双击时,会调用mouseDoubleClickEvent()。 如果用户双击,该部件将接收鼠标按键事件,鼠标

释放事件,最后是该事件,而不是第二个鼠标按下事件。 (如果在此操作期间鼠标未稳定,则还可能会接收到某些鼠标移动

事件。) 程序无法区分是不是DoubleClick事件,直到第二次鼠标点击到达。

 

  接受键盘输入的部件需要重新实现更多的事件处理程序:

1.keyPressEvent()在按下一个键时被调用,并且当一个键被按下足够长时间以使其自动重复时再次调用。 Tab和Shift键

都是qt焦点机制的关键字。如果要强制这些键由您的部件处理,您必须重新实现QWidget :: event()。

2.当控件获得键盘的焦点时(调用setFocusPolicy()使控件获得焦点),调用focusInEvent()。表现良好的部件表明他

们以清晰而谨慎的方式拥有键盘焦点。

3.当部件失去键盘焦点时,调用focusOutEvent()。

 

  您可能需要重新实现一些较不常见的事件处理程序:

1.只要按住鼠标按钮并拖动鼠标就会调用mouseMoveEvent()。 这在拖放操作中可能很有用。

如果您调用setMouseTracking(true),即使没有按钮被按下,您也可以获取鼠标移动事件。 

2.keyReleaseEvent()每当一个键按下时被释放时调用。(如果该键是自动重复的),在这种情况下,部件将为每次重复

接收一对密钥释放和按键事件。

3.当控件有焦点,并滚动鼠标上的滑轮时,wheelEvent()事件被调用。

4.当鼠标进入窗口部件的屏幕空间时,将调用enterEvent()。这不包括任何部件的子类拥有的屏幕空间。

5.当鼠标离开窗口部件的屏幕空间时,将调用leaveEvent()。 如果鼠标进入一个部件,它不会导致leaveEvent()。

6.当部件移动到其父项时,将调用moveEvent()。

7.当用户关闭窗口部件时调用closeEvent()(或者调用close()时)。

 

  在QEvent :: Type的文档中也有一些相当模糊的事件。 要处理这些事件,您需要直接重新实现event()。

  event()的默认实现处理Tab和Shift + Tab(移动键盘焦点),并将大多数其他事件传递给上面更专业

的处理程序处理。  

  事件系统中涵盖了事件和用于传递的机制。

 

Groups of Functions and Properties

  

 

Widget Style Sheets

  除了每个平台的标准窗口部件样式外,窗口部件也可以根据样式表中指定的规则进行样式化。 此功能使您能够自定义特定部件的外观,以向用户提供有关其目的的视觉提示。 例如,可以以特定方式对按钮进行风格化以指示其执行破坏性动作。

  Qt样式表文档中更详细地描述了窗口部件样式表的使用。

 

Transparency and Double Buffering(透明度和双缓冲)

  自Qt 4.0起,QWidget自动对其绘制进行双缓冲,因此不需要在paintEvent()中写入双缓冲代码,以避免闪烁。

  自Qt 4.1起,Qt::WA_ContentsPropagated 属性已被弃用。只要没有设置Qt::WA_PaintOnScreen,默认情况下,父窗口部件的内容将传播给每个子项。自定义的控件可以利用这个特征,更新不规则区域(创建非矩形窗口部件),或使用颜色少于alpha组件来绘制自定义控件。下图显示了如何通过微调自定义窗口部件的属性来实现不同的效果。

          

  在上图中,构造了一个具有半透明矩形子窗小部件,并将其添加到父窗口小部件(QLabel显示为像素图)。 然后,设置不同的属性和部件属性来实现不同的效果:

1.左窗口部件没有设置其他属性或窗口部件属性。 这种默认状态适用于大多数自定义小部件使用透明度,不规则形状,或者不用不透明的画笔在整个区域上绘制。

2.中心部件具有autoFillBackground属性集。 此属性用于依靠窗口部件提供默认背景的自定义窗口小部件,并且不要使用不透明的画笔在其整个区域上绘制。

3.属性组件具有Qt::WA_OpaquePaintEvent部件属性集。 这表示窗口部件将用不透明的颜色在其整个区域上绘制。 窗口部件的区域最初将初始化,在图中表示为红色对角网格图案,通过覆盖区域发光。 Qt :: WA_OpaquePaintArea属性对于需要快速绘制自己的专用内容并且不需要默认填充背景的小部件很有用。

 

  要使用简单的背景颜色(如实时绘图或绘图部件)快速更新自定义小部件,最好选择合适的背景颜色(使用setBackgroundRole()和  QPalette::Window角色),设置autoFillBackground属性,并且只能在窗口小部件的paintEvent()中实现必要的绘图功能。

  要快速更新使用不透明内容(例如视频流部件),最好设置部件的Qt :: WA_OpaquePaintEvent,以避免与重新绘制部件背景相关的任何不必要的开销。

  如果窗口小部件同时具有Qt :: WA_OpaquePaintEvent部件属性和autoFillBackground属性集,则Qt :: WA_OpaquePaintEvent属性优先。 根据您的要求,您应该选择其中之一。

  由于Qt 4.1,父窗口部件的内容也被传播到标准的Qt窗口部件。 如果父窗口小部件以非标准方式进行装饰,则可能会导致一些意外的结果,如下图所示。

 

      

  

 

  

  

 

  

posted @ 2017-05-31 14:59  billxyd  阅读(20382)  评论(0编辑  收藏  举报