Image on Qt QMdiArea background - image

Qt developers!
Is there are way to add image on the background of my midArea like on picture below?
I know I can use something like this
QImage img("logo.jpg");
mdiArea->setBackground(img);
But I don't need any repeat of my image on the background.
Thank you!

As I said in my comment above, you can sub-class the QMdiArea, override its paintEvent() function and draw your logo image yourself (in the bottom right corner). Here is the sample code that implements the mentioned idea:
class MdiArea : public QMdiArea
{
public:
MdiArea(QWidget *parent = 0)
:
QMdiArea(parent),
m_pixmap("logo.jpg")
{}
protected:
void paintEvent(QPaintEvent *event)
{
QMdiArea::paintEvent(event);
QPainter painter(viewport());
// Calculate the logo position - the bottom right corner of the mdi area.
int x = width() - m_pixmap.width();
int y = height() - m_pixmap.height();
painter.drawPixmap(x, y, m_pixmap);
}
private:
// Store the logo image.
QPixmap m_pixmap;
};
And finally use the custom mdi area in the main window:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow mainWindow;
QMdiArea *mdiArea = new MdiArea(&mainWindow);
mainWindow.setCentralWidget(mdiArea);
mainWindow.show();
return app.exec();
}

Related

Convert an uploaded from desktop image to black and white in Qt

My program consists of two functions: first a user clicks a button (btn_image) to upload an image from desktop and it displays on the label (lbl_image). Secondly, I push another button (cnv_image) in order to change the colors of that uploaded image to black and white.
I have managed to implement the first function: the image chosen by a user successfully displays. However, I am confused how to convert that image to b&w. I wrote a function that is triggered after clicking the cnv_image button, but the problem is to refer to that uploaded image. So, when I click cnv_image buttom the uploaded image simply disappears.
I tried to use image.load (ui->lbl_image) to refer to the label which contains the image but it shows a mistake.
How can I implement my second function?
void MainWindow::on_btn_image_clicked()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Choose"), "", tr("Images (*.png *.jpg *jpeg)"));
if (QString::compare(fileName, QString()) != 0) {
QImage image;
bool valid = image.load(fileName);
if (valid) {
ui->lbl_image->setPixmap(QPixmap::fromImage(image));
}
}
}
void MainWindow::on_cnv_image_clicked()
{
QImage image;
image.load(ui->lbl_image);
QSize sizeImage = image.size();
int width = sizeImage.width(), height = sizeImage.height();
QRgb color;
for (int f1=0; f1<width; f1++) {
for (int f2=0; f2<height; f2++) {
int gray = qGray(color);
image.setPixel(f1, f2, qRgb(gray, gray, gray));
}
}
ui->lbl_image->setPixmap(QPixmap::fromImage(image));
}
I update your code, I add QImage image; as private member of MainWindow class so In mainwindow.h :
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui
{
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow: public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_btn_image_clicked();
void on_cnv_image_clicked();
private:
Ui::MainWindow *ui;
QImage image;
};
#endif // MAINWINDOW_H
and in on_cnv_image_clicked function
void MainWindow::on_cnv_image_clicked()
{
QSize sizeImage = image.size();
int width = sizeImage.width(), height = sizeImage.height();
QRgb color;
int value;
for (int f1 = 0; f1 < width; f1++)
{
for (int f2 = 0; f2 < height; f2++)
{
color = image.pixel(f1, f2);
int gray = (qRed(color) + qGreen(color) + qBlue(color)) / 3;
image.setPixel(f1, f2, qRgb(gray, gray, gray));
}
}
ui->lbl_image->setPixmap(QPixmap::fromImage(image));
ui->lbl_image->setScaledContents(true);
}
Result :
Welcome to Stackoverflow!
First of all, it's a good idea to keep a copy of the QImage in your class when you load it. It helps to avoid extra conversions from QPixmap to QImage in next steps. I'll skip it because it's out of the scope of your question.
You can use QImage::convertTo to convert the format of a QImage in place. It means that, it does not create a new QImage. As per documentation it may detach the QImage. You can read more about Implicit Sharing if you are interested.
So, the implementation should be something like:
void MainWindow::on_cnv_image_clicked()
{
QImage image = ui->lbl_image->pixmap().toImage();
image.convertTo(QImage::Format_Grayscale8);
ui->lbl_image->setPixmap(QPixmap::fromImage(image));
}
Take a look at the list of QImage::Formats to evaluate other grayscale/mono options.

Show grey level value of pixel in Qt when the mouse is over it

Currently I am working on the display of gray level image with zoom feature. I am able to get the position of the pixel and the zoom feature is working well. However I encountered two problems:
1.) How can I get the grey level value of the pixel that is pointed by the mouse? I only managed to obtain the rgb value through “QRgb rgbValue = pix.toImage().pixel(x,y)”. How can I convert it into grey level value? Or is there any direct way to get the grey level value of the pixel.
2.) I have implemented “mouseMoveEvent(QMouseEvent *event)” and “setMouseTracking(true)”. However the function of “mouseMoveEvent(QMouseEvent *event)” is not functioning when I move the mouse. What is wrong with my code?
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsScene>
#include <QGraphicsItem>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
protected:
void mouseMoveEvent(QMouseEvent * event);
private:
Ui::MainWindow *ui;
QGraphicsScene* scene;
QGraphicsItem* item;
QPixmap pix;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QImage image("E:/image_00002.bmp");
pix = QPixmap::fromImage(image);
scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);
scene->addPixmap(pix);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
ui->graphicsView->setMouseTracking(true);
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
QPoint local_pt = ui->graphicsView->mapFromGlobal(event->globalPos());
QPointF img_coord_pt = ui->graphicsView->mapToScene(local_pt);
double x = img_coord_pt.x();
double y = img_coord_pt.y();
/* How can I get a gray level image here */
QRgb rgbValue = pix.toImage().pixel(x,y);
ui->label_X->setText(QString::number(x));
ui->label_Y->setText(QString::number(y));
ui->label_Value->setText(QString::number(rgbValue));
}
To elaborate a bit on what hank said. In order for your QMainWindow to receive the events from the QGraphicsScene you need to install an event filter (see http://qt-project.org/doc/qt-4.8/qobject.html#installEventFilter ). Quoting from the DOCs:
An event filter is an object that receives all events that are sent to this object.
The filter can either stop the event or forward it to this object.
In order to process the events you need to define an eventFilter method in your main window class. Below are the on_pushButton_clicked() and eventFilter() methods that should do what you want:
void MainWindow::on_pushButton_clicked()
{
ui->graphicsView->setMouseTracking(true);
scene->installEventFilter(this);
}
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::GraphicsSceneMouseMove ) {
QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent*>(event);
QPointF img_coord_pt = mouseEvent->scenePos();
double x = img_coord_pt.x();
double y = img_coord_pt.y();
QColor color = QColor(pix.toImage().pixel(x,y));
int average = (color.red()+color.green()+color.blue())/3;
ui->label_X->setText(QString::number(x));
ui->label_Y->setText(QString::number(y));
ui->label_Value->setText(QString::number(average));
return true;
} else {
return QObject::eventFilter(obj, event);
}
}
Does this help?

drawing a point over an image on QLabel

I displayed a picture on QLabel and wanted to take coordinates and paint a point on image on mouse click event. I am able to get coordinates but painter is painting point below my image on label, i want it above my image.
My code is :
main.cpp
#include "imageviewer.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
imageviewer w;
w.showMaximized();
return a.exec();
}
imageviewer.h
#include <QPushButton>
class imageviewer : public QLabel
{
Q_OBJECT
public:
explicit imageviewer(QWidget *parent = 0);
private slots:
void mousePressEvent(QMouseEvent * e);
void paintEvent(QPaintEvent * e);
private:
QLabel *label1 ;
int mFirstX;
int mFirstY;
bool mFirstClick;
bool mpaintflag;
};
#endif
imageviewer.cpp
#include <QtGui>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include "imageviewer.h"
#include <QDebug>
imageviewer::imageviewer(QWidget *parent)
: QLabel(parent)
{
label1 = new QLabel;
label1->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
QPixmap pm1("/home/nishu/Pictures/img_0002.jpg");
label1->setPixmap(pm1);
label1->adjustSize();
label1->setScaledContents(true);
QHBoxLayout *hlayout1 = new QHBoxLayout;
hlayout1->addWidget(label1);
setLayout(hlayout1);
}
void imageviewer :: mousePressEvent(QMouseEvent *e)
{
mFirstX=0;
mFirstY=0;
mFirstClick=true;
mpaintflag=false;
if(e->button() == Qt::LeftButton)
{
//store 1st point
if(mFirstClick)
{
mFirstX = e->x();
mFirstY = e->y();
mFirstClick = false;
mpaintflag = true;
qDebug() << "First image's coordinates" << mFirstX << "," << mFirstY ;
update();
}
}
}
void imageviewer :: paintEvent(QPaintEvent * e)
{
QLabel::paintEvent(e);
if(mpaintflag)
{
QPainter painter(this);
QPen paintpen(Qt::red);
paintpen.setWidth(10);
QPoint p1;
p1.setX(mFirstX);
p1.setY(mFirstY);
painter.setPen(paintpen);
painter.drawPoint(p1);
}
}
Help me to sort out what exactly problem is?
with line QPainter painter(this); you set QPainter to draw on your main widget instead of QLabel's pixmap. Change block to this and it will work:
if(mpaintflag)
{
QImage tmp(label1->pixmap()->toImage());
QPainter painter(&tmp);
QPen paintpen(Qt::red);
paintpen.setWidth(10);
QPoint p1;
p1.setX(mFirstX);
p1.setY(mFirstY);
painter.setPen(paintpen);
painter.drawPoint(p1);
label1->setPixmap(QPixmap::fromImage(tmp));
}
EDIT:
Just noticed, that you derived from QLabel, not from QWidget, as i assumed automatically, looking at layout. Indeed, you don't need label1 and layout inside of our imageviewer class. That whole point of subclassing is that you implement behavior and filter events the way you want it and then you add them to main widget if that is needed
EDIT2:
Imageviewer class should be derived from QLabel, remove label1 and layout, and paint not on image, but on imageviewer itself, i.e. this. Then you need to add new class to your program, which is derived from QMainwindow or QWidget for example, where you should include your imageviewer class, create layout and add your class to it like this:
#include "imageviewer.h"
//.... somewhere in constructor ....
imageviewer *viewer1=new imageviewer(this); // creating new object of imageviewer
viewer1->setPixmap(...);
hlayout1->addWidget(viewer1);
You derived your class from QLabel, so you should not create another QLabel *label1 and put it inside label's layout. That doesn't make any sense. Why would anyone put a label into a label? You need to remove label1 and use the imageviewer object as a label instead. Your constructor should contain only the following code:
setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
QPixmap pm1(...);
setPixmap(pm1);
adjustSize();
setScaledContents(true);
I've checked that it fixes your problem.

Detect click on Gtk::Image?

I've been trying to detect click on a Gtk::Image with gtkmm for over 2 hours, but I couldn't get it to work. It does compile and execute fine, but the event is never triggered.
Some stuff I tried, that compiles, does not crash, but doesn't work:
m_image = manage(new Gtk::Image(Gtk::Stock::APPLY, Gtk::ICON_SIZE_BUTTON));
m_image->add_events(Gdk::ALL_EVENTS_MASK);
m_hbox->pack_start(*m_image, Gtk::PACK_SHRINK);
m_image->signal_button_release_event()
.connect(sigc::hide(sigc::mem_fun(*this, &Todo::switchStatus)));
m_image->show();
or
#include <gtkmm/main.h>
#include <gtkmm/window.h>
#include <gtkmm/button.h>
#include <gtkmm/stock.h>
#include <gtkmm/image.h>
#include <iostream>
using namespace std;
class Win : public Gtk::Window
{
public:
Win();
bool link(GdkEventButton* e);
private:
Gtk::Image image;
};
Win::Win()
: image(Gtk::Stock::APPLY, Gtk::ICON_SIZE_BUTTON)
{
cerr << "created" << endl;
image.add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
image.signal_button_release_event().connect(sigc::mem_fun(*this, &Win::link));
image.show();
add(image);
}
bool Win::link(GdkEventButton* e)
{
cerr << "kuh" << endl;
}
int main(int argc, char *argv[])
{
Gtk::Main app(argc, argv);
Gtk::Window window;
window.resize(300, 500);
Win win;
Gtk::Main::run(win);
return 0;
}
From http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Image.html:
Gtk::Image is a "no window" widget (has no Gdk::Window of its own), so by default does not receive events. If you want to receive events on the image, such as button clicks, place the image inside a Gtk::EventBox, then connect to the event signals on the event box
So I guess try to put a signal on an eventbox after wrapping the image with the EventBox.
I like to put a button overtop of the image with an opacity of 0. Then you can use the click event from it instead.
This thread is quite old but still popular. I came across the same problem and I coded this code, maybe it can help someone save tim. My code detects the click ONLY if the pointer is hovering the image.
#include <gtk/gtk.h>
//compile with cc `pkg-config --cflags gtk+-3.0` text.c `pkg-config --libs gtk+-3.0` -o text
static void click_callback(GtkWidget *widget, GdkEventButton *event, gpointer );
static gboolean inRange(gint value, gint min, gint max);
static gboolean pointInRect(gint mouseX, gint mouseY, gint wx, gint wy, gint width, gint height);
GtkWidget *image;
GtkWidget *image2;
int main (int argc, char *argv[])
{
GtkWidget *event_box;
GtkWidget *window;
GtkWidget *box;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
/* GTK_ALIGN_CENTER is necessary otherwise
* the callback triggers from the space on
* the top and the bottom of the image */
gtk_widget_set_valign(box, GTK_ALIGN_CENTER);
image = gtk_image_new_from_file("image1.png");
image2 = gtk_image_new_from_file("image2.png");
gtk_box_pack_start(GTK_BOX(box), image, TRUE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(box), image2, TRUE, FALSE, 0);
event_box = gtk_event_box_new ();
gtk_container_add (GTK_CONTAINER (event_box), box);
gtk_container_add (GTK_CONTAINER (window), event_box);
g_signal_connect(window, "destroy",
G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect( event_box, "button_press_event", G_CALLBACK( click_callback ), image);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_title(GTK_WINDOW(window), "Image click event");
gtk_widget_show_all(window);
gtk_main();
return 0;
}
static void click_callback(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
GtkAllocation alloc;
GtkAllocation alloc2;
gtk_widget_get_allocation(image, &alloc);
gtk_widget_get_allocation(image2, &alloc2);
if (pointInRect(event->x, event->y, alloc.x, alloc.y, alloc.width, alloc.height))
g_print("You clicked from image\n");
if (pointInRect(event->x, event->y, alloc2.x, alloc2.y, alloc2.width, alloc2.height))
g_print("You clicked from image2\n");
}
static gboolean pointInRect(gint mouseX, gint mouseY, gint wx, gint wy, gint width, gint height)
{
return inRange(mouseX, wx, wx + width) &&
inRange(mouseY, wy, wy + height);
}
static gboolean inRange(gint value, gint min, gint max)
{
return (value >= min && value <= max);
}

Qt jpg image display

I want to display .jpg image in an Qt UI. I checked it online and found https://doc.qt.io/archives/qt-4.8/qt-widgets-imageviewer-example.html. I thought Graphics View will do the same, and also it has codec to display video. How to display images using Graphics View? I went through the libraries, but because I am a totally newbie in Qt, I can't find a clue to start with. Can you direct me to some resources/examples on how to load and display images in Qt?
Thanks.
You could attach the image (as a pixmap) to a label then add that to your layout...
...
QPixmap image("blah.jpg");
QLabel *imageLabel = new QLabel();
imageLabel->setPixmap(image);
mainLayout.addWidget(imageLabel);
...
Apologies, this is using Jambi (Qt for Java) so the syntax is different, but the theory is the same.
#include ...
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene scene;
QGraphicsView view(&scene);
QGraphicsPixmapItem item(QPixmap("c:\\test.png"));
scene.addItem(&item);
view.show();
return a.exec();
}
This should work. :) List of supported formats can be found here
If the only thing you want to do is drop in an image onto a widget withouth the complexity of the graphics API, you can also just create a new QWidget and set the background with StyleSheets. Something like this:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
...
QWidget *pic = new QWidget(this);
pic->setStyleSheet("background-image: url(test.png)");
pic->setGeometry(QRect(50,50,128,128));
...
}
Add Label (a QLabel) to the dialog where you want to show the image. This QLabel will actually display the image. Resize it to the size you want the image to appear.
Add the image to your resources in your project.
Now go into QLabel properties and select the image you added to resources for pixmap property. Make sure to check the next property scaledContents to shrink the image in the size you want to see it.
That's all, the image will now show up.
I want to display .jpg image in an Qt UI
The simpliest way is to use QLabel for this:
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QLabel label("<img src='image.jpg' />");
label.show();
return a.exec();
}
I understand your frustration the " Graphics view widget" is not the best way to do this, yes it can be done, but it's almost exactly the same as using a label ( for what you want any way) now all the ways listed do work but...
For you and any one else that may come across this question he easiest way to do it ( what you're asking any way ) is this.
QPixmap pix("Path\\path\\entername.jpeg");
ui->label->setPixmap(pix);
}
Using QPainter and QImage to paint on a window-widget (QMainWindow) (just another method)
class MainWindow : public QMainWindow
{
public:
MainWindow();
protected:
void paintEvent(QPaintEvent* event) override;
protected:
QImage image = QImage("/path/to/image.jpg");
};
// for convenience resize window to image size
MainWindow::MainWindow()
{
setMinimumSize(image.size());
}
void MainWindow::paintEvent(QPaintEvent* event)
{
QPainter painter(this);
QRect rect = event->rect();
painter.drawImage(rect, image, rect);
}
int main(int argc, char** argv)
{
QApplication a(argc, argv);
MainWindow mainWindow;
mainWindow.show();
return a.exec();
}

Resources