简体   繁体   English

如何在QScrollArea上绘制选择矩形?

[英]How can I draw a selection rectangle on QScrollArea?

I have created an Image Viewer application that opens and saves an image and load the image on QLabel,then I created a ScrollArea to scroll for large images, in my second step I am trying to draw a selection rectangle to select a specific sub area , the steps I have taken to paint the selection rectangle as follows: 我创建了一个Image Viewer应用程序,该应用程序可打开并保存图像并将其加载到QLabel上,然后创建一个ScrollArea来滚动查看大图像,在第二步中,我试图绘制选择矩形以选择特定的子区域,我绘制选择矩形所采取的步骤如下:

1- I used an PaintEvent to paint the rectangle. 1-我用PaintEvent绘制矩形。 2- I used MouseEvent to select the sub area. 2-我使用MouseEvent选择子区域。

The problem is, when I run my code, I can draw the rectangle on the QWidget but not on the ScrollArea. 问题是,当我运行代码时,可以在QWidget上绘制矩形,但不能在ScrollArea上绘制矩形。

Here is my code: 这是我的代码:

in imageviewer.h 在imageviewer.h中

class ImageViewer : public QWidget{
Q_OBJECT
public:
   explicit ImageViewer(QWidget *parent = 0);
   ~ImageViewer();
private:
   Ui::ImageViewer *ui;

private slots:
  void on_openButton_pressed();

  void on_saveButton_pressed();

private:
  QPixmap image;
  QImage *imageObject;
  bool selectionStarted;
  QRect selectionRect;
  QMenu contextMenu;

protected:
  void paintEvent(QPaintEvent *e);
  void mousePressEvent(QMouseEvent *e);
  void mouseMoveEvent(QMouseEvent *e);
  void mouseReleaseEvent(QMouseEvent *e);
};

this is imageviewer.cpp 这是imageviewer.cpp

ImageViewer::ImageViewer(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ImageViewer)
{
    ui->setupUi(this);
    ui->scrollArea->setWidget(ui->imageLabel);
}

open & save functions: 打开和保存功能:

void ImageViewer::on_openButton_pressed()
{
    QString imagePath = QFileDialog::getOpenFileName(this, tr("Open File") , "" ,
                                                 tr("JPEG (*.jpg *.jpeg);;PNG (*.png);;BMP (*.bmp)"));

    imageObject = new QImage();
    imageObject->load(imagePath);

    image = QPixmap::fromImage(*imageObject);

    ui->imageLabel->setPixmap(image);
    ui->imageLabel->adjustSize();

}

void ImageViewer::on_saveButton_pressed()
{
    QString imagePath = QFileDialog::getSaveFileName(this, tr("Save File") , "" ,
                                                 tr("JPEG (*.jpg *.jpeg);;PNG (*.png);;BMP (*.bmp)"));

    *imageObject = image.toImage();
    imageObject->save(imagePath);
}

paint & mouse event functions: 绘画和鼠标事件功能:

void ImageViewer::paintEvent(QPaintEvent *e){
    QWidget::paintEvent(e);
    QPainter painter(this);
    painter.setPen(QPen(QBrush(QColor(0,0,0,180)),1,Qt::DashLine));
    painter.setBrush(QBrush(QColor(255,255,255,120)));
    painter.drawRect(selectionRect);
}

void ImageViewer::mousePressEvent(QMouseEvent *e){
    if(e->button() == Qt::RightButton){
        if(selectionRect.contains(e->pos()))
            contextMenu.exec(this->mapToGlobal(e->pos()));
    }
    else{
        selectionStarted = true;
        selectionRect.setTopLeft(e->pos());
        selectionRect.setBottomRight(e->pos());
    }
}

void ImageViewer::mouseMoveEvent(QMouseEvent *e){
    if(selectionStarted){
        selectionRect.setBottomRight(e->pos());
        repaint();
    }
}

void ImageViewer::mouseReleaseEvent(QMouseEvent *e){
    selectionStarted = false;
}

and this is a screenshot for my application 这是我的应用程序的屏幕截图

在此处输入图片说明

How can I draw a selection rectangle on QScrollArea? 如何在QScrollArea上绘制选择矩形?

You need QRubberBand which supposed to be directly applied to ui->imageLabel widget you use to display an image you want to scroll. 您需要QRubberBand ,它应该直接应用于ui->imageLabel小部件, ui->imageLabel小部件用于显示要滚动的图像。 Whether or not you should overload QLabel for ui->imageLabel is a question of implementation. 是否应为ui->imageLabel重载QLabel是实现的问题。 Please see the example for mouse events which, of course better be applied to your label image class. 请参见有关鼠标事件的示例 ,当然最好将其应用于标签图像类。

I understand from the way the code looks you used Qt Designer? 我从代码的外观上了解到您使用Qt Designer吗? That complicates overriding that label class but you can either not use .ui file or use event filter for trapping all the events for the given object. 这使覆盖该标签类变得复杂,但是您不能使用.ui文件或使用事件过滤器来捕获给定对象的所有事件。

What you currently have can be finally polished enough to be good for actual use, of course. 当然,您当前拥有的东西可以最终抛光到足以适合实际使用的程度。 It just makes much more effort for you. 这只会为您付出更多的努力。 You can avoid overloading paintEvent etc. and the key is to apply the right approach directly where it needs to be applied. 您可以避免paintEvent等重载,关键是在需要应用的地方直接应用正确的方法。

// the example applied to authors code as requested
class MyImageLabel : public QLabel
{
public:
   explicit MyImageLabel(QWidget *parent = 0) : QLabel(parent), rubberBand(0) {}
private:
   QRubberBand* rubberBand;
   QPoint origin;

   void mousePressEvent(QMouseEvent *event);
   void mouseMoveEvent(QMouseEvent *event);
   void mouseReleaseEvent(QMouseEvent *event)
};

void MyImageLabel::mousePressEvent(QMouseEvent *event)
{
    origin = event->pos();
    if (!rubberBand)
        rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
    rubberBand->setGeometry(QRect(origin, QSize()));
    rubberBand->show();
}

void MyImageLabel::mouseMoveEvent(QMouseEvent *event)
{
    rubberBand->setGeometry(QRect(origin, event->pos()).normalized());
}

void MyImageLabel::mouseReleaseEvent(QMouseEvent *event)
{
    rubberBand->hide();
    // determine selection, for example using QRect::intersects()
    // and QRect::contains().
}

ImageViewer::ImageViewer(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ImageViewer)
{
    ui->setupUi(this);
    // resolve this better than:
    delete ui->imageLabel; // you already have the QLabel object here?
    ui->imageLabel = new MyImageLabel;
    ui->scrollArea->setWidget(ui->imageLabel);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM