2014-11-19 12 views
7

Ho una finestra di dialogo che ha ad esempio QLineEdit e desidero avvisare l'utente, quando il testo nello QLineEdit è errato e perché è sbagliato. Vorrei mostrare un piccolo pop-up accanto allo QLineEdit che dice ad esempio "questa stringa non ha una vocale". Ho provato QToolTip::showText, ma questo è solo un popup temporaneo che scompare dopo un movimento del mouse. Certamente non voglio nessun tipo di QMessageBox. Quale sarebbe il modo corretto per farlo?Notifica popup sull'input errato in Qt

risposta

11

Mi piace questa domanda, l'ho considerata speciale e mi sono preso il tempo di compilare il popup di notifica che penso tu voglia. Ho creato un'applicazione di test con un semplice QPushButton che mostra il popup. Puoi sempre show e hide a seconda dei segnali che ricevi.

Spero che questo aiuta, ho messo un sacco di gioia in esso :-D

Ecco il risultato finale:

enter image description here

Ecco il progetto di esempio:

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:

0.123.516,410617 millions
#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(); 
} 
+2

Grazie mille, questo è esattamente quello che volevo. Una cosa però è che questa soluzione ruba l'attenzione.Per soluzione, questo non ruba la messa a fuoco, ne abbiamo bisogno. setWindowFlags (Qt :: FramelessWindowHint | Qt :: Tool); setAttribute (Qt :: WA_ShowWithoutActivating); setAttribute (Qt :: WA_TranslucentBackground); Potresti cambiarlo nell'esempio? – tach

+0

@tach Fatto! Grazie! : D – Iuliu

+0

@luliu Grazie per il tuo codice. È davvero un buon esempio La mia domanda è, c'è un modo semplice per far sparire questa etichetta pop-up nello stesso modo dell'animazione? – Horizon1710

4

È possibile creare un QToolTip che rimane attivo fino a quando il tempo scade o si chiama: QToolTip::hideText()

Si crea questo QToolTip con una chiamata a questa funzione statica: http://qt-project.org/doc/qt-5/qtooltip.html#showText-2

Passando in un -1 per il msecDlayTime lascerà lo QToolTip fino a quando l'utente non farà clic sul mouse.

Lo svantaggio è che solo l'ultima versione di Qt supporta questo.

+0

Questa è una buona soluzione, il suo svantaggio è che solo una descrizione comandi può essere presente in una sola volta . – tach