Search code examples
c++qtqt5qtableview

QTableView to show the content of table item when mouse hover


Writing with phone, so the format may be bad.

I have a table with QTableView, there are two columns in the table. The second column contains a very long string which can't be fully shown without resizing. I want to show the string in a rectangle when I hover the mouse on one item, and the rectangle is near the mouse (many software like Eclipse and VS have such function).

I have searched the internet for a while, but still don't know how to program this view feature.

enter image description here enter image description here


Solution

  • First to implement the popup you need to know when the mouse enters the region of an item in the table, for this we will use the eventFilter() method and will look for when the QEvent::MouseMove event is used and we will obtain the index through the function indexAt() and the position of the mouse, and compare if this is different from the previous index. And if it happens it will show or hide the popup as needed.

    To create the PopUp we use a dialog and insert a QLabel, and use the setWordWrap property to fit the text correctly

    #ifndef TABLEVIEW_H
    #define TABLEVIEW_H
    
    #include <QDialog>
    #include <QEvent>
    #include <QLabel>
    #include <QMouseEvent>
    #include <QTableView>
    #include <QVBoxLayout>
    #include <QHeaderView>
    
    class TableView: public QTableView{
        Q_OBJECT
        QDialog *popup;
        QLabel *popupLabel;
    
    public:
        TableView(QWidget *parent = Q_NULLPTR):QTableView(parent){
            viewport()->installEventFilter(this);
            setMouseTracking(true);
            popup = new QDialog(this, Qt::Popup | Qt::ToolTip);
    
            QVBoxLayout *layout = new QVBoxLayout;
            popupLabel = new QLabel(popup);
            popupLabel->setWordWrap(true);
            layout->addWidget(popupLabel);
            popupLabel->setTextFormat(Qt::RichText);
            //popupLabel->setOpenExternalLinks(true);
            popup->setLayout(layout);
            popup->installEventFilter(this);
        }
    
        bool eventFilter(QObject *watched, QEvent *event){
            if(viewport() == watched){
                if(event->type() == QEvent::MouseMove){
                    QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
                    QModelIndex index = indexAt(mouseEvent->pos());
                    if(index.isValid()){
                        showPopup(index);
                    }
                    else{
                        popup->hide();
                    }
                }
                else if(event->type() == QEvent::Leave){
                    popup->hide();
                }
            }
            else if(popup == watched){
                if(event->type() == QEvent::Leave){
                    popup->hide();
                }
            }
            return QTableView::eventFilter(watched, event);
        }
    
    private:
        void showPopup (const QModelIndex &index) const {
            if(index.column() == 1){
                QRect r = visualRect(index);
                popup->move(viewport()->mapToGlobal(r.bottomLeft()));
                popup->setFixedSize(100, popup->heightForWidth(100));
                popupLabel->setText(index.data(Qt::DisplayRole).toString());
                popup->adjustSize();
                popup->show();
            }
            else {
                popup->hide();
            }
        }
    };
    
    #endif // TABLEVIEW_H
    

    Screenshot:

    enter image description here

    In the following link you will find an example.