如何使用c++继承和扩展QCalendarWidget ?

时间:2022-09-24 23:21:07

At present the QCalendarWidget only supports SingleSelection or NoSelection. I'd like to be able to write a widget that inherits from QCalendarWidget in Qt 4.6.2 and adds the ability for the user to select any day in a week and have that custom week selected.

目前,QCalendarWidget只支持SingleSelection或NoSelection。我希望能够编写一个小部件,它可以从Qt 4.6.2中继承QCalendarWidget,并添加用户在一周内选择任何一天的能力,并选择自定义周。

e.g. Click on Thu 5 August 2010 and all days from Saturday 31 July to Friday 6 August inclusive get selected.

例如:点击2010年8月5日,从7月31日星期六到8月6日的所有日子,包括被选中。

My experience with Qt is limited and it's been a while since I've done some C++ so do I need to worry about implementing a copy constructor or virtual destructors when inheriting in Qt, or any other pitfalls to be aware of? What would the header and cpp files look like for such a custom widget and where is the best place to add my custom paint logic and SelectionMode?

我对Qt的体验是有限的,我已经有一段时间没有做过c++了,所以我需要担心在Qt继承时实现一个复制构造函数或虚拟析构函数,或者其他需要注意的陷阱吗?对于这样一个自定义小部件,标题和cpp文件会是什么样子?在哪里可以添加我的自定义的绘图逻辑和选择模式?

I'm using gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) and Qt 4.6.2

我使用的是gcc版本4.4.3 (Ubuntu 4.4.3-4ubuntu5)和Qt 4.6.2。

1 个解决方案

#1


1  

After reading the QCalendarWidget source code, it seems to me this might be the case for inheritance, but there will be issues.

在阅读了QCalendarWidget源代码之后,我觉得这可能是继承的理由,但也会有问题。

First, classes that derive from QObject, widgets included, shouldn’t have copy constructors. The explanation for this is here. The QObject destructor is virtual, so no matter how you declare yours, it will be virtual too.

首先,来自QObject(包括小部件)的类不应该有复制构造函数。对此的解释是这样的。QObject析构函数是虚拟的,因此无论您如何声明它,它也将是虚拟的。

When extending a class to change its behavior, look for virtual functions. If there aren’t any, it’s a good indication that inheritance might not be the best approach. In this case, we have three virtual methods:

当扩展一个类来改变其行为时,查找虚拟函数。如果没有,这说明继承可能不是最好的方法。在这种情况下,我们有三个虚拟方法:

virtual QSize sizeHint() const;
virtual QSize minimumSizeHint() const;
virtual void paintCell(QPainter *painter, const QRect &rect, const QDate &date) const;

The first two are virtuals from QWidget and deal with sizing the widget. They are probably not important. The last one might do part of what you want: making the whole week appear selected when a day of that week is picked by the user.

前两个是QWidget的虚拟机,并处理小部件的大小。它们可能并不重要。最后一个可能会做你想做的部分:当用户选择一周的某一天,让整个星期都被选中。

Now, for the possible issues:

现在,对于可能的问题:

The selection mode property is non-virtual and, moreover, is enum-valued. One cannot extend the enumerated type to include the new proposed WeekSelection value. If you don’t have to change selection modes on runtime, you can safely ignore this property and work only with week selections. (Ignoring a property is a good indication that your widget should probably have a QCalendarView and not be a QCalendarView.)

选择模式属性是非虚的,而且,它的值是被赋值的。不能将枚举类型扩展为包含新建议的周选择值。如果您不需要在运行时更改选择模式,您可以安全地忽略此属性,只在周选择时工作。(忽略属性是一个很好的迹象,表明您的小部件应该有一个QCalendarView,而不是一个QCalendarView。)

QCalendarView is also a composite widget (unlike a label or push button). Internally, it is made of a QTableView, many QToolButtons, a QSpinBox and so on. This kind of widget is harder to extend by inheritance, because you don’t have access to its internals and most of the behavior (such as painting and handling input events) is done by the internal widgets, not by QCalendarView itself.

QCalendarView也是一个复合小部件(不像标签或按钮)。在内部,它由一个QTableView、许多QToolButtons、一个QSpinBox等组成。这种小部件很难通过继承扩展,因为您无法访问它的内部构件,而且大多数行为(比如绘画和处理输入事件)都是由内部小部件完成的,而不是由QCalendarView本身完成的。

In some situations, you can hunt for the children widgets using findChildren() and modify their behavior by changing properties and installing event filters. This is prone to break, however, because Nokia can change the internals from 4.6.2 to 4.6.3 as long as the public binary interface of the class is preserved.

在某些情况下,您可以使用findChildren()来搜索子部件,并通过更改属性和安装事件过滤器来修改它们的行为。但是,这很容易中断,因为只要保持类的公共二进制接口,Nokia就可以将内部构件从4.6.2更改为4.6.3。

Ask yourself if the new widget must inherit from QCalendarWidget. If not and inheriting leads you to a dead end, consider copying the source code of QCalendarWidget and adapting it to your needs. You can go even further and clone the Qt source code, change the original widget itself to include your behavior and propose a merge request back to Nokia.

问自己新部件是否必须从QCalendarWidget继承。如果不是并且继承导致了您的死,考虑复制QCalendarWidget的源代码并根据您的需要调整它。您可以更进一步,克隆Qt源代码,更改原始的小部件本身,以包含您的行为,并向诺基亚提出合并请求。

#1


1  

After reading the QCalendarWidget source code, it seems to me this might be the case for inheritance, but there will be issues.

在阅读了QCalendarWidget源代码之后,我觉得这可能是继承的理由,但也会有问题。

First, classes that derive from QObject, widgets included, shouldn’t have copy constructors. The explanation for this is here. The QObject destructor is virtual, so no matter how you declare yours, it will be virtual too.

首先,来自QObject(包括小部件)的类不应该有复制构造函数。对此的解释是这样的。QObject析构函数是虚拟的,因此无论您如何声明它,它也将是虚拟的。

When extending a class to change its behavior, look for virtual functions. If there aren’t any, it’s a good indication that inheritance might not be the best approach. In this case, we have three virtual methods:

当扩展一个类来改变其行为时,查找虚拟函数。如果没有,这说明继承可能不是最好的方法。在这种情况下,我们有三个虚拟方法:

virtual QSize sizeHint() const;
virtual QSize minimumSizeHint() const;
virtual void paintCell(QPainter *painter, const QRect &rect, const QDate &date) const;

The first two are virtuals from QWidget and deal with sizing the widget. They are probably not important. The last one might do part of what you want: making the whole week appear selected when a day of that week is picked by the user.

前两个是QWidget的虚拟机,并处理小部件的大小。它们可能并不重要。最后一个可能会做你想做的部分:当用户选择一周的某一天,让整个星期都被选中。

Now, for the possible issues:

现在,对于可能的问题:

The selection mode property is non-virtual and, moreover, is enum-valued. One cannot extend the enumerated type to include the new proposed WeekSelection value. If you don’t have to change selection modes on runtime, you can safely ignore this property and work only with week selections. (Ignoring a property is a good indication that your widget should probably have a QCalendarView and not be a QCalendarView.)

选择模式属性是非虚的,而且,它的值是被赋值的。不能将枚举类型扩展为包含新建议的周选择值。如果您不需要在运行时更改选择模式,您可以安全地忽略此属性,只在周选择时工作。(忽略属性是一个很好的迹象,表明您的小部件应该有一个QCalendarView,而不是一个QCalendarView。)

QCalendarView is also a composite widget (unlike a label or push button). Internally, it is made of a QTableView, many QToolButtons, a QSpinBox and so on. This kind of widget is harder to extend by inheritance, because you don’t have access to its internals and most of the behavior (such as painting and handling input events) is done by the internal widgets, not by QCalendarView itself.

QCalendarView也是一个复合小部件(不像标签或按钮)。在内部,它由一个QTableView、许多QToolButtons、一个QSpinBox等组成。这种小部件很难通过继承扩展,因为您无法访问它的内部构件,而且大多数行为(比如绘画和处理输入事件)都是由内部小部件完成的,而不是由QCalendarView本身完成的。

In some situations, you can hunt for the children widgets using findChildren() and modify their behavior by changing properties and installing event filters. This is prone to break, however, because Nokia can change the internals from 4.6.2 to 4.6.3 as long as the public binary interface of the class is preserved.

在某些情况下,您可以使用findChildren()来搜索子部件,并通过更改属性和安装事件过滤器来修改它们的行为。但是,这很容易中断,因为只要保持类的公共二进制接口,Nokia就可以将内部构件从4.6.2更改为4.6.3。

Ask yourself if the new widget must inherit from QCalendarWidget. If not and inheriting leads you to a dead end, consider copying the source code of QCalendarWidget and adapting it to your needs. You can go even further and clone the Qt source code, change the original widget itself to include your behavior and propose a merge request back to Nokia.

问自己新部件是否必须从QCalendarWidget继承。如果不是并且继承导致了您的死,考虑复制QCalendarWidget的源代码并根据您的需要调整它。您可以更进一步,克隆Qt源代码,更改原始的小部件本身,以包含您的行为,并向诺基亚提出合并请求。