need help to design an extensible widget
-
I have a MDI window. When a subwindow is opened, I set a widget as the subwindow
auto *w{new MyWidget}; auto *subWindow{m_mdiArea->addSubWindow(w)}; subWindow->setWindowTitle("my window"); subWindow->setFixedSize(subWindow->sizeHint()); subWindow->show();
This widget contains itself another widget. What I would like to achieve is adding a second widget inside MyWidget layed out horizontally with the already existing widget and placed to the right of it. Its initial state would be to be hidden and I would like to toggle its visibility on and off in a way that takes as little as possible space from MyWidget space.
I have seen in a tutorial how this is something very common in extensible dialog design where you have a 'more' button and clicking on it, toggles the visibility on and off of some extra dialog components.
However, I want my widget design to remain very slick. I wish that I could connect the windows right border as if it was some sort of QSizeGrip but this does not seem to be an option...
Perhaps the best that can be done would be to add a flat textured QPushButton that would be very thin and be of the same height as its containing parent that would act as some sort of clickable border to toggle the visibility of my second widget...
Does that sound like a good idea?
Is this something that has been done before publicly available that could look at how they have solved this challenge? -
@lano1106 said in need help to design an extensible widget:
Perhaps the best that can be done would be to add a flat textured QPushButton that would be very thin and be of the same height as its containing parent that would act as some sort of clickable border to toggle the visibility of my second widget
Furiously makes me think of a QSplitter ;)
-
@mpergand yes. I have thought about QSplitter
but can it be configured in such a way that by simply clicking it, one of the widgets is going to appear/be hidden?
I do not want users to be able to slide the control and have to complexify my code to figure out how to be displayed in an intermediate width... I am really looking for an on/off solution...
Pretty much like an extensible dialog box... (with a QSplitter type of button)
I have returned to QSplitter documentation. It seems like if I play with its property opaqueResize and the method setCollapsible(), I could get very close to what I want to achieve... I just need to figure out how to have the second widget collapsed at the initial state... Is a QSplitter child collapsed means its visibility is set to false?
Maybe a user will tell... or else the source code will tell for sure...
-
maybe by subclassing QSplitterHandle:
class Splitter : public QSplitterHandle { public: Splitter(QSplitter* parent=nullptr) : QSplitterHandle(Qt::Horizontal, parent) {} protected: void mouseReleaseEvent(QMouseEvent *) override { int width2=200; // 2nd panel int splitWidth=splitter()->width(); if(splitter()->widget(1)->width()==0) splitter()->setSizes({splitWidth-width2,width2}); else splitter()->setSizes({splitWidth,00}); } void mouseMoveEvent(QMouseEvent *) override { } };
you have to subclass QSplitter as well and implemente createHandle()
-
@lano1106
A little more elaborated version:class SplitterHandle : public QSplitterHandle { void mouseReleaseEvent(QMouseEvent *event) override { if(!rect().contains(event->localPos().toPoint())) return; int width2=splitter()->widget(1)->maximumWidth(); // 2nd panel max width int splitWidth=splitter()->width(); if(splitter()->widget(1)->width()==0) splitter()->setSizes({splitWidth-width2,width2}); else splitter()->setSizes({splitWidth,0}); } void paintEvent(QPaintEvent *) override { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); QFont font=this->font(); font.setBold(true); painter.setFont(font); if(splitter()->widget(1)->width()==0) { painter.drawText(rect(),Qt::AlignCenter,"<"); } else painter.drawText(rect(),Qt::AlignCenter,">"); } void mouseMoveEvent(QMouseEvent *) override { // block mouse move } void enterEvent(QEvent *) override { setCursor(Qt::ArrowCursor); } public: SplitterHandle(QSplitter* parent=nullptr) : QSplitterHandle(Qt::Horizontal, parent) {} };