- 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/
我在尝试从子文件夹调用 View 时遇到一些错误。首先,这东西能用 Route::get('/', function() { return View::make('sample'); }); 但是当我
我有另一个 View 设置,并准备好等待其viewmodel。我的RelayCommand到达我的“当前” View 模型。从当前的 View 模型显示新 View 的最佳方法是什么? 我一直在阅读,
我有一个 bigquery View ,我想与数据分析师共享,以便他们可以通过 Data Studio 访问其数据。此共享 View 对另一个数据集中的私有(private) View 进行查询,而私
我有 3 个 View ,并希望将它们集成到一个 View 中,以便它们成为这一 View 中的子文件夹。 我怎样才能做到这一点?还是我必须制作一个 View ,然后再次手动添加和配置这些 View
我在沙发数据库中有一些文档,这些文档的字段是不同关联文档的ID数组: { associatedAssets: ["4c67f6241f4a0efb7dc2abc24a004dfe", "270f
我正在开发一个小实用程序 View ,它将嵌入到我们的几个应用程序中。它将位于一个公共(public)图书馆中。 我应该将其作为 ViewModel 以及默认的 View 实现公开,还是作为具有固定
由于我的某些 View 具有相似的功能,因此我希望能够与每个 View 共享相同的 View 模型。我的想法是将 token 传递给viewmodel的构造函数,但这将导致代码中出现许多if和else
我有一个目标 View (蓝色 View 和红色 View 用于左上角位置)。我试图用手指移动这个 View 。如果 View 不旋转,一切都很好。 但当我旋转 View 并移动时,第一次就很好了。但
我收到这个错误, "Attempt to invoke virtual method 'android.view.View android.view.View.getRootView()' on a
我将发布我目前拥有的源代码,然后解释我的问题。 这是我希望过渡发生的窗口 这是关联的 View 模型 public class MainViewModel {
我正在尝试找出我遇到的错误。最初,我的同事只是使用 将 View 添加到 subview 中 [self.view addSubview:someController.view]; 来自当前ViewC
我是 MVVM 的新手,需要一些帮助。 我的应用程序由许多不同的窗口组成,这些窗口显示允许用户编辑业务层中的数据的控件。 目前,每次用户打开这些窗口之一的新实例时,都会从头开始创建一个 ViewMod
我一直在寻找与我类似的问题以找到解决方案,但我真的找不到类似的东西。 我试图使用 asynctask 类从解析中下载帖子数组,在获取帖子后,它应该在我的页面中设置帖子数组,并执行 setAdapter
这个问题在这里已经有了答案: What is local/remote and no-interface view in EJB? (2 个答案) 关闭 9 年前。 我以前理解它的意思是“接口(in
希望这不会太困惑。 我有一个主视图 Controller ( MainView ),在 View 底部有一个堆栈 View ,在堆栈 View 中我有三个 View 。在一个 View 中(我们称之为
我一直在想这个问题,我真的不知道如何正确地将一个 View Controller 管理的 View 添加到另一个 View Controller 的 View 中。 这不起作用,因为 View 没有完
在明显的情况下,我必须将大量文件从一个 View 复制到另一个 View 。要复制的文件名将作为输入给出。有什么想法可以通过脚本实现吗? 谢谢,日语 最佳答案 最简单的方法是使用 clearfsimp
我正在使用完整日历。这里我的问题是,当单击上一个按钮或下一个按钮单击功能时,如何找到月 View 、周 View 或日 View 格式的完整日历。这里正在调用下一个和上一个按钮的自定义代码。因为使用这
我对这两者感到困惑,并试图找出差异,但没有得到我正在寻找的特定内容。 在哪里使用索引 View 而不是普通 View 。 它们之间的一些重要区别。 最佳答案 关键的区别在于物化 View 很好,物化了
我在一个 xib 中有一个 CustomView,在两个不同的 xib 中有两个不同的 View 。我想在一个 CustomeView 中依次显示这两个 View 。我有一个 NSView 对象,它连
我是一名优秀的程序员,十分优秀!