Designing a "composite widget"
This is my first foray into designing a UI element with Qt, so I'd appreciate a pointer as to whether I'm going in the right direction.
I use Qt 5.7, but from Python/PyQt, not C++. No QML/Quick Controls.
The code base currently has a number of plain
QLineEditcontrols for entering dates. There is validation checking, but no interface other than typing into the widget.
I wish to implement (what I call) a "composite widget":
QLineEdit, like the existing one. (I wish to preserve this to allow users to just do in-line editing of date if they so wish.)
- A "..."
QPushButtonto the right of the line. When clicked, this will bring up a small modal dialog containing a
QCalendarWidget. This allows the user to pick a date. When picked, the dialog will close and the date will be copied back to the line edit.
- The two widgets (presumably) to be enclosed in a
QHBoxLayout, so that they appear side-by-side.
So I assume I should be designing: a top-level widget, which holds the layout, which holds the
QLineEditfollowed by the
QPushButton. Like (approximate syntax):
class JDateLineEdit(QWidget): def __init__(self): super().__init__() self.lineEdit = QLineEdit() self.button = QPushButton("...") layout = QHBoxLayout() layout.addWidget(self.lineEdit) layout.addWidget(self.button) self.setLayout(layout) self.button.clicked.connect(self.datePicker) def datePicker(): # 1. Create Dialog, containing QCalendarWidget. # 2. Copy currently selected date to be initial date on calendar. # 3. Show modal dialog, allow user interaction. # 4. Copy selected date back to QLineEdit.
Does this look about right? In particular, since my "composite widget" is composed of a
QHBoxLayoutwhich then holds 2
QWidgets, I see it that it must derive from generic
QWidget, rather than, say, directly from
whether I'm going in the right direction.
Yes, looks quite reasonable. Since you're also working with python you don't need to care about some peculiarities of C++, like if you were to design a widget that is to be put in a library, thus needing to keep the ABI binary compatible. Anyway, generally this is the correct approach.
I see it that it must derive from generic QWidget, rather than, say, directly from QLineEdit?
Unless your widget is going to modify some behaviour of
QLineEditI'd simply go with a
QWidgetsubclass. Don't forget to expose the relevant/needed signals and/or slots from the child widgets though, at least if you want to allow the user programmer to have access to them, e.g.
Thank you for confirming the approach is about right. That's what I'd do in C#/ASP.NET for a "UserControl". Qt ought to have that class :)
I tend to be a bit lazy/ad hoc about exposing signals, attributes etc. from the embedded controls. I'm well aware it's "naughty", but I'll probably allow the embedded widgets to be visible to the outside world! (Well this is Python, so I think you'd have a hard time concealing them anyway....) Then I don't have to write all that behaviour/style transference code or guess what to expose/rewrite every time I find I want to access another property/function. Just insert a (date) "value" that's the overall date for the world to access.
I tend to be a bit lazy/ad hoc about exposing signals, attributes etc. from the embedded controls. I'm well aware it's "naughty", but I'll probably allow the embedded widgets to be visible to the outside world!
Well, it's just we C++ people tend to frown on breaking encapsulation, but it will work all the same.
This discussion about "composite widgets" in general has been useful.
However, in my case of wanting to design "a line edit with a calendar popup", specifically, don't do this! I was fooled by the picture at http://doc.qt.io/qt-5/qdateedit.html#details showing it with a line-only interface. I have only just discovered that
QDateEdithas http://doc.qt.io/qt-5/qdatetimeedit.html#calendarPopup-prop (would be nice if docs showed a pic using that!), which does exactly what I had in mind.