QWidget pos() not updated during resizes involving origin - macos

I am desperately failing at the supposedly simple problem to obtain the position and geometry of a Qt window on the screen. I originally stumbled upon this problem in a Python/PyQt context, but have since tracked it to Qt itself, where the QWidget::pos() property is not updated when the user resizes the window using any of the top or left edges or corners, i.e., resizes that involve the origin at the top left corner, hence the position of the window.
The following Qt/C++ program is the minimum to reproduce the problem (name as Qt_test.cc and build with qmake -project Qt_test.cc; qmake; make):
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QDebug>
class PrintingQWidget : public QWidget {
Q_OBJECT
public slots:
void print() {
qDebug() << pos() << width() << height();
}
};
#include "Qt_test.moc"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
PrintingQWidget window;
QPushButton btn("Print position", &window);
window.connect(&btn, SIGNAL(clicked()), SLOT(print()));
window.show();
return app.exec();
}
Click on "Print position" to obtain the coordinates of the window, then resize the window using the top or left edges, and click again. On my system (MacOSX), the window position in the QWidget::pos() property was not updated. I clearly understand from the documentation that QWidget::pos() should always yield the coordinates of the top-left corner of the widget, which is not the case.
Anyone able to reproduce this problem? Any workarounds?

OK, it appears that this is actually a bug in Qt 4.8. My example program, as well as Merlin069's version, behave perfectly fine with Qt 5. Both Qt 4.8.2 and Qt 4.8.4 are affected by the bug. (For Qt 4.8.4, I tested both the homebrew and dmg installations, which both behave incorrectly). My test system was MacOSX 10.7.5.
Maybe some of you with different systems/Qt versions can still run the test program and report back, so that I can file a better bug report?

Looking closer at your code, you should not be including the moc file. Anyhow, I decided to code this myself and I get the correct, expected coordinates in screen space. Here's the code: -
Header (widget.h)
#include <QWidget>
#include <QDebug>
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(QWidget* parent = NULL)
: QWidget(parent)
{
}
virtual ~MyWidget()
{
}
public slots:
void PrintPos() const
{
qDebug() << pos() << width() << height();
}
};
Main.cpp
#include "widget.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyWidget debugWidget(NULL);
QPushButton btn("print position", &debugWidget);
QObject::connect(&btn, &QPushButton::released, &debugWidget, &MyWidget::PrintPos);
debugWidget.show();
return app.exec();
}

Related

Simplifying a Qt program and I am having trouble displaying an image in Qt using QGraphicsScene

Both of these code segments load in an image. Code 1, loads an image and has a zoom function and Code 2 is supposed to only load an image. Code 1 works perfectly, but when I tried to simplify it, I lost the load image functionality. For some reason the image is being destroyed before it is made visible.
It seems like it should be fairly straight forward but I can't seem to fix it.
Code 1: (this works but seems overly complicated)
#include <QtGlobal>
#if QT_VERSION >= 0x050000
#include <QtWidgets>
#else
#include <QtGui>
#endif
int main(int argc,char* argv[])
{
QApplication app(argc,argv);
QImage image(":/images/2.png");
QGraphicsScene* scene = new QGraphicsScene();
QGraphicsView* view = new QGraphicsView(scene);
QGraphicsPixmapItem* item = new QGraphicsPixmapItem(QPixmap::fromImage(image));
scene->setBackgroundBrush(QPixmap(":/images/2.png"));
scene->setBackgroundBrush(image.scaled(100,100,Qt::IgnoreAspectRatio,Qt::SmoothTransformation));
QGraphicsPixmapItem* pi = scene->addPixmap(QPixmap::fromImage(image).scaledToWidth(50));
QGraphicsEllipseItem *item2 = new QGraphicsEllipseItem( 0, &scene );
item2->setRect( -50.0, -50.0, 50, 100.0 );
scene->addItem(item2);
view->show();
return app.exec();
}
Code 2: (this is the simplified version but it is broken)
#include <QtGlobal>
#if QT_VERSION >= 0x050000
#include <QtWidgets>
#else
#include <QtGui>
#endif
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QImage myImage;
myImage.load("2.png");
QGraphicsScene* scene = new QGraphicsScene();
QGraphicsView* view = new QGraphicsView(scene);
QGraphicsPixmapItem* item = new QGraphicsPixmapItem(QPixmap::fromImage(myImage));
scene->addItem(item);
view->show();
return app.exec();
}
Do you want to load the same image in both versions of the code?
If yes, you should as well use the same path to this image.
In the first version of your code you use ":/images/2.png" as your image source. This is a path pointing to a file in the Qt Resource System. You probably have a .qrc file in your project containing your desired image file.
You should use the same path in the second version and have the same .qrc file compiled into the project.

Image on Qt QMdiArea background

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();
}

zoom the Image Element in QML. without using QImage::scaled(), QPixmap::scaled().

I am trying to implement zoom in / out of a image using Image Element in QML.
I want the Pixel scale to be modified if i double click / pinch zoom.
How can i implement this without using QImage::scaled(), QPixmap::scaled().
Basically i dont want to involve Qt logic into my application.
I want Similar effect to hat is happening in the following tutorial
http://harmattan-dev.nokia.com/docs/library/html/qt4/widgets-imageviewer.html
But without Qt Logic in the app.
i know it's not the best answer but i cannot write a comment (i got less then 50 reps...) but zooming in/out qml is easy using PinchArea if you add a MouseArea you can also use onClicked or onDoubleClicked.... there is a useful example for pinch to zoom here(qt.git).
The ImageViewer example you posted got features like print save and so on, and you don't want to use "qt Logic", so i think you will need to use "qt Logic". I would wirte one class for each feature and implement it where i need it.
first of all i think this could help you(Extending QML Functionalities using C++).
Here a (not tested) example for saveing and reading a file:
fileio.h
#ifndef FILEIO_H
#define FILEIO_H
#include <QObject>
#include <QVariant>
class FileIO : public QObject
{
Q_OBJECT
public:
Q_PROPERTY(QString source
READ source
WRITE setSource
NOTIFY sourceChanged)
explicit FileIO(QObject *parent = 0);
Q_INVOKABLE QString source();
Q_INVOKABLE QVariant read();
Q_INVOKABLE bool write(const QVariant& data);
public slots:
void setSource(const QString& source) ;
signals:
void sourceChanged(const QString& source);
void error(const QString& msg);
private:
QString mSource;
};
#endif // FILEIO_H
and fileio.cpp
#include "fileio.h"
#include <QFile>
#include <QDataStream>
#include <QString>
#include <QDebug>
FileIO::FileIO(QObject *parent) :
QObject(parent){
}
QString FileIO::source(){
return mSource;
}
QVariant FileIO::read()
{
if (mSource.isEmpty()){
emit error("source is empty");
return QVariant();
}
QFile file(mSource);
QVariant fileContent; // i dont know if you can use QImage but i think you cann't
if ( file.open(QIODevice::ReadOnly) ) {
QDataStream t( &file );
fileContent << t //you may have to reimplement "<<" operator
file.close();
} else {
emit error("Unable to open the file");
return QVariant();
}
return fileContent;
}.....
and register that in main.cpp like
qmlRegisterType<FileIO, 1>("FileIO", 1, 0, "FileIO");
so you can import it in your qml like
import FileIO 1.0
Rectangle{
id: someId
...
FileIO{
id: yourAccessToYourFileIOclass
}
}
i've not tested that code yet, i hope it helps.
for better answers post what you want to do exacly save, print , any filters....
p.s. I also would create a model in qt and bring it to qml...
greez Matthias

Displaying translucent / irregular-shaped windows with Qt

Is it possible to display translucent and/or irregular-shaped windows with Qt?
(I'm assuming it ultimately depends on the capabilities of the underlying GUI system, but let's assume at least Windows XP / Mac OS X)
If so, how does one accomplish this?
Yes, it is possible. The key is the Qt::WA_TranslucentBackground attribute of QWidget
Here is a simple class that draws a round translucent window with a red background 50% alpha.
TranslucentRoundWindow.h:
#include <QWidget>
class TranslucentRoundWindow : public QWidget
{
public:
TranslucentRoundWindow(QWidget *parent = 0);
virtual QSize sizeHint() const;
protected:
virtual void paintEvent(QPaintEvent *paintEvent);
};
TranslucentRoundWindow.cpp:
#include <QtGui>
#include "TranslucentRoundWindow.h"
TranslucentRoundWindow::TranslucentRoundWindow(QWidget *parent) : QWidget(parent, Qt::FramelessWindowHint)
{
setAttribute(Qt::WA_TranslucentBackground);
}
QSize TranslucentRoundWindow::sizeHint() const
{
return QSize(300, 300);
}
void TranslucentRoundWindow::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(Qt::NoPen);
painter.setBrush(QColor(255, 0, 0, 127));
painter.drawEllipse(0, 0, width(), height());
}
If you want to be able to move this window with the mouse, you will have to override mousePressEvent, mouseMoveEvent and mouseReleaseEvent.
It certainly is possible. Qt ships with the "Shaped Clock" demonstration. The documentation of which is here.
It creates a top-level window with an odd shape. Should be all you need.

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