Qt unresolved external symbol after refactoring - c++

I had a properly working Qt code with custom widget. Then I refractored a signal name and undo the action immediately. Since then I'm getting -
mainwindow.obj:-1: error: LNK2001: unresolved external symbol "protected: virtual void
__thiscall QWidget::mouseDoubleClicked(class QMouseEvent *)"
?mouseDoubleClicked#QWidget##MAEXPAVQMouseEvent###Z)
mouseDoubleClicked is the method which wmits the refractored signal. Although I undo the refractoring action but still it's giving this error. The same code did run bofe that.
I've tried cleaning and running qMake but no success. Even created a new project and copy pasted the file contents but still got the same error.
These are the files-
mainwindow.h
#pragma once;
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
myqtimagewidget.h
#pragma once
#include <QWidget>
#include <QImage>
#include <QPainter>
#include <QtGui/QMouseEvent>
#include "opencv2/opencv.hpp"
class MyQtImageWidget : public QWidget
{
Q_OBJECT
protected:
QImage qimage;
cv::Mat temp;
void paintEvent(QPaintEvent*);
void mouseDoubleClicked(QMouseEvent* event);
// void mousePressEvent(QMouseEvent *event);
public:
explicit MyQtImageWidget(QWidget *parent = 0) : QWidget(parent) {}
QSize sizeHint() const {return qimage.size(); }
QSize minimumSizeHint() const {return qimage.size(); }
signals:
void signalMouseMoved(QString);
public slots:
void showImage(const cv::Mat &image);
};
myqtimagewidget.cpp
#include "myqtimagewidget.h"
#include "opencv2/opencv.hpp"
using namespace cv;
void MyQtImageWidget::showImage(const Mat &image)
{
//resize image to fit widget. Maintains aspect ratio
int width = this->maximumWidth();
int hight = this->maximumHeight();
Mat rescaledImg;
if(image.cols > width || image.rows > hight)
{
// debug info --v
QString data = "Original dimention: " + QString::number(image.cols) + "x" + QString::number(image.rows);
qDebug(data.toStdString().c_str());
// debug info --^
double aspectRatio = (double)image.cols / (double)image.rows; // width / height
cv::Size2i newSize;
// debug info --v
qDebug(std::to_string(width).c_str());
qDebug(std::to_string(hight).c_str());
// debug info --^
if(image.cols >= image.rows)
{
newSize = cv::Size(width, width / aspectRatio);
}
else
{
newSize = cv::Size(hight * aspectRatio, hight);
}
cv::resize(image, rescaledImg, newSize, 1, 1);
// debug info --v
data = "Resized dimention: " + QString::number(rescaledImg.cols) + "x" + QString::number(rescaledImg.rows);
qDebug(data.toStdString().c_str());
// debug info --^
}
else
rescaledImg = image;
// Convert the image to the RGB888 format
switch (rescaledImg.type())
{
case CV_8UC1:
cvtColor(rescaledImg, temp, CV_GRAY2RGB);
break;
case CV_8UC3:
cvtColor(rescaledImg, temp, CV_BGR2RGB);
break;
}
// QImage needs the data to be stored continuously in memory
assert(temp.isContinuous());
// Assign OpenCV's image buffer to the QImage. Note that the bytesPerLine parameter
// (http://qt-project.org/doc/qt-4.8/qimage.html#QImage-6) is 3*width because each pixel
// has three bytes.
qimage = QImage(temp.data, temp.cols, temp.rows, temp.cols*3, QImage::Format_RGB888);
repaint();
}
void MyQtImageWidget::paintEvent(QPaintEvent *event)
{
// Display the image
QPainter painter(this);
painter.drawImage(QPoint(0,0), qimage);
painter.end();
}
void MyQtImageWidget::mouseDoubleClicked(QMouseEvent *event)
{
int x = event->pos().x(), y = event->pos().y();
QString data = "x: " + QString::number(x) + ", y: " + QString::number(y);
emit MyQtImageWidget::signalMouseMoved(data);
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "opencv2/opencv.hpp"
#include "myqtimagewidget.h"
using namespace cv;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QString imageSrc = "E:\\Images\\Panorama\\Harshil3578_stitch.jpg";
Mat image = imread(imageSrc.toStdString(), IMREAD_COLOR);
}
MainWindow::~MainWindow()
{
delete ui;
}
In the GUI I have a widget promoted to MyQtImageWidget and connected to a QLabel.

Consider what the linker is telling you:
QWidget has a virtual method named mouseDoubleClicked.
That method is not implemented.
The problem is that QWidget does not have a virtual method named mouseDoubleClicked. My best guess is that during your refactoring, you somehow modified the header file for QWidget, renaming an existing virtual function to mouseDoubleClicked.
If that's the case, getting a fresh copy of qwidget.h (or re-installing Qt) should resolve the problem.

Related

QGraphicsView doesn't respect heightForWidth() to maintain aspect ratio?

I created a small MVCE example to reproduce aspect ratio issue with an image on QGraphicsView.
Building on this i realized the image scaling calculates the aspect ratio correctly but every time i resize QGraphicsView it ignores my heightForWidth() value (which actually returns the right height).
ImageView.h
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QResizeEvent>
#include <QWidget>
#include <QImage>
#include <QPixmap>
class ImageView : public QGraphicsView
{
Q_OBJECT
public:
ImageView(QWidget* parent = nullptr);
void setImage(const QImage& image);
virtual int heightForWidth(int width) const override;
protected:
virtual void resizeEvent(QResizeEvent *event) override;
private:
QGraphicsScene* m_scene;
QImage m_image;
QPixmap m_pixImage;
int m_rows;
int m_cols;
};
ImageView.cpp
#include "imageview.h"
#include <QDebug>
ImageView::ImageView(QWidget *parent) :
QGraphicsView{parent},
m_scene{new QGraphicsScene{this}},
m_rows{0},
m_cols{0}
{
setScene(m_scene);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
QSizePolicy p(QSizePolicy::Minimum,QSizePolicy::Minimum);
p.setHeightForWidth(true);
setSizePolicy(p);
setFrameStyle(0);
setMouseTracking(true);
}
void ImageView::setImage(const QImage &image)
{
m_image = image;
m_cols = image.width();
m_rows = image.height();
m_pixImage = QPixmap::fromImage(image);
m_scene->addPixmap(m_pixImage);
fitInView(m_scene->itemsBoundingRect(),Qt::KeepAspectRatio);
}
/* virtual */ int ImageView::heightForWidth(int width) const
{
int height = (m_cols != 0) ? width * m_rows / m_cols : width;
qDebug() << "Height for width: " << height;
return height;
}
void ImageView::resizeEvent(QResizeEvent *event)
{
m_scene->clear();
qDebug() << "Graphics View: " << event->size();
QPixmap pxImg = m_pixImage.scaled(event->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
if(!pxImg.isNull())
{
qDebug() << "Image: " << pxImg.size();
qDebug() << "Graphics View: " << event->size();
m_scene->addPixmap(pxImg);
}
fitInView(m_scene->itemsBoundingRect(),Qt::KeepAspectRatio);
QGraphicsView::resizeEvent(event);
}
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:
Ui::MainWindow *ui;
};
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->graphicsView->setImage(QImage("656780.png"));
}
MainWindow::~MainWindow()
{
delete ui;
}
Output:
Height for width: 586 // ideal height for the width to maintain aspect ratio (width should be 781)
Graphics View: QSize(782, 544) // instead height is set to 544 (width should be 725)
Image: QSize(725, 544) // scaling the image to the resize event size with aspect ratio
// turns out 725 is right for a width of 544
Graphics View: QSize(782, 544) // same here
As a result of the output my image is never scaled to the exact size of the QGraphicsView on resizing.
How do i solve this? Is my calculation wrong? Or am i missing something?
Okay after struggling a lot i realized i need not scale the image manually in QGraphicsView. fitInView() actually does this automatically. To answer my question, KeepAspectRatioByExpanding is the answer.
void ImageView::resizeEvent(QResizeEvent *event)
{
fitInView(m_scene->itemsBoundingRect(),Qt::KeepAspectRatioByExpanding);
QGraphicsView::resizeEvent(event);
}
This scales the image along with the size of QGraphicsView. One must keep in mind to allow scrollbars to show up if the image is upscaled or shrinked below its original size.

Dynamically resizing two QLabel implementations

I'm trying to create a simple frame in Qt with a tick and some text. I made two new label implementations because I wanted the labels to dynamically fill all the available space but when I resize the window the sizes are off, as shown by the qDebug output, which represents the size of the image label:
Resized: 244 , 244 <-- Window first created
Resized: 305 , 305 <-- Window maximized
Resized: 135 , 135 <-- Window restored to original size
As you can see, when the window is restored to its original size the image is not. The last size should be 244, 244.
The code which describes the behaviour of the two widgets is the following:
"widgets.h":
/*
* This file includes many custom widgets.
*/
#ifndef APOCRYPHA_WIDGETS
#define APOCRYPHA_WIDGETS
#include <QWidget>
#include <QLabel>
#include <QTimer>
#include <QPixmap>
#include <QResizeEvent>
#include <QPaintEvent>
class AutoTextLabel : public QLabel {
Q_OBJECT
public:
explicit AutoTextLabel(QWidget* parent);
AutoTextLabel(QWidget* parent, QString text);
protected:
void resizeEvent(QResizeEvent* event) override;
private:
QTimer* resizeTimer;
private slots:
void onResizeEnd();
};
class AutoImageLabel : public QLabel {
Q_OBJECT
public:
explicit AutoImageLabel(QWidget* parent);
AutoImageLabel(QWidget* parent, const QPixmap& pixmap);
void setFillOrientation(int orientation);
QSize sizeHint() const override;
public slots:
void setPixmap(const QPixmap &newPix);
void resizeEvent(QResizeEvent* event) override;
protected:
// void paintEvent(QPaintEvent* event) override;
private:
int fillOrientation;
int widthForHeight(int h) const;
int heightForWidth(int w) const override;
QPixmap scaledPixmap() const;
QPixmap labelPixmap;
};
#endif //APOCRYPHA_WIDGETS
"widgets.cpp":
/*
* This file includes many custom widgets.
*/
#include "widgets.h"
#include <QPainter>
#include <QDebug>
AutoTextLabel::AutoTextLabel(QWidget *parent, QString text) : QLabel(text, parent){
// Enable antialiasing
QFont aaFont(font());
aaFont.setStyleStrategy(QFont::PreferAntialias);
setFont(aaFont);
// This timer is used to fire a slot when a window is resized
resizeTimer = new QTimer();
resizeTimer->setSingleShot(true);
connect(resizeTimer, SIGNAL(timeout()), SLOT(onResizeEnd()));
}
AutoTextLabel::AutoTextLabel(QWidget *parent) : AutoTextLabel(parent, "") {}
void AutoTextLabel::resizeEvent(QResizeEvent *event) {
QWidget::resizeEvent(event);
// Only fire when 25ms have passed since the last resize.
resizeTimer->start(25);
}
void AutoTextLabel::onResizeEnd() {
QFont updatedFont(font());
// Resize Text
if (!text().isEmpty()){
int fontSize = 1;
updatedFont.setPixelSize(fontSize);
QRect boundingRectangle;
// Update bounding rectangle
if (wordWrap())
boundingRectangle = QFontMetrics(updatedFont).boundingRect(contentsRect(), Qt::TextWordWrap, text());
else
boundingRectangle = QFontMetrics(updatedFont).boundingRect(text());
while (boundingRectangle.height() <= contentsRect().height()) {
fontSize++;
updatedFont.setPixelSize(fontSize);
// Update bounding rectangle
if (wordWrap())
boundingRectangle = QFontMetrics(updatedFont).boundingRect(contentsRect(), Qt::TextWordWrap, text());
else
boundingRectangle = QFontMetrics(updatedFont).boundingRect(text());
}
updatedFont.setPixelSize(fontSize - 1);
setFont(updatedFont);
}
}
/* Auto Image Label */
AutoImageLabel::AutoImageLabel(QWidget *parent, const QPixmap &pixmap) : QLabel(parent) {
setMinimumSize(1, 1);
setScaledContents(false);
setPixmap(pixmap);
}
AutoImageLabel::AutoImageLabel(QWidget *parent) : QLabel(parent) {
setScaledContents(false);
}
void AutoImageLabel::resizeEvent(QResizeEvent *event) {
QWidget::resizeEvent(event);
if(!labelPixmap.isNull())
QLabel::setPixmap(scaledPixmap());
qDebug() << "Resized: " << scaledPixmap().width() << ", " << scaledPixmap().height();
}
int AutoImageLabel::widthForHeight(int h) const {
return labelPixmap.isNull() ? width() : (labelPixmap.width() * h) / labelPixmap.height();
}
int AutoImageLabel::heightForWidth(int w) const {
return labelPixmap.isNull() ? height() : (labelPixmap.height() * w) / labelPixmap.width();
}
void AutoImageLabel::setFillOrientation(int orientation) {
this->fillOrientation = orientation;
}
QSize AutoImageLabel::sizeHint() const {
if (fillOrientation == Qt::Horizontal)
return QSize(width(), heightForWidth(width()));
else
return QSize(widthForHeight(height()), height());
}
QPixmap AutoImageLabel::scaledPixmap() const {
return labelPixmap.scaled(sizeHint(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
void AutoImageLabel::setPixmap(const QPixmap &newPix) {
labelPixmap = newPix;
QLabel::setPixmap(scaledPixmap());
}
"other_frames.h":
//
// Created by Riccardo on 18/09/2017.
//
#ifndef APOCRYPHA_OTHER_FRAMES_H
#define APOCRYPHA_OTHER_FRAMES_H
#include <QFrame>
#include <QLabel>
#include <QGridLayout>
#include <QWidget>
#include <QResizeEvent>
#include <QPixmap>
#include <QTimer>
#include "widgets.h"
class ConfirmationFrame : public QFrame {
Q_OBJECT
public:
explicit ConfirmationFrame(QWidget* parent);
ConfirmationFrame(QWidget* parent, const QString& text);
private:
QGridLayout* layout;
AutoImageLabel* imageLabel;
AutoTextLabel* textLabel;
};
#endif //APOCRYPHA_OTHER_FRAMES_H
"other_frames.cpp":
//
// Created by Riccardo on 18/09/2017.
//
#include "other_frames.h"
#include <QDebug>
ConfirmationFrame::ConfirmationFrame(QWidget* parent, const QString &text) : QFrame(parent) {
textLabel = new AutoTextLabel(this, text);
QPixmap pix(":/images/check-tick.png");
imageLabel = new AutoImageLabel(this, pix);
textLabel->setAlignment(Qt::AlignCenter);
imageLabel->setAlignment(Qt::AlignCenter);
textLabel->setWordWrap(true);
// Green Background
setStyleSheet("background-color: rgba(106, 242, 94, 1);");
layout = new QGridLayout();
layout->setSpacing(0);
layout->setContentsMargins(32, 32, 32, 32);
layout->setRowStretch(0, 1);
layout->setRowStretch(1, 1);
layout->addWidget(imageLabel, 0, 1);
layout->addWidget(textLabel, 1, 1);
setLayout(layout);
}
ConfirmationFrame::ConfirmationFrame(QWidget *parent) : ConfirmationFrame(parent, "") {
}
"window_main.h":
#ifndef WINDOW_MAIN_H
#define WINDOW_MAIN_H
#include <QMainWindow>
#include <QMenuBar>
#include <QMenu>
#include <QGridLayout>
#include <QFrame>
#include <QScreen>
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
QFrame *mainFrame;
void center(QScreen* screen);
void autoSetSize(QScreen* screen);
private:
void createMenu();
// Components
QGridLayout *mainLayout;
QMenuBar *menuBar;
QMenu *fileMenu;
};
#endif // WINDOW_MAIN
"window_main.cpp":
#include "window_main.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
mainFrame = new QFrame();
mainLayout = new QGridLayout();
mainLayout->setSpacing(0);
mainLayout->setContentsMargins(0, 0, 0, 0);
createMenu();
mainFrame->setStyleSheet("background-color: red;");
mainFrame->setLayout(mainLayout);
setCentralWidget(mainFrame);
}
void MainWindow::createMenu(){
menuBar = new QMenuBar;
fileMenu = new QMenu(tr("&File"), this);
menuBar->addMenu(fileMenu);
setMenuBar(menuBar);
}
void MainWindow::center(QScreen *screen) {
QSize size = screen->availableSize();
int x = size.width() / 2 - width() / 2;
int y = size.height() / 2 - height() / 2;
move(x, y);
}
void MainWindow::autoSetSize(QScreen *screen) {
QSize screenSize = screen->availableSize();
// TODO Math.round
setMinimumSize(QSize((int)(screenSize.width() / 1.25), (int)(screenSize.height() / 1.25)));
}
"main.cpp":
#include <QApplication>
#include <iostream>
#include <QFile>
#include "quiz/choice.h"
#include "quiz/question.h"
#include "quiz/quizmaker.h"
#include <QSettings>
#include <QStandardPaths>
#include <QDebug>
#include <src/user_interface/other_frames.h>
#include "user_interface/window_main.h"
#include <QScreen>
#include <QFontDatabase>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
// Set Application Parameters
QCoreApplication::setOrganizationName("Riccardo Fagiolo");
QCoreApplication::setOrganizationDomain("kopharex.me");
QCoreApplication::setApplicationName("Apocrypha");
// Set application font
const int id = QFontDatabase::addApplicationFont(":/fonts/montserrat/Montserrat-Regular.otf");
QString family = QFontDatabase::applicationFontFamilies(id).at(0);
QFont font(family);
font.setStyleStrategy(QFont::PreferAntialias);
a.setFont(font);
// App Settings
QSettings settings;
settings.setValue("data_dir", QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
// Create UI
auto* window = new MainWindow();
ConfirmationFrame* cframe = new ConfirmationFrame(window, "But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?");
window->mainFrame->layout()->addWidget(cframe);
window->autoSetSize(a.primaryScreen());
//cframe->updateTextLabel();
window->show();
window->center(a.primaryScreen());
// [...] - Nothing related to user interface.
return a.exec();
}
Here is a screenshot of the current MainWindow and ConfirmationFrame to give you an idea of what i'm trying to accomplish:
Window Screenshot
All comments regarding the code are welcome.
Thanks for any help,
Riccardo
Hello I tried to fix the resizing issue with an hack.
Before starting the timer to resize the text, just reduce its font to a 1 pixel font:
void AutoTextLabel::resizeEvent(QResizeEvent *event) {
QWidget::resizeEvent(event);
// set a very small font, then start the timer
QFont updatedFont(font());
updatedFont.setPixelSize(1);
setFont(updatedFont);
// Only fire when 25ms have passed since the last resize.
resizeTimer->start(25);
}
Can the effect be acceptable in your opinion?

How to start and stop usb camera streaming using openCV by clicking a button and paint it into a custom widget on Qt?

I'm quite new on qt. I'm trying to create a tab on my ui that can give the option to count how many usb cameras are connected to computer and list then using OPENCV. After that, I want to select one of then and start streaming a video into a custom widget, using paintEvent. My main difficulties are: how to start and stop a streaming when a button is pressed. Below i'm posting my code.
mainwindow.h
//includes...
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void on_CheckCamerasButton_clicked();
void on_StartStreamingButton_clicked();
private:
Ui::MainWindow *ui;
cameraimage camera;
};
#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);
}
MainWindow::~MainWindow(){
delete ui;
}
void MainWindow::on_StartStreamingButton_clicked(){
camera.startStreaming();
}
void MainWindow::on_CheckCamerasButton_clicked(){
camera.stopStreaming();
}
cameraimage.h
//includes...
class cameraimage : public QWidget
{
Q_OBJECT
public:
explicit cameraimage(QWidget *parent = nullptr);
private:
QPoint mPoint;
QTimer *timer;
cv::VideoCapture captureVideo;
public slots:
void paintEvent(QPaintEvent * event);
void startStreaming();
void stopStreaming();
};
#endif // CAMERAIMAGE_H
cameraimage.cpp
#include "cameraimage.h"
cameraimage::cameraimage(QWidget *parent) : QWidget(parent)
{
setMouseTracking(true);
}
void cameraimage::startStreaming(){
qDebug() << "Starting Streaming";
captureVideo.open(-1);
if (captureVideo.isOpened() == false){
qDebug() << "Camera can't open";
return;
}
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1);
}
void cameraimage::stopStreaming(){
captureVideo.release();
timer->stop();
}
void cameraimage::paintEvent(QPaintEvent *){
cv::Mat tmpImage;
cv::Mat image;
captureVideo.read(tmpImage);
if (tmpImage.empty() == true){
qDebug() << "EMPTY!";
return;
}
cv::cvtColor(tmpImage, image, CV_BGR2RGB);
QImage img((const unsigned char*)(image.data), image.cols, image.rows, QImage::Format_RGB888);
QPixmap pixmap = QPixmap::fromImage(img);
QPainter painter(this);
float comprimento = 1.0*width()/pixmap.width();
float altura = 1.0*height()/pixmap.height();
float ratio = 0.;
if (comprimento<=altura)
ratio = comprimento;
else
ratio = altura;
QSize size = ratio*pixmap.size();
size.setHeight(size.height()-10);
QPoint p;
p.setX(0 + (width()-size.width())/2);
p.setY(5);
painter.drawPixmap(QRect(p, size), pixmap.scaled(size, Qt::KeepAspectRatio));
}
I've got the following output after clicked on StartStreamingButton on MainWindow:
Starting Streaming...
EMPTY!
EMPTY!
EMPTY!
...
Can someone help me please?
Best regards :D

How can I use QtConcurrent::Run and QThread?

My code is about images. It can be open image, changing quality, resize, showing image size... For resize and change quaity, I use slider and when I change sliders values, image is read from buffer again and again. Because of this, freezing is happening in my program. So, to solve the problem I want to use QtConcurrent::run and QThread or QFuture. Actually I have no idea how can I use them and I would like to your help to solve my problem.
Here is my code. The functions are that to cause freezing:
void MainWindow::reprocess_image(int scale, int quality) {
rescale_image(scale);
requality_image(quality);
show_pixmap();
}
void MainWindow::rescale_image(int scale) {
int w = m_image->width();
int h = m_image->height();
int new_w = (w * scale)/100;
int new_h = (h * scale)/100;
ui->lbl_width->setText(QString::number(new_w));
ui->lbl_height->setText(QString::number(new_h));
m_pixmap = QPixmap::fromImage(
m_image->scaled(new_w, new_h, Qt::KeepAspectRatio, Qt::FastTransformation));
ui->lbl_scale->setText(QString::number(scale));
}
void MainWindow::requality_image(int quality) {
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
m_pixmap.save(&buffer, "WEBP", quality);
auto l_size_b = buffer.size();
double l_size_kb = buffer.size() / 1024.00;
ui->lbl_size->setText(QString::number(l_size_kb));
QImage image;
image.loadFromData(ba);
m_pixmap = QPixmap::fromImage(image);
ui->lbl_quality->setText(QString::number(quality));
double comp_p = 100.0 * l_size_b / m_orig_size;
if(comp_p>100) {
ui->lbl_compression->setText(QString::number(comp_p));
QLabel* m_label = ui->lbl_size;
m_label->setStyleSheet("QLabel { background-color : red; color : black; }");
}
else if(comp_p<=100) {
ui->lbl_compression->setText(QString::number(comp_p));
QLabel* m_label = ui->lbl_size;
m_label->setStyleSheet("QLabel { background-color : rgba(0,0,0,0%); color : black; }");
}
}
void MainWindow::on_sld_quality_valueChanged(int value) {
reprocess_image(ui->sld_scale->value(), value);
}
void MainWindow::on_sld_scale_valueChanged(int scale) {
reprocess_image(scale, ui->sld_quality->value());
}
And this is my mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsPixmapItem>
QT_FORWARD_DECLARE_CLASS(QGraphicsScene)
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
virtual void showEvent(QShowEvent *e) override;
private slots:
void on_openButton_clicked();
void on_sld_quality_valueChanged(int value);
void on_sld_scale_valueChanged(int value);
void on_saveButton_clicked();
private:
void reprocess_image(int scale, int quality);
void rescale_image(int);
void requality_image(int);
void show_pixmap();
void change_size();
Ui::MainWindow *ui;
QPixmap m_pixmap;
QImage *m_image;
qint64 m_orig_size;
QGraphicsScene *m_scene;
};
#endif // MAINWINDOW_H
How can I integrate QtConcurrent::run(), QThread and QFuture to my code?
The whole point of QtConcurrent::run is that you're not managing your own threads. So there's nothing to integrate. To get notified about when code submitted to QtConcurrent::run has finished you can use QFutureWatcher or emit a signal from the callable.

Widget background not transparent when using QGraphicsView but transparent when using QGridLayout

When I was using QGridLayout to display my widgets, only the widget was shown and the part of the image that was transparent was not shown. Now I switched to using QGraphicsScene and QGraphicsView, and now my images have a gray background wherever they used to be transparent.
void Piece::paintEvent(QPaintEvent *)
{
string image = ":/images/" + color + piece + ".png";
pixmap.load(image.c_str());
//pixmap.setMask(pixmap.createMaskFromColor(QColor(240, 240, 240)));
QPainter paint(this);
paint.drawPixmap(0, 0, pixmap);
}
That's how the image is displayed on my widget. When I used the code,
layout->addWidget(0,0,1,1);
the background is transparent. But when I use,
scene->addWidget(piece);
The widget has a gray background. How can I make it transparent? The full code can be found here if necessary (probably won't be necessary): https://github.com/gsingh93/Chess
EDIT: I can't figure this problem out at all... I tried using setAutoFillBackground(false); but that didn't work. So my last hope was converting my whole class from a QWidget to a QGrahhicsItem. That didn't work and the background of the image is still gray instead of transparent. If you can't figure out what's wrong with this code can someone please post or link me to an example of how to display an image with a transparent background using QGraphicsScene? Here is the original code, followed by the QGraphicsItem code, followed by my main function.
#include "headers/piece.h"
#include <QPainter>
#include <QMouseEvent>
#include <QBitmap>
#include <QCursor>
using namespace std;
Piece::Piece(string color, string piece, QWidget *parent) :
QWidget(parent)
{
this->piece = piece;
this->color = color;
this->setMaximumHeight(36);
this->setMaximumWidth(36);
x = 0;
y = 0;
setMouseTracking(false);
}
void Piece::paintEvent(QPaintEvent *)
{
string image = ":/images/" + color + piece + ".png";
pixmap.load(image.c_str());
//pixmap.setMask(pixmap.createMaskFromColor(QColor(240, 240, 240)));
QPainter paint(this);
paint.drawPixmap(0, 0, pixmap);
}
void Piece::setPosition(int file, int rank)
{
pixmap.load(":/images/whitepawn.png");
QImage image = pixmap.toImage();
x = (file-1)*50 + 18;// - image.width()/2;
y = (rank-1)*50 + 18;// - image.height()/2;
move(x, y);
}
void Piece::mouseMoveEvent(QMouseEvent *event)
{
if(event->buttons() == Qt::LeftButton)
{
x = event->globalX()-18;
y = event->globalY()-18;
move(x,y);
}
}
.
#include "piece2.h"
#include <QPainter>
#include <QMouseEvent>
#include <QBitmap>
#include <QCursor>
#include <QGraphicsSceneMouseEvent>
using namespace std;
Piece2::Piece2(string color, string piece, QObject *parent) :
QGraphicsItem()
{
this->piece = piece;
this->color = color;
//this->setMaximumHeight(36);
//this->setMaximumWidth(36);
x = 0;
y = 0;
//setMouseTracking(false);
}
void Piece2::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
string image = ":/images/" + color + piece + ".png";
pixmap.load(image.c_str());
//pixmap.setMask(pixmap.createMaskFromColor(QColor(240, 240, 240)));
//QPainter paint(this);
painter->drawPixmap(0, 0, pixmap);
}
void Piece2::setPosition(int file, int rank)
{
pixmap.load(":/images/whitepawn.png");
QImage image = pixmap.toImage();
x = (file-1)*50 + 18;// - image.width()/2;
y = (rank-1)*50 + 18;// - image.height()/2;
setPos(x, y);
}
void Piece2::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if(event->buttons() == Qt::LeftButton)
{
// x = event->globalX()-18;
// y = event->globalY()-18;
setPos(x,y);
}
}
.
#include <QtGui>
#include <QGraphicsScene>
#include <QGraphicsView>
#include "headers/board.h"
#include "headers/pawn.h"
#include "headers/knight.h"
#include "headers/bishop.h"
#include "headers/rook.h"
#include "headers/king.h"
#include "headers/queen.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QGraphicsScene *scene = new QGraphicsScene();
QGraphicsView *view = new QGraphicsView();
Board board;
scene->addWidget(&board);
scene->addWidget(board.pawn2);
board.pawn2->setPosition(1,1);
//view->viewport()->setPalette(QColor(Qt::transparent));
//view->viewport()->setAutoFillBackground(false);
view->setScene(scene);
//view->setBackgroundRole(QPalette::NoRole);
view->show();
return app.exec();
}
Did you try using a stylesheet to set the background transparency?
yourWidget->setStyleSheet("background-color: transparent;");
I confirm your problem. Additional, laurents solution can't work in Linux. But for me worked next action:
Before put your QWidget to QGraphicsScene by addWidget() method, set him next flag:
board->setAttribute( Qt::WA_TranslucentBackground );
Detailed explanation is here (ru): https://webhamster.ru/mytetrashare/index/mtb0/1625823664d5m6pmpy7s