QTableView add Rows renders wrong



  • I have a Problem actually. When i add a Row to a normal QTableView it renders outside of the QTableView like here.
    0_1503339642631_hinzugefügt.png

    This is the only QTableView i have that will do that, when i add Rows. The Problem is also, when i delete Rows. Then the overwritten Part is always there.

    0_1503339703522_gelöscht.png

    Anyone knows what that is?


  • Lifetime Qt Champion

    Hi,

    You should share how you create that QTableView as well as the configuration you use for it.



  • doctorContactModel = new DoctorContactModel(this);
        DoctorContactDelegate *doctorContactDelegate = new DoctorContactDelegate(this);
        ui->tvDoctorContact->setModel(doctorContactModel);
        ui->tvDoctorContact->setItemDelegate(doctorContactDelegate);
        ui->tvDoctorContact->setSelectionMode(QAbstractItemView::SingleSelection);
        ui->tvDoctorContact->setEditTriggers(QAbstractItemView::SelectedClicked);
        ui->tvDoctorContact->resizeColumnToContents(0);
        ui->tvDoctorContact->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
        ui->tvDoctorContact->horizontalHeader()->setStretchLastSection(true);
    

    I didnt changed something in the Configuration of the QTableView. Only the Objectname. But how can i post the Configuration?


  • Lifetime Qt Champion

    That looks good.

    What is your DoctorContactModel ?



  • @SGaist said in QTableView add Rows renders wrong:

    DoctorContactModel

    Thats a Model Class from QAbstractTableModel. I can post the code.

    #include "doctorcontactmodel.h"
    #include "database.h"
    
    DoctorContactModel::DoctorContactModel(QObject *parent)
        : QAbstractTableModel(parent)
    {
    }
    
    DoctorContactModel::~DoctorContactModel()
    {
        for (auto item : mItems)
        {
            delete item;
        }
    }
    
    QVariant DoctorContactModel::headerData(int section, Qt::Orientation orientation, int role) const
    {
        if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
        {
            switch (section)
            {
                case 0:
                    return QString("ID");
                case 1:
                    return QString("Kontakt");
                case 2:
                    return QString("Kategorie");
                case 3:
                    return QString("Kommentar");
            }
        }
    
        return QVariant();
    }
    
    int DoctorContactModel::rowCount(const QModelIndex &parent) const
    {
        if (parent.isValid())
            return 0;
    
        return mItems.count();
    }
    
    int DoctorContactModel::columnCount(const QModelIndex &parent) const
    {
        if (parent.isValid())
            return 0;
    
        return 4;
    }
    
    QVariant DoctorContactModel::data(const QModelIndex &index, int role) const
    {
        if (!index.isValid())
            return QVariant();
    
        if (role == Qt::DisplayRole)
        {
            if (index.column() == 0)
                return mItems.at(index.row())->Id;
            if (index.column() == 1)
                return mItems.at(index.row())->Value;
            if (index.column() == 3)
                return mItems.at(index.row())->Comment;
        }
    
        if (index.column() == 2)
            return QVariant::fromValue(mItems.at(index.row())->Type);
    
        return QVariant();
    }
    
    Qt::ItemFlags DoctorContactModel::flags(const QModelIndex &index) const
    {
        return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
    }
    
    bool DoctorContactModel::setData(const QModelIndex &index, const QVariant &value, int role)
    {
        Q_UNUSED(role);
    
        if (index.column() == 1)
            mItems.value(index.row())->Value = value.toString();
        else if (index.column() == 2)
            mItems.value(index.row())->Type->setCurrentIndex(value.toInt());
        else if (index.column() == 3)
            mItems.value(index.row())->Comment = value.toString();
    
        Database *db = Database::instance();
        db->updateDoctorContact(mItems.at(index.row())->Id, mItems.at(index.row())->Value,
                                mItems.at(index.row())->Type->currentIndex(), mItems.at(index.row())->Comment);
    
        emit columnChanged();
    
        return true;
    }
    
    void DoctorContactModel::setupModel(int id)
    {
        this->beginResetModel();
        mItems.clear();
    
        Database *db = Database::instance();
        QVector<QList<QString>> data = db->selectDoctorContact(id);
    
        for (QList<QString> row : data)
        {
            mItems.append(new DoctorContactItem(row.at(0).toInt(), row.at(1), row.at(2).toInt(), row.at(3)));
        }
    
        this->endResetModel();
    }
    
    void DoctorContactModel::addRow(int doctorid)
    {
        int count = rowCount();
        beginInsertRows(QModelIndex(), count, count);
    
        Database *db = Database::instance();
        int id = db->insertDoctorContact(doctorid, "", 0, "");
        mItems.append(new DoctorContactItem(id, "", 0, ""));
    
        endInsertRows();
    }
    
    void DoctorContactModel::removeRow(QModelIndex &index)
    {
        beginRemoveRows(QModelIndex(), index.row(), index.row());
    
        Database *db = Database::instance();
        db->deleteDoctorContact(mItems.at(index.row())->Id);
        mItems.remove(index.row());
    
        endRemoveRows();
    }
    

    Maybe its a Problem with the Layout!? I dont know.


  • Lifetime Qt Champion

    Since it's connected to a database, why not use a QSqlTableModel ?



  • Maybe thats better, but i dont want to rewrite all my Code. Im fine with that Solution. Im just more interested now why the TableView renders outside its content.

    update: finally i found out that one line is causing the problem.

    void DoctorContactDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        if (index.column() == 0)
        {
            painter->fillRect(option.rect, QBrush(QColor(215, 215, 215, 84)));
            QStyledItemDelegate::paint(painter, option, index);
        }
        else if (index.data().canConvert<DoctorComboBox*>())
        {
            DoctorComboBox *cbox = qvariant_cast<DoctorComboBox*>(index.data());
            cbox->setGeometry(option.rect);
            cbox->render(painter, painter->deviceTransform().map(option.rect.topLeft())); //<--- this line
        }
        else
            QStyledItemDelegate::paint(painter, option, index);
    }
    


  • Nobody has an Idea? It seems like that the TableView has generally Problems with ComboBoxes. I added a normal QComboBox to that Cell and the Problem still exists.


  • Lifetime Qt Champion

    Do you really need to do custom painting for your DoctorComboBox ? Can't it be painted like classic QComboBox ?



  • What do you mean with that?


  • Lifetime Qt Champion

    The thing is, it seems that you want to show your custom combo box like it was a permanent editor, is that the case ?

    If not, I was just wondering why you were rendering the widget itself. Your model could return the data for the different roles needed to show the data the way you want it (i.e. background role, decoration role etc.).



  • It would be nice to show the Data in a ComboBox permanently. I tried to render a QLineEdit and have the same Problem as with the ComboBox. I dont know why i cant render an Element without having that Problem.

    I want that the User can see that the Data is changeable and because of that i picked directly a ComboBox. You have an Idea how i can solve that different?



  • Nobody can help me? I cant render any Element in this Table without having this Problem. Is that a Bug?


  • Lifetime Qt Champion

    First, I'd check with a delegate like the Star Delegate sample to see if everything goes well with custom painting. Then I'd check with just a rendering a combo box without any modification to the painter.



  • I tested it now with another Widgets and the Problem is still existing. So its not a Problem with only QComboBox. So it seems its a generally Problem with rendering. I have a similar Widget like in the StarDelegate Example and the Problem occurs. I tried not to modiy the QPainter but the Problem still exists. I also deleted the QTableView and created a new One.

    Any other Ideas?


  • Qt Champions 2016

    Hi
    I newer say such issue with
    https://wiki.qt.io/Combo_Boxes_in_Item_Views

    I think you ask it to draw in wrong position with
    painter->deviceTransform().map(option.rect.topLeft()))

    You should check the y pos when its drawing wrongly.

    Else it look ok from fast glance.



  • @mrjj said in QTableView add Rows renders wrong:

    painter->deviceTransform().map(option.rect.topLeft()))

    If i delete this part the Problem still exists. I took a look at your Link. In this Example there is no paint Event and im wondering. How does the Delegate know how to paint the Element?

    If i remove the render Part the ComboBox isnt shown.

    I think its a Problem with the Painter or the Renderfunction. Or perhaps something in my Layout.

    Update:

    It looks like its a Layout Problem. When i switch the Buttons to the Upper i dont have that Problem.
    0_1503921395908_Unbenannt.png

    But why? Its a normal Gridlayout with a normal Row under the QTableView.


  • Lifetime Qt Champion

    Can you show the code that setup everything including the buttons ?



  • I use the Designer. Cant show any Code, but only the XML Part which is not editable.

    0_1503991011571_Unbenannt.png



  • still have the problem. the rows renders outside of the tableview.


  • Lifetime Qt Champion

    Then can you provide a minimal compilable example so people can test that locally to help find the problem ?



  • I have made the Project Public in my Repository for some Days.

    https://git.kubitox.com/Ben/KT

    The Problem is in "Medikamentenplan" the below part. The Problem occurs in DoctorContact


  • Lifetime Qt Champion

    I can't reproduce the defect you have on macOS.

    On a side note, you should review that code base, I had to fix several errors before being able to run your application.



  • I installed a Virtual Machine with Linux and tested it. You are right, on other OS it isnt there. Maybe a Problem with Windows. But i dont know how to fix that now. Im using QT 5.9.1 and MSVC 2015 with 64-bit.

    Could it be that the Problem is a Driver Problem?


  • Lifetime Qt Champion

    Maybe a glitch in the Windows style.



  • I have totally no Answer for that. Anyone has the Time to Check my Project over Teamviewer? If yes please write me a Message. We can do that with Teamspeak or Discord. Would be nice if you speak German.



  • I updated now to Qt 5.9.2 and the Problem is gone. Thx for everyone that tried to help.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.