How to deal with the two overlapped widget?



  • I've defined two derived classed inherited from Widget, named ImageWidget and AnnoWidget respectively. ImageWidget is used for loading Image and AnnoWidget is used for drawing rectangles on the image. And I set both of the child objects of the the classes in the center of the mainwindow.

            image_widget = new ImageWidget();
    	setCentralWidget(image_widget);
    
    	anno_widget = new AnnoWidget();
    	setCentralWidget(anno_widget);
    

    So it is clear that the latter one will cover the first one that I can only draw rectangels but not load image.
    1.How can I change my code to load the image and draw rectangles on that?
    2.How can I save my new image with the rectangles on it?

    Wish you can help me with this!
    Here is my code.

    //annotation.h
    
    #ifndef ANNOTATION_H
    #define ANNOTATION_H
    
    #include <QtWidgets/QMainWindow>
    #include "ui_annotation.h"
    #include "imagewidget.h"
    #include "annowidget.h"
    
    class Annotation : public QMainWindow
    {
    	Q_OBJECT
    
    public:
    	Annotation(QWidget *parent = 0);
    	~Annotation();
    
    	void Init();
    
    private:
    	Ui::AnnotationClass ui;
    
    	QMenu *menu_file;
    	QToolBar *toolbar_open;
    	QToolBar *toolbar_save;
    	QToolBar *toolbar_delete;
    	QAction *action_open;
    	QAction *action_save;
    	QAction *action_save_annotation;
    	QAction *action_delete;
    
    	ImageWidget *image_widget;
    	AnnoWidget *anno_widget;
    
    };
    
    #endif // ANNOTATION_H
    
    
    //annotation.cpp
    
    #include "annotation.h"
    
    Annotation::Annotation(QWidget *parent)
    	: QMainWindow(parent)
    {
    	ui.setupUi(this);
    
    	Init();
    }
    
    Annotation::~Annotation()
    {
    
    }
    
    void Annotation::Init()
    {
    	menu_file = menuBar()->addMenu(tr("&File"));
    
    	action_open = new QAction(tr("Open"),this);
    	action_save = new QAction(tr("Save"),this);
    	action_save_annotation = new QAction(tr("Annotation"),this);
    	action_delete = new QAction(tr("Delete"),this);
    
    	toolbar_open = addToolBar(tr("Open"));
    	toolbar_save = addToolBar(tr("Save"));
    	toolbar_delete = addToolBar(tr("Delete"));
    	
    	menu_file->addAction(action_open);
    	menu_file->addAction(action_save);
    	menu_file->addAction(action_save_annotation);
    	toolbar_open->addAction(action_open);
    	toolbar_save->addAction(action_save);
    	toolbar_save->addSeparator();
    	toolbar_save->addAction(action_save_annotation);
    	toolbar_delete->addAction(action_delete);
    
    	image_widget = new ImageWidget();
    	setCentralWidget(image_widget);
    
    	anno_widget = new AnnoWidget();
    	setCentralWidget(anno_widget);
    
    	connect(action_open,&QAction::triggered,image_widget,&ImageWidget::Open);
    	connect(action_save,&QAction::triggered,image_widget,&ImageWidget::Save);
    	connect(action_delete,&QAction::triggered,anno_widget,&AnnoWidget::Delete);
    
    	
    }
    
    
    //imagewidget.h
    
    #ifndef IMAGEWIDGET_H
    #define IMAGEWIDGET_H
    
    #include <QWidget>
    #include <QImage>
    #include <vector>
    #include <QPainter>
    #include <QFileDialog>
    #include <QMouseEvent>
    #include "ui_imagewidget.h"
    #include "Rect.h"
    
    using namespace std;
    
    class ImageWidget : public QWidget
    {
    	Q_OBJECT
    
    public:
    	ImageWidget(QWidget *parent = 0);
    	~ImageWidget();
    
    public slots:
    	void Open();
    	void Save();
    	void SaveAnnotation();
    	void ReadXml();
    	void paintEvent(QPaintEvent *);
    //	void mousePressEvent(QMouseEvent *event);
    //	void mouseMoveEvent(QMouseEvent *event);
    //	void mouseReleaseEvent(QMouseEvent *event);
    
    private:
    	Ui::ImageWidget ui;
    
    //	bool draw_status;
    	QImage *ptr_image;
    //	vector<Rect*> rect_array;
    
    
    };
    
    #endif // IMAGEWIDGET_H
    
    
    //imagewidget.hpp
    
    #include "imagewidget.h"
    
    ImageWidget::ImageWidget(QWidget *parent)
    	: QWidget(parent)
    {
    	ui.setupUi(this);
    
    	ptr_image = new QImage();
    //	draw_status = false;
    }
    
    ImageWidget::~ImageWidget()
    {
    
    }
    
    void ImageWidget::Open()
    {
    	QString fileName = QFileDialog::getOpenFileName(this,tr("Read Image"),".",tr("Image(*.bmp *.png *.jpg)"));
    
    	if (!fileName.isEmpty())
    	{
    		ptr_image->load(fileName);
    	}
    
    	update();
    }
    
    void ImageWidget::Save()
    {
    	QString fileName = QFileDialog::getSaveFileName(this,tr("Save Image"),".",tr("Image(*.bpm *.png *.jpg)"));
    
    	if (!fileName.isEmpty())
    	{
    		ptr_image->save(fileName);
    	}
    }
    
    void ImageWidget::SaveAnnotation()
    {
    
    }
    
    void ImageWidget::ReadXml()
    {
    
    }
    /*
    void ImageWidget::mousePressEvent(QMouseEvent *event)
    {
    	if (Qt::LeftButton==event->button())
    	{
    		draw_status = true;
    		
    	}
    }
    */
    void ImageWidget::paintEvent(QPaintEvent *)
    {
    	QPainter painter(this);
    	QRect image_rect(0,0,ptr_image->width(),ptr_image->height());
    
    	painter.begin(this);
    	painter.drawImage(image_rect,*ptr_image);
    
    	update();
    
    }
    
    //annowidget.h
    
    #ifndef ANNOWIDGET_H
    #define ANNOWIDGET_H
    
    #include <QWidget>
    #include <vector>
    #include <QMouseEvent>
    #include "ui_annowidget.h"
    #include "Rect.h"
    
    using namespace std;
    
    class AnnoWidget : public QWidget
    {
    	Q_OBJECT
    
    public:
    	AnnoWidget(QWidget *parent = 0);
    	~AnnoWidget();
    
    	void mousePressEvent(QMouseEvent *event);
    	void mouseMoveEvent(QMouseEvent *event);
    	void mouseReleaseEvent(QMouseEvent *event);
    	void Delete();
    	void paintEvent(QPaintEvent *);
    
    private:
    	Ui::AnnoWidget ui;
    
    	QPoint m_Start;
    	QPoint m_End;
    	bool draw_status;
    	vector<Rect*> rect_array;
    };
    
    #endif // ANNOWIDGET_H
    
    //annowidget.cpp
    
    #include "annowidget.h"
    
    AnnoWidget::AnnoWidget(QWidget *parent)
    	: QWidget(parent)
    {
    	ui.setupUi(this);
    }
    
    AnnoWidget::~AnnoWidget()
    {
    	for (int i=0;i<rect_array.size();i++)
    	{
    		if (rect_array[i])
    		{
    			delete rect_array[i];
    			rect_array[i] = NULL;
    		}
    	}
    }
    
    void AnnoWidget::mousePressEvent(QMouseEvent *event)
    {
    	if (Qt::LeftButton==event->button())
    	{
    		draw_status = true;
    		m_Start = m_End = event->pos();
    	}
    }
    
    void AnnoWidget::mouseMoveEvent(QMouseEvent *event)
    {
    	if (draw_status)
    	{
    		m_End = event->pos();
    	}
    	
    }
    
    void AnnoWidget::mouseReleaseEvent(QMouseEvent *event)
    {
    	Rect *current_rect = NULL;
    	current_rect = new Rect(m_Start,m_End);
    	rect_array.push_back(current_rect);
    	draw_status = false;
    }
    
    void AnnoWidget::paintEvent(QPaintEvent *)
    {
    	QPen pen;
    	QPainter painter(this);
    	painter.begin(this);
    	pen.setWidth(5);
    	pen.setColor(Qt::red);
    	painter.setPen(pen);
    	
    	for (int i=0;i<rect_array.size();i++)
    	{
    		rect_array[i]->Draw(painter);
    	}
    
    	if (draw_status)
    	{
    		painter.drawRect(m_Start.rx(),m_Start.ry(),m_End.rx()-m_Start.rx(),m_End.ry()-m_Start.ry());
    	}
    
    	update();
    }
    
    void AnnoWidget::Delete()
    {
    	if (!rect_array.empty())
    	{
    		rect_array.pop_back();
    	}
    }
    

  • Lifetime Qt Champion

    Hi,

    Do you really need two widgets on top of each others ? Why not handle the painting of these rectangles in the same widget ?

    In any case, you should use QStackedLayout or QStackedWidget. They allow to have widgets on top of each others.



  • Thank you very much. I know that using only one widget would make things much easier. I'm just trying to do this to learn something new, beacause there are too many Qt classes that I've never confronted. Besides, I also think it more appropriate to place totally distinguished functions in different classes.


  • Moderators

    @Geng.Y Well, you can still have two different classes which use same underlying widget to draw image/rectangles.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.