如何在 QScrollArea 上绘制一个选择矩形?
How can I draw a selection rectangle on QScrollArea?
我创建了一个图像查看器应用程序,它可以打开和保存图像并将图像加载到 QLabel 上,然后我创建了一个 ScrollArea 来滚动大图像,在我的第二步中我试图绘制一个 selection矩形到select一个特定的子区域,我绘制selection矩形的步骤如下:
1- 我使用了 PaintEvent 来绘制矩形。
2- 我使用 MouseEvent select 子区域。
问题是,当我运行我的代码时,我可以在 QWidget 上绘制矩形,但不能在 ScrollArea 上绘制。
这是我的代码:
在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);
};
这是imageviewer.cpp
ImageViewer::ImageViewer(QWidget *parent) :
QWidget(parent),
ui(new Ui::ImageViewer)
{
ui->setupUi(this);
ui->scrollArea->setWidget(ui->imageLabel);
}
打开和保存功能:
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);
}
绘图和鼠标事件函数:
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;
}
这是我的应用程序的屏幕截图
How can I draw a selection rectangle on QScrollArea?
您需要 QRubberBand which supposed to be directly applied to ui->imageLabel
widget you use to display an image you want to scroll. Whether or not you should overload QLabel
for ui->imageLabel
is a question of implementation. Please see the example 鼠标事件,当然最好将其应用于您的标签图像 class。
我从代码的外观上了解到您使用了 Qt Designer?这使覆盖该标签 class 变得复杂,但您可以不使用 .ui 文件或使用 event filter 来捕获给定对象的所有事件。
当然,您目前拥有的东西最终可以打磨得足以满足实际使用。它只会让你付出更多的努力。您可以避免重载 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);
}
我创建了一个图像查看器应用程序,它可以打开和保存图像并将图像加载到 QLabel 上,然后我创建了一个 ScrollArea 来滚动大图像,在我的第二步中我试图绘制一个 selection矩形到select一个特定的子区域,我绘制selection矩形的步骤如下:
1- 我使用了 PaintEvent 来绘制矩形。 2- 我使用 MouseEvent select 子区域。
问题是,当我运行我的代码时,我可以在 QWidget 上绘制矩形,但不能在 ScrollArea 上绘制。
这是我的代码:
在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);
};
这是imageviewer.cpp
ImageViewer::ImageViewer(QWidget *parent) :
QWidget(parent),
ui(new Ui::ImageViewer)
{
ui->setupUi(this);
ui->scrollArea->setWidget(ui->imageLabel);
}
打开和保存功能:
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);
}
绘图和鼠标事件函数:
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;
}
这是我的应用程序的屏幕截图
How can I draw a selection rectangle on QScrollArea?
您需要 QRubberBand which supposed to be directly applied to ui->imageLabel
widget you use to display an image you want to scroll. Whether or not you should overload QLabel
for ui->imageLabel
is a question of implementation. Please see the example 鼠标事件,当然最好将其应用于您的标签图像 class。
我从代码的外观上了解到您使用了 Qt Designer?这使覆盖该标签 class 变得复杂,但您可以不使用 .ui 文件或使用 event filter 来捕获给定对象的所有事件。
当然,您目前拥有的东西最终可以打磨得足以满足实际使用。它只会让你付出更多的努力。您可以避免重载 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);
}