Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pop-up notification about wrong input in Qt

I have a dialog that has for example QLineEdit and I would like to notify the user, when the text in the QLineEdit is wrong and why it is wrong. I would like to show a small pop-up next to the QLineEdit that says for example "this string doesn't have a vowel". I tried QToolTip::showText, but this is only temporary popup which disappears after a mouse movement. I certainly don't want any kind of QMessageBox. What would be the correct way to do this?

like image 363
tach Avatar asked Nov 19 '14 19:11

tach


2 Answers

You can create a QToolTip that remains active until the time expires or you call: QToolTip::hideText()

You create this QToolTip with a call to this static function: http://qt-project.org/doc/qt-5/qtooltip.html#showText-2

Passing in a -1 for the msecDlayTime will leave the QToolTip up until the user clicks the mouse.

The downside is that only the latest version of Qt supports this.

like image 87
Jonathan Mee Avatar answered Sep 23 '22 19:09

Jonathan Mee


I like this question, I've considered it a special one and I took the time to build the notification popup I think you want. I've built a test application with a simple QPushButton which shows the popup. You can always show and hide it depending on signals you receive.

I hope this helps, I've put a lot of joy in it :-D

Here is the final result:

enter image description here

Here is the example project:

popup.pro:

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = Popup
TEMPLATE = app


SOURCES += main.cpp\
        widget.cpp \
    popupwidget.cpp

HEADERS  += widget.h \
    popupwidget.h

FORMS    += widget.ui

popupwidget.h:

#ifndef POPUPWIDGET_H
#define POPUPWIDGET_H

#include <QWidget>
#include <QLabel>
#include <QGridLayout>
#include <QPropertyAnimation>

class PopUpWidget : public QWidget
{
    Q_OBJECT

    Q_PROPERTY(float popupOpacity READ getPopupOpacity WRITE setPopupOpacity)

    void setPopupOpacity(float opacity);
    float getPopupOpacity() const;

public:
    explicit PopUpWidget(QWidget *parent = 0);

protected:
    void paintEvent(QPaintEvent *e);

public slots:
    void setPopupText(const QString& text);
    void show();

private:
    QLabel label;
    QGridLayout layout;
    QPropertyAnimation animation;
    float popupOpacity;
};

#endif // POPUPWIDGET_H

popupwidget.cpp:

#include "popupwidget.h"

#include <QPainter>

PopUpWidget::PopUpWidget(QWidget *parent) :
    QWidget(parent)
{
    resize(200, 50);

    setWindowFlags(Qt::FramelessWindowHint | Qt::Tool);
    setAttribute(Qt::WA_TranslucentBackground);
    setAttribute(Qt::WA_ShowWithoutActivating);

    animation.setTargetObject(this);
    animation.setPropertyName("popupOpacity");
    animation.setDuration(150);

    label.setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);

    layout.addWidget(&label, 0, 0);
    setLayout(&layout);
}

void PopUpWidget::paintEvent(QPaintEvent *e)
{
    Q_UNUSED(e)

    // Draw the popup here
    // You can always pick an image and use drawPixmap to
    // draw it in order to make things simpler

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    // Prepare the popup dimensions
    QRect roundedRectDimensions;
    roundedRectDimensions.setX(rect().x() + 5);
    roundedRectDimensions.setY(rect().y() + 5);
    roundedRectDimensions.setWidth(rect().width() - 10);
    roundedRectDimensions.setHeight(rect().height() - 10);

    painter.setBrush(QBrush(Qt::lightGray));

    QPen pen;
    pen.setColor(Qt::gray);
    pen.setWidth(3);
    painter.setPen(pen);

    // Draw the popup body
    painter.drawRoundedRect(roundedRectDimensions, 15, 15);

    painter.setPen(Qt::NoPen);
    painter.setBrush(QBrush(Qt::gray));

    // Draw the popup pointer
    const QPointF points[3] = {
        QPoint(roundedRectDimensions.x(), roundedRectDimensions.height() / 2 - 5 + 3),
        QPoint(roundedRectDimensions.x(), roundedRectDimensions.height() / 2 + 5 + 3),
        QPoint(roundedRectDimensions.x() - 5, roundedRectDimensions.height() / 2 + 3)
    };

    painter.drawPolygon(points, 3);
}

void PopUpWidget::setPopupText(const QString &text)
{
    label.setText(text);
}

void PopUpWidget::show()
{
    setWindowOpacity(0.0);

    animation.setStartValue(0.0);
    animation.setEndValue(1.0);

    QWidget::show();

    animation.start();
}

void PopUpWidget::setPopupOpacity(float opacity)
{
    popupOpacity = opacity;

    setWindowOpacity(opacity);
}

float PopUpWidget::getPopupOpacity() const
{
    return popupOpacity;
}

widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

#include "popupwidget.h"

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void onPopUpButtonClicked();

private:
    Ui::Widget *ui;
    PopUpWidget *popUp;
};

#endif // WIDGET_H

widget.cpp:

#include "widget.h"
#include "ui_widget.h"


#include <QDebug>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    popUp = new PopUpWidget(this);

    connect(ui->popUpButton, SIGNAL(clicked()),
            SLOT(onPopUpButtonClicked()));
}

Widget::~Widget()
{
    delete ui;
}

void Widget::onPopUpButtonClicked()
{
    popUp->setPopupText("Example popup notification...");

    const QPoint globalPos = ui->popUpButton->mapFromGlobal(QPoint(0, 0));
    const int posX = -globalPos.x();
    const int posY = -globalPos.y();

    popUp->setGeometry(posX + ui->popUpButton->width(),
                       posY - ui->popUpButton->height() / 2,
                       popUp->width(),
                       popUp->height());

    popUp->show();
}

widget.ui:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Widget</class>
 <widget class="QWidget" name="Widget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>223</width>
    <height>128</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Widget</string>
  </property>
  <layout class="QGridLayout" name="gridLayout">
   <item row="0" column="0">
    <widget class="QPushButton" name="popUpButton">
     <property name="text">
      <string>Pop notification!</string>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

main.cpp:

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    Widget w;
    w.show();

    return a.exec();
}
like image 21
Iuliu Avatar answered Sep 23 '22 19:09

Iuliu