- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
精简版QTreeView
使用的默认委托是什么?特别是我正在尝试找到其paint()
方法?
较长的版本
我是Python用户(Pyside / PyQt),并且正在使用自定义委托来重新创建QTreeView
的某些功能。因此,我试图找到在QTreeView
中使用的默认委托和绘画方法。更好的办法是对其进行解释。
交叉岗位
我在Qt中心(http://www.qtcentre.org/threads/64458-Finding-default-delegate-for-QTreeView?)发表了同样的问题。
最佳答案
tl; dr
所有项目视图的默认委托为QStyledItemDelegate
。它的paint()
方法调用在drawControl()
中定义的qcommonstyle.cpp
绘制每个项目。因此,请仔细阅读qcommonstyle.cpp
以获得有关如何绘制每个项目的细节。
长格式答案
那些喜欢简洁的人应该阅读上面的tl; dr和documentation on Styles in Item Views。如果您仍然受困(可能会有很多Python用户),那么此答案的其余部分应该会有所帮助。
一,默认委托人是QStyledItemDelegateQStyledItemDelegate
是视图中项目的默认委托。 Qt's Model/View Programming overview中明确指出:
从Qt 4.4开始,默认的委托实现由
QStyledItemDelegate,这被Qt用作默认委托
标准视图。
docs for QStyledItemDelegate
提供更多细节:
在Qt项目视图(例如QTableView)中显示模型中的数据时,
单个项目由代表绘制。另外,当一个项目是
编辑后,它提供了一个编辑器小部件,该小部件位于
编辑时进行项目视图。 QStyledItemDelegate是
所有Qt项目视图的默认委托,并安装在它们上
创建它们时。
总之,如果您想了解任何项目视图(不仅是树视图,还包括表和列表)的底层机制,请研究QStyledItemDelegate
。paint()
中的qstyleditemdleegate.cpp
方法在on line 419 of the doxygenated code base中定义。让我们看一下最后两行:
QStyle *style = widget ? widget->style() : QApplication::style();
style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
QApplication.style()
。其次,调用该样式的
drawControl()
方法以绘制要绘制的项目。就是这样。这实际上是
QStyledItemDelegate.paint()
的最后一行!
QApplication
时以系统特定的方式选择的某种样式绘制它。从
the docs for QStyle:
src/gui/styles/N.cpp
中找到样式N的源代码。
QWindowsStyle
)继承了
QCommonStyle
的大多数方法。每个特定样式通常仅包含与该共同基础的微小偏差。因此,对
qcommonstyle.cpp
的深入研究将揭示Qt开发人员发现对绘制GUI的所有部分有用的基本功能。它的重要性很难夸大。
drawControl()
中
qcommonstyle.cpp
的实现,该实现始于第1197行。在以下提到的内容中,当我指代行号而未提及文件名时,按照惯例,我指的是
qcommonstyle.cpp
in the doxygenated code base。
QStyleOption
对象并包含所需的所有信息
drawControl()
标志来告知
QStyle.ControlElement
尝试绘制哪种元素。控件是窗口的高层组件,向用户显示信息:复选框,按钮和菜单项之类的信息。这里列举了所有控制元素:
QStyledItemDelegate.paint()
的控制元素是
CE_ItemViewItem
,它只是一个要在项目视图中显示的项目。在
QCommonStyle.drawControl()
中,
CE_ItemViewItem
的情况从2153行开始。让我们深入研究。
drawControl()
计算的第一件事。为了获得此信息,它调用
subElementRect()
(在第2313行中定义,首先在第2158行中调用)。例如,我们有:
QRect textRect = subElementRect(SE_ItemViewItemText, vopt, widget);
QStyle.SubElement
标志,在本例中为
SE_ItemViewItemText
。样式子元素代表控制元素的组成部分。视图中的每个项目都具有三个可能的子元素:复选框,图标和文本。显然,
SE_ItemViewItemText
子元素表示文本。此处列举了所有可能的子元素:
subElementRect()
方法包含子元素枚举中的所有情况:我们的
SE_ItemViewItemText
情况从第3015行开始。
subElementRect()
返回一个
QRect
,它使用整数精度在平面中定义一个矩形,并且可以用四个整数(左,上,宽,高)构造。例如
r1 = QRect(100, 200, 11, 16)
。对于子元素,它指定其大小以及将在视口中绘制的x,y位置。
subElementRect()
实际上调用
viewItemLayout()
(在第999行定义)进行实际工作,这是一个两步过程。首先,
viewItemLayout()
使用
viewItemSize()
计算子元素的高度和宽度。其次,它计算子元素的x和y位置。让我们依次考虑这些操作。
viewItemLayout()
调用
viewItemSize()
(在第838行中定义),它计算子元素所需的高度和宽度。
viewItemSize()
在哪里获得标题栏高度之类的默认数字?这是像素指标的范围。像素度量是由单个像素值表示的样式相关大小。例如,
Style.PM_IndicatorWidth
返回复选框指示符的宽度,而
QStyle.PM_TitleBarHeight
返回应用程序样式的标题栏高度。这里列举了所有不同的
QStyle.PixelMetric
:
viewItemSize()
中经常使用。
pixelMetric()
的第一个输入是枚举中的
QStyle.PixelMetric
之一。在
qcommonstyle.cpp
中,
pixelMetric()
的实现始于第4367行。
viewItemSize()
使用以下方法计算复选框的宽度和高度(如果需要):
return QSize(proxyStyle->pixelMetric(QStyle::PM_IndicatorWidth, option, widget),
proxyStyle->pixelMetric(QStyle::PM_IndicatorHeight, option, widget));
pixelMetric()
不仅在
viewItemSize()
中使用,而且无处不在。它用于计算许多GUI元素(从窗口边框到图标)的度量属性,并且在整个
qcommonstyle.cpp
中使用。基本上,每当您需要知道样式用于大小不变的某些图形元素(例如复选框)使用多少像素时,样式就会调用像素度量。
viewItemLayout()
的第二部分致力于组织刚刚计算出宽度和高度的子元素的布局。也就是说,它需要找到它们的x和y位置以完成将值填充到
QRect
中,例如
textRect
。根据视图的一般设置(例如,左右方向还是左右方向),子元素的组织方式会有所不同。因此,
viewItemLayout()
根据此类因素计算每个子元素的最终静止位置。
sizeHint()
的线索,
subElementRect()
可能是有用的提示和技巧。特别是,当您希望自定义视图与默认值紧密匹配时,
viewItemSize()
可能包含有用的花絮和您可能要查询的相关像素指标。
QRect
,
drawControl()
就继续前进,最后开始绘制。
drawPrimitive(PE_PanelItemViewItem, option, painter);
QStyle.drawControl()
的调用,但是第一个参数不是控制元素,而是原始元素(PE)。就像
drawControl()
是控制所有高级控件元素的绘制的大型扩展方法一样,
QStyle.drawPrimitive()
在GUI中绘制大多数较低级的原始图形元素(例如项目视图中的矩形背景)。这些低层单元,即原始元素,在这里列举:
PE_PanelItemViewItem
基本元素是“项目视图中项目的背景”。
drawPrimitive()
的实现,而我们的样式必须从第140行开始。在其中,您可以详细了解其如何执行其原始绘制操作。这是有关如何在您的自定义委托中实践中使用
paint()
命令的有用提示来源。
QStyle.drawPrimitive()
情况,重新实现
PE_PanelItemViewItem
从773行开始。它首先根据项目的状态选择适当的背景色。它通过查询项目的
QStyle.StateFlag
来实现。
option.state
包含描述该项目当时状态的状态标志(是否已启用,已选择,正在编辑等)。这些状态不仅在后端使用,而且在自定义委托中重新实现
QStyledItemDelegate.paint()
时,您可能需要使用它们。您可以在此处找到
QStyle.StateFlag
的枚举:
drawPrimitive()
然后使用
QPainter.fillRect()
用该颜色填充适当的区域(第786行):
p->fillRect(vopt->rect, vopt->backgroundBrush);
QPainter.fillRect()
是非常有用的方法。
drawControl()
然后继续完成绘制项目,从复选框(第2165行)开始,然后是图标(第2185行),最后是文本(第2194行)。我们将不做详细介绍,但我将简要讨论它是如何绘制文本的。
QStyle.StateFlags
。然后
drawControl()
将文本绘制职责踢出自定义方法
viewItemDrawText()
(在第921行定义):
viewItemDrawText(painter, vopt, textRect);
QStyleOption
类,通过该类可以在样式内传递内容(它包括图标,检查状态和文本属性)。
QtGui.QTextLine
的
QtGui.QTextLayout
中。最后的被省略的文本(即,用椭圆表示,取决于自动换行设置)由
QPainter.drawText()
绘制(请参阅第983行),这是Qt的原始绘画操作之一。
viewItemDrawText()
用于处理自动换行。这是我们开始了解一些Qt胆量的地方,这是Python用户从未想过的,更不用说修补了。例如,它使用
QStackTextEngine
类。我鼓励您使用Google'qstacktextengine pyqt',以了解Python用户很少遇到这种情况。如果您对此感兴趣,请尝试一下!
QStyle.drawControl()
中
qcommonstyle.cpp
的实现。此练习对于弄清楚用于计算尺寸和绘制项目所包含的原始图形元素的确切过程非常有帮助。但是,有时候,这头野兽可能会变得非常恐怖和无助,例如在处理自动换行时。在这种情况下,您可能只需要为委托人找出所需功能的自定义实现即可。
QStyle
的文档,特别是
Styles in Item Views部分的帮助。在那里,我们发现了以下启示性的爱情金块:
QStyledItemDelegate
也用于计算
QStyledItemDelegate
绘制其项目,绘制
CE_ItemViewItems
…当
QCommonStyle
(以及其他任何子类)的实现
关于qt - Qt中项目 View 的默认委托(delegate)的机制是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33990029/
我看了很多文章,但我仍然不清楚我们通常创建的普通委托(delegate)和多播委托(delegate)之间的区别。 public delegate void MyMethodHandler(objec
考虑以下几点: Action a1 = new Action(_insert); Action a2 = new Action(a1); a2 指的是什么?它是 a1,a1 的浅拷贝还是 a1 的深拷
我希望这听起来像是一个显而易见的问题,但是委托(delegate)返回类型是否也必须与其委托(delegate)的方法的返回类型相匹配? EG,像这样: public static void Save
我想使用 Kotlin 委托(delegate),但我不想在委托(delegate)人之外创建委托(delegate)。委托(delegate)的所有示例都如下所示: interface Worker
class SuperClass { var delegate : SuperClassDelegate? } protocol SuperClassDelegate { func d
我有一个加载 View 的 View ,需要将 View 推送到主导航 Controller 。 我已经为每个 View 设置了一个委托(delegate),并且基本上使我的调用沿着“链”返回到主导航
为简单起见,假设我想创建一个自定义 UITextField 并向其添加一个简单的行为;也就是说,如果文本字段成为第一响应者,背景颜色将变为绿色。 为此,在我的自定义类中,我必须将该类设置为委托(del
我非常有信心我应该能够使用非静态方法的委托(delegate),但下面给了我一个错误: public class TestClass { private delegate void TestD
在 C# 中不能从 System.Delegate 或 System.MulticastDelegate 继承。只要您声明标准的“运行时托管”方法,就完全可以在 MSIL 中执行此操作。但是,每次我向
我在 Storyboard 中定义了一个 iPad 界面,带有一个 SplitViewController。我想将 SplitViewController 的委托(delegate)设置为指向详细 C
我有几个解析器。有一个顶级的可以委托(delegate)给另一个。 Parser我们从 Reader 中获取他们的输入(可变)。我只想要一个 Parser为了能够一次解析,只有一个解析器应该有 Rea
一直以来我都在阅读关于反射的文章,每个人都在说:“反射很慢”,“反射很慢”。 现在我决定测试速度有多慢,令我惊讶的是,使用反射创建的委托(delegate)实际上是使用 lambda 创建的委托(de
在 Xcode 4.5 中启动了 Cocos2D 2.1 模板(没有物理引擎),针对 iOS 6 和 iPad。在 CDAudioManager.m 文件中,以下代码... AVAudioSessio
以下是来自未管理的 dll 的函数代码。它接受一个函数指针作为参数,并简单地返回被调用函数返回的值。 extern __declspec(dllexport) int _stdcall callDe
//NewCharts.h #import @interface NewCharts : UIViewController @property(nonatomic,retain)IBOutlet U
鉴于以下 MSDN 示例代码,为什么我不能定义 Action 委托(delegate)“内联”: public static void Main(string[] args) { Action
在虚幻引擎中,UFUNCTION用于通过附加说明符来丰富功能,以用于蓝图使用、复制和委托(delegate)。 然而,一些委托(delegate)类型似乎不允许绑定(bind) UFUNCTION(如
我刚刚将照片选择器放入我的项目中,一切正常。唯一的事情是它坚持在我设置委托(delegate)的地方给我以下警告 - Assigning to 'id' from incompatible type
我有一个 UIImageView 的子类,并且想将 self 作为参数传递给委托(delegate)。我在 MyImageView 之前收到错误“预期 ')'”。我需要将对象传递给委托(delegat
我正在开发 iOS 10 的语音转文本功能。 我希望调用 SFSpeechRecognitionTaskDelegate 的委托(delegate)方法来检查完成的结果。 func speechRec
我是一名优秀的程序员,十分优秀!