1 Attachment(s)
How to insert a drawing in QWidget in Qt Designer form ?
I created a dialog in Qt Designer di Qt 6.5 per Windows 10 in which I put a QWidget that will contain a drawing made with QPainter in my application code. What should I write in the paintEvent(QPaintEvent* event) where the drawing is created and that I want to insert in the QWidget of the Qt Designer form ?
To better understand what I'm saying, I attach a screenshot of what I have now: a red led drawn with QPainter in the ::paintEvent(QPaintEvent* event) code of my application and a check box inserted by Qt Designer.
Here instead the paintEvent method in which I draw the led:
Code:
{
Q_UNUSED(event);
QRect geo
= ui.
widgetLed->geometry
();
int width = geo.width();
int height = geo.height();
int x = 0, y = 0;
if (alignment_ & Qt::AlignLeft)
x = 0;
else if (alignment_ & Qt::AlignRight)
x = width - diamX_;
else if (alignment_ & Qt::AlignHCenter)
x = (width - diamX_) / 2;
else if (alignment_ & Qt::AlignJustify)
x = 0;
if (alignment_ & Qt::AlignTop)
y = 0;
else if (alignment_ & Qt::AlignBottom)
y = height - diamY_;
else if (alignment_ & Qt::AlignVCenter)
y = (height - diamY_) / 2;
diamX_ * 0.4, diamY_ * 0.4);
g.setColorAt(0, Qt::white);
if (state_)
g.setColorAt(1, color_);
else
g.setColorAt(1, Qt::black);
p.setPen(color_);
p.
setRenderHint(QPainter::Antialiasing,
true);
p.setBrush(brush);
p.drawEllipse(x, y, diamX_ - 1, diamY_ - 1);
if (flashRate_ > 0 && flashing_)
timer_->start(flashRate_);
else
timer_->stop();
}
All this to be able to see the check box and the led side by side and not as in the figure I have attached.
Re: How to insert a drawing in QWidget in Qt Designer form ?
If you want to insert a picture of an LED, then do this:
- In Qt Designer, you insert a QLabel widget where you want to draw the LED. If you want the label to look like an LED in Designer, then you can create a pixmap (see below) and set that as the "pixmap" property for the QLabel. It is just a picture, you can't change any of the "LED" properties unless you use different pixmaps to simulate the appearance.
- In your application, you draw the LED into a QPixmap of the right size, then call QLabel::setPixmap().
- Based on your current code for your LED widget, replace the paintEvent() or add this new method to create the pixmap instead of painting to the screen. (If you keep the paintEvent(), this will allow you to use the widget either as a QWidget or to create a pixmap for a QLabel).
Code:
{
painter.
setRenderHint(QPainter::Antialiasing,
true);
QString ledShapeAndColor
= shapes
[m_shape
];
if (m_value)
ledShapeAndColor.append(colors[m_onColor]);
else
ledShapeAndColor.append(colors[m_offColor]);
renderer.load(ledShapeAndColor);
renderer.render(&painter);
return pixmap;
}
Code:
// In your application:
QSize size
= myLabel
->size
();
using LED = Led_6_0_1;
LED led; // Temporary - this is not a widget to appear on screen. It is used simply for drawing the pixmap.
// Set shape and colors for led
led.setShape( LED::Circle );
led.setOnColor( LED::Red );
led.setOffColor( LED::Grey );
// Create the pixmap and install it
QPixmap pixmap
= led.
createPixmap( size
);
myLabel->setPixmap( pixmap );
If you want to change LED colors or shape in response to user input, then you need to change the pixmap by running this code again with the new properties and setting the pixmap again.
Another option would be to use Qt Designer to insert a QLabel at any place you want an LED, then using the Designer's "Promote to" feature to change the QLabel to an LED. I do not know if this will let you change properties in Qt Designer, but at least your LED will be accessible in your application as an Led_6_0_1 instance and you can change the properties at run time for your app instead of having to create a new pixmap for every change.
It would really be much easier if you got your plugin to work instead.
Re: How to insert a drawing in QWidget in Qt Designer form ?
Quote:
Originally Posted by
d_stranz
It would really be much easier if you got your plugin to work instead.
And that's exactly what I'm doing and I've asked for help: creating LED plugins. How do I do then, so that the shape property keeps the selection made and see in Qt Designer (application creation phase in MainWindow) change the shape of the Led of the svg image. How should I write the plugin code to get this effect ?
Re: How to insert a drawing in QWidget in Qt Designer form ?
Quote:
How should I write the plugin code to get this effect ?
The plugin code you wrote (and I built on my PC) works just fine in Qt Designer under Qt 5.15.3. In Qt Designer, I can create an LED widget, change the color and shape, and it shows up on the form in Qt Creator. I don't see any reason why the same code, built against Qt 6.x should not also work with the Qt Designer that ships with the Qt 6.x distribution.
There seems to be something broken in your copy of Qt Creator or in the way you are building or installing the plugin. I think that the plugin is unable to load the SVG files in Qt Designer and I think it is using your icon instead of an actual LED instance. There are two ways to test this:
1 - Change the icon and rebuild the plugin. If you see the new icon when you insert the widget in a Qt Designer form, then you know that is what is happening.
2a - Insert a QMessageBox warning in the paintEvent where you try to load the svg file for the color and shape. If the load fails, pop up the warning.
or
2b - Instead of a message box, if the load fails, draw an "X" instead of rendering the svg.
In the case of 1, it is possible that the Qt Creator cannot make the LED widget at all so is substituting the icon. That could be because you have not linked the DLL against the SVG library, so Qt Designer does not load it and cannot instantiate the SVG renderer.
In the case of 2a, it is creating the widget but is unable to load the SVG to perform the rendering. Again, this could be a problem with the QSvg DLL.
Re: How to insert a drawing in QWidget in Qt Designer form ?
Quote:
Originally Posted by
d_stranz
2a - Insert a QMessageBox warning in the paintEvent where you try to load the svg file for the color and shape. If the load fails, pop up the warning.
...
In the case of 2a, it is creating the widget but is unable to load the SVG to perform the rendering. Again, this could be a problem with the QSvg DLL.
I rewrote the code again and post it for you so you can see it too. I put the QMessageBox in QNewLed::paintEvent(..) at what point ?
QNewLed.h:
Code:
#pragma once
#include <QtWidgets/QWidget>
#include <QtUiPlugin/QDesignerExportWidget>
#include <QtSvg>
#include <QSvgRenderer>
class QDESIGNER_WIDGET_EXPORT QNewLed
: public QWidget{
Q_OBJECT
Q_PROPERTY(ledShape shape READ getShape WRITE setShape)
public:
explicit QNewLed
(QWidget *parent
= nullptr
);
virtual ~QNewLed();
enum ledShape { Circle, Square, Triangle, Rounded };
Q_ENUM(ledShape)
public slots:
ledShape getShape() const { return m_shape; }
void setShape(ledShape);
protected:
ledShape m_shape;
private:
};
QNewLed.cpp:
Code:
#include "QNewLed.h"
{
m_shapes << ":/resources/circle_green.svg" << ":/resources/square_orange.svg" << ":/resources/triang_blue.svg" << ":/resources/round_yellow.svg";
setMinimumSize
(QSize(50,
50));
}
QNewLed::~QNewLed()
{
delete renderer;
}
void QNewLed::setShape(ledShape newShape)
{
m_shape = newShape;
update();
}
{
Q_UNUSED(event);
ledShapeAndColor = m_shapes[m_shape];
painter.
setRenderHint(QPainter::Antialiasing,
true);
renderer->load(ledShapeAndColor);
renderer->render(&painter);
}
QNewLedPlugin.h:
Code:
#pragma once
#include <QtUiPlugin/QDesignerCustomWidgetInterface>
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface" FILE "qnewledplugin.json")
public:
QNewLedPlugin
(QObject *parent
= nullptr
);
bool isContainer() const override;
bool isInitialized() const override;
QIcon icon
() const override;
QString includeFile
() const override;
QString whatsThis
() const override;
private:
bool initialized;
};
QNewLedPlugin.cpp:
Code:
#include "QNewLed.h"
#include "QNewLedPlugin.h"
#include <QtCore/QtPlugin>
{
initialized = false;
}
{
if (initialized)
return;
initialized = true;
}
bool QNewLedPlugin::isInitialized() const
{
return initialized;
}
{
return new QNewLed(parent);
}
QString QNewLedPlugin
::name() const {
return "QNewLed";
}
QString QNewLedPlugin
::group() const {
return "I Miei Plugin";
}
QIcon QNewLedPlugin
::icon() const {
}
QString QNewLedPlugin
::toolTip() const {
}
QString QNewLedPlugin
::whatsThis() const {
}
bool QNewLedPlugin::isContainer() const
{
return false;
}
QString QNewLedPlugin
::domXml() const {
return "<widget class=\"QNewLed\" name=\"led\">\n"
" <property name=\"geometry\">\n"
" <rect>\n"
" <x>0</x>\n"
" <y>0</y>\n"
" <width>50</width>\n"
" <height>50</height>\n"
" </rect>\n"
" </property>\n"
" <property name=\"toolTip\" >\n"
" <string>Binary Led</string>\n"
" </property>\n"
" <property name=\"whatsThis\" >\n"
" <string>Led widget</string>\n"
" </property>\n"
" <property name=\"shape\" >\n"
" <enum>QNewLed::Circle</enum>\n"
" </property>\n"
"</widget>\n";
}
QString QNewLedPlugin
::includeFile() const {
return "QNewLed.h";
}
This new version is a little more simplified than the previous one, just to understand where I'm wrong.
Re: How to insert a drawing in QWidget in Qt Designer form ?
Code:
{
Q_UNUSED(event);
ledShapeAndColor = m_shapes[m_shape];
painter.
setRenderHint(QPainter::Antialiasing,
true);
if ( renderer->load(ledShapeAndColor) )
renderer->render(&painter);
else
QMessageBox::warning( this,
"Warning",
"QSvgRenderer->load() failed" );
}
But this code is very inefficient. You do not need to load the SVG file every time you paint. You need to load it only when you construct the default LED or when you change the shape or color. So in your QNewLed(), setColor(), and setShape() methods, that's where you should call renderer->load(). In the paintEvent() all you need to do is call renderer->render(). In the constructor for the QNewLed class, you should set the default color and shape and load that SVG file there.
Re: How to insert a drawing in QWidget in Qt Designer form ?
I made the change I proposed in paintEvent(QPaintEvent* event). No svg image upload error message appeared. However, it is still impossible to get the new selection accepted by the shape property, which always remains in Circle.
Re: How to insert a drawing in QWidget in Qt Designer form ?
Sorry, I can't give you any more help on this. Your code works on my PC, so I don't know what is wrong on your end. Your JSON file is empty, but it doesn't seem to matter.
One last thing to try: Instead of rendering an SVG file, just replace the paint event code with some simple QPainter drawing. It doesn't matter what it is as long as something different is drawn for each shape. If you still don't see any changes, then I have no idea what could be wrong.
Code:
{
painter.
setRenderHint( QPainter::Antialiasing,
true );
painter.setPen( Qt::blue );
const QRect & rect
= event
->rect
();
switch m_shape :
{
case Circle:
painter.drawEllipse( rect );
break;
case Square:
painter.drawRect( rect );
break;
case Triangle:
{
QPolygon triangle
= QPolygon() << rect.
bottomLeft() << rect.
bottomRight() <<
QPoint( rect.
center().
x(), rect.
topLeft().
y() );
painter.drawConvexPolygon( triangle );
}
break;
case Rounded:
{
QPoint p1
( c.
x(), rect.
bottomLeft().
y() );
QPoint p2
( rect.
bottomLeft().
x(), c.
y() );
QPoint p3
( c.
x(), rect.
topLeft().
y() );
QPoint p4
( rect.
bottomRight().
x(), c.
y());
painter.drawConvexPolygon( diamond );
}
break;
}
}
2 Attachment(s)
Re: How to insert a drawing in QWidget in Qt Designer form ?
First of all, thank you for your patience and advice. I'll try your changes now and see what happens.
Added after 26 minutes:
I tried and absolutely nothing changes, the result is always the same, I can't get the shape to change, it always remains the first value of the enum i.e. Circle, it doesn't take the other values (which are displayed in the shape list).
I attach the images related to the settings of the libraries used in the plugin project and of the application that uses the plugin (plugin test application).
Re: How to insert a drawing in QWidget in Qt Designer form ?
When you are building the plugin, do you have QDESIGNER_WIDGET_EXPORT defined in the preprocessor settings?
Re: How to insert a drawing in QWidget in Qt Designer form ?
Quote:
Originally Posted by
d_stranz
When you are building the plugin, do you have QDESIGNER_WIDGET_EXPORT defined in the preprocessor settings?
no, I didn't write anything in Qt project settings in Visual Studio C++ 2022. By default Visual Studio C++ 2022 put me in the "Preprocessor Definitions" field in C/C++ | Preprocessor: $(Qt_DEFINES_).
Among other things, I also compiled the example reported by Qt 6.5 on the Custom Widget: Analog Clock Plugin. This works fine, even though it has no enum-property to select an item from.
Re: How to insert a drawing in QWidget in Qt Designer form ?
What I wanted to achieve is like in this other program I wrote, without using custom plugins, but reading the .svg files directly.
ProvaQLed.h:
Code:
#pragma once
#include <QtWidgets/QMainWindow>
#include <QPixmap>
#include "ui_ProvaQLed.h"
{
Q_OBJECT
public:
ProvaQLed
(QWidget *parent
= nullptr
);
~ProvaQLed();
protected:
protected slots:
void boxCurrentIndexChanged(int index);
private:
Ui::ProvaQLedClass *ui;
int w = 0;
int h = 0;
bool cliccato = false;
};
ProvaQLed.cpp:
Code:
#include "ProvaQLed.h"
#include <QPainter>
#include <QtSvg>
#include <QSvgRenderer>
{
ui->setupUi(this);
// leggi le dimensioni della QLabel sul form
w = ui->lblimage->width();
h = ui->lblimage->height();
// crea gli item della QComboBox
ui->cmbLeds->addItem("Circle");
ui->cmbLeds->addItem("Square");
ui->cmbLeds->addItem("Triangle");
ui->cmbLeds->addItem("Rounded");
ui->cmbLeds->setCurrentIndex(0);
// assegna un valore di default per il path file .svg
strShape = ":/Resources/circle_orange.svg";
// crea oggetto contenente l'immagine svg
// selezione della voce desiderata
QObject::connect(ui
->cmbLeds,
&QComboBox
::currentIndexChanged,
this,
&ProvaQLed
::boxCurrentIndexChanged);
}
ProvaQLed::~ProvaQLed()
{
delete ui;
}
void ProvaQLed::boxCurrentIndexChanged(int index)
{
if (index == 0)
strShape = ":/Resources/circle_orange.svg";
else if (index == 1)
strShape = ":/Resources/square_red.svg";
else if (index == 2)
strShape = ":/Resources/triang_green.svg";
else if (index == 3)
strShape = ":/Resources/round_yellow.svg";
}
{
// mantieni la giusta risoluzione dell'immagine
ui->lblimage->setPixmap(pix);
}
By pressing on the "Led Shape" combo box, I select the Triangle item and the LED is redrawn with the triangular shape in green colour. I wanted to get this same thing using my plugin and setting the type of shape and color of the LED through the shape property of the plugin.
2 Attachment(s)
Re: How to insert a drawing in QWidget in Qt Designer form ?
I am attaching a complete project here that implements the Qt Designer plugin and an optimized version of the QLed widget.
Please create a new folder and unzip the files there. Open Led.sln in Visual Studio. DO NOT change anything. Just build the Release version, then copy QLed.dll into your Qt plugins\designer folder. If you have other versions of your DLL there, DELETE THEM.
I have set all the project properties in Visual Studio to the correct values for building a Qt Designer plugin. Do not change them. For safety reasons, the DLL does not automatically install into the designer plugins directory. You must copy it there manually.
If Visual Studio complains about a missing Qt version, go to the Extensions -> Qt VS Tools -> Qt Versions in Visual Studio and select the Qt version that you want to use as a default. See the screen shot of that dialog on my system - the version I am using is 5.15.3. If you are using a Qt 6.5.x version, select that one as default. If you do not see your Qt version, click the "<add new Qt version>" link at the bottom of the list, browse for the top-level folder, and add it. Make sure it is checked as the default version.
To test it, open the TestLed.ui file from the TestLed project in Qt Designer. Select one of the LEDs on the form, then change the shape property. If you have built and installed the DLL without changing anything then it should show you the change in the form.
If you do anything else except set up the correct Qt version, then I can't help you any more. I have spent a long time working on this for you, and the plugin and QLed widget work perfectly on my PC.
Attachment 13794
Project files here: Attachment 13796
2 Attachment(s)
Re: How to insert a drawing in QWidget in Qt Designer form ?
Thank you for all the time you have dedicated to my program, but doing everything as you said, the result is always negative: it is not possible to accept changes to the shape property.
Qt 6.5 installation was done with their installer: qt-unified-windows-x64-4.5.2-online.exe. The settings that I used during the installation of Qt 6.5 you see in the 2 attachments that I put you. I do not know what to do...Attachment 13797 Attachment 13798
Re: How to insert a drawing in QWidget in Qt Designer form ?
Quote:
I do not know what to do...
I don't know either. @Lesiok, @Ginsengelf, anyone else - do you have any idea why this works on my system with Qt 5.15.3, but not on @giorgik's system with Qt 6.5? It should be a simple matter of building the plugin against Qt 6 and then copying the DLL into the designer plugins folder. I do not think Qt broke the Qt Designer plugin API between Qt 5 and Qt 6.
Because of Qt's new licensing requirements for Qt 6, I cannot use it so I have not installed it.
Re: How to insert a drawing in QWidget in Qt Designer form ?
Quote:
Originally Posted by
d_stranz
Because of Qt's new licensing requirements for Qt 6, I cannot use it so I have not installed it.
In what sense ? I currently use Qt only for my own use and consumption, not to sell programs. How does it differ from version 5.x. Because otherwise, given the problems I encounter and perhaps due to a License that I don't like, I change the version and go to 5.x too. Let me know about that.
Re: How to insert a drawing in QWidget in Qt Designer form ?
I use Qt for commercial desktop programs. I bought a commercial license to Qt 5 and paid for maintenance support for many years. I stopped paying for maintenance when Qt 6 came out, but the Qt 5 license gives me the right to use the parts of Qt 5 that ship under the commercial license forever. With Qt 6, that changed. If I want a commercial license for Qt 6, I have to pay for it every year for as long as I sell my programs that use it. Even if I stop developing new programs, I still have to pay as long as I am selling programs that are already written. The price is several thousand USD each year. I won't agree to that.
And I do not want to use Qt under open source rules because 1) not all parts of Qt are available under open source and 2) I do not ever want to be in a position of being forced to release my source code if I change Qt to fix a bug or enhance some Qt code. So Qt 5 is good enough for me.
If you do not write commercial software using Qt, then you can use whatever version you want under the open source license.
Re: How to insert a drawing in QWidget in Qt Designer form ?
Thanks for all the clarifications and above all thanks for your help.
Re: How to insert a drawing in QWidget in Qt Designer form ?
For installing Qt 6.5 and then using the Visual Studio C++ 2022 Community to create a project with Qt, I followed this comprehensive video tutorial:
https://www.youtube.com/watch?v=rH2Kq2BIGVs