Search code examples
c++qtqtwidgets

Implementing resize handles on QRubberband? Is QSizeGrip relevant?


I'd like to make my QRubberband instance user resizeable. I've seen this question here but there isn't a solution.

The use case is that the user can drag out a selection marquee over a photo and then make fine adjustments by dragging on the QRubberband margins to change geometry, or reposition existing geometry by dragging the selection. I have the repositioning implemented but I am wondering about resize handles for changing the geometry of the QRubberband.

Is it possible to use QSizeGrip here? Barring that, is there a standard way of checking for mouse-within-margin type events within Qt or some other way to implement this? This is for a research app that doesn't need or warrant lots of effort on this feature but it would be good to have.


Solution

  • Yes, it's possible. Here is the implementation:

    Header:

    class Resizable_rubber_band : public QWidget {
    public:
      Resizable_rubber_band(QWidget* parent = 0);
    
    private:
      QRubberBand* rubberband;
      void resizeEvent(QResizeEvent *);
    
    };
    

    Source:

    Resizable_rubber_band::Resizable_rubber_band(QWidget *parent) : QWidget(parent) {
      //tell QSizeGrip to resize this widget instead of top-level window
      setWindowFlags(Qt::SubWindow);
      QHBoxLayout* layout = new QHBoxLayout(this);
      layout->setContentsMargins(0, 0, 0, 0);
      QSizeGrip* grip1 = new QSizeGrip(this);
      QSizeGrip* grip2 = new QSizeGrip(this);
      layout->addWidget(grip1, 0, Qt::AlignLeft | Qt::AlignTop);
      layout->addWidget(grip2, 0, Qt::AlignRight | Qt::AlignBottom);
      rubberband = new QRubberBand(QRubberBand::Rectangle, this);
      rubberband->move(0, 0);
      rubberband->show();
      show();
    }
    
    void Resizable_rubber_band::resizeEvent(QResizeEvent *) {
      rubberband->resize(size());
    }
    

    Usage: (ui->label is the label used for displaying the image to be cropped)

    Resizable_rubber_band* band = new Resizable_rubber_band(ui->label);
    band->move(100, 100);
    band->resize(50, 50);
    band->setMinimumSize(30, 30);
    

    screenshot