本文介绍了QListWidget 在多个项目之间单击和拖动时导致分段错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 QListWidget,其中有多个项目,每个项目在点击时都像一个按钮响应.我遇到了一个问题,如果您单击一个项目并将鼠标拖动到屏幕上除您单击的项目之外的任何其他位置,那么程序将导致分段错误和崩溃.有谁知道我该如何解决这个问题?

I have a QListWidget with multiple items each acting like a button responding when clicked on. I have run into a problem where if you click on one item and drag the mouse to anywhere else on the screen apart from the item you clicked on then the program will cause a segmentation fault and crash. Does anyone know how I might fix this?

我已经包含了我在下面编写的所有代码,尽管此代码还依赖于我认为无法在此处发布的专有代码

I have included all the code that I have written below, although this code also relies on proprietary code that I don't think I can post here

window.cc

#include "globals.h"

#include <QLabel>
#include <QBoxLayout>
#include <QScrollArea>
#include <QListWidget>
#include <QListWidgetItem>
#include <QPushButton>
#include <QMessageBox>

#include "windowheader.h"

namespace{

class statisticsTab : public QWidget {
public:
    statisticsTab();
private:
    QGridLayout * layout;
    QLabel * title;
    QLabel * userListTitle;
    QLabel * branchListTitle;
    UserListWidget * userList;
    BranchListWidget * branchList;
    QListWidget * statsPage;
};

inline statisticsTab::statisticsTab() : QWidget() {
    layout = new QGridLayout();
    cur_repo = new GITPP::REPO();

    title = new QLabel("Repository Statistics");
    title->setStyleSheet("QLabel {font-weight: bold;}");
    layout->addWidget(title, 0, 0, 1, 2);

    userListTitle = new QLabel("Contributors");
    layout->addWidget(userListTitle, 1, 0, 1, 1);

    branchListTitle = new QLabel("Branches");
    layout->addWidget(branchListTitle, 1, 1, 1, 1);

    statsPage = new QListWidget();
    layout->addWidget(statsPage, 3, 0, 1, 2, Qt::AlignTop);
    QListWidgetItem * statsPageDefault = new QListWidgetItem(QString("Click on a contributor or branch to get started!"), 0, 0);
    statsPage->addItem(statsPageDefault);

    userList = new UserListWidget(statsPage);
    layout->addWidget(userList, 2, 0, 1, 1);

    branchList = new BranchListWidget(statsPage);
    layout->addWidget(branchList, 2, 1, 1, 1);

    if(cur_repo != nullptr) {
        GITPP::COMMITS commits = cur_repo->commits();
        std::vector <std::string> contributors;

        for(auto commit : commits) {
            contributors.push_back(commit.author());
        }

        std::sort(contributors.begin(), contributors.end());
        contributors.erase(unique(contributors.begin(), contributors.end()), contributors.end());

        for(auto contributor : contributors) {
            QString contributorName = QString::fromStdString(contributor);
            QListWidgetItem * contributorNameItem = new QListWidgetItem(contributorName);
            userList->addItem(contributorNameItem);
        }

        GITPP::BRANCHES branches = cur_repo->branches();

        for(auto branch : branches) {
            QListWidgetItem * branchName = new QListWidgetItem(QString::fromStdString(branch.name()), 0, 0);
            branchList->addItem(branchName);
        }
    } else {
        QListWidgetItem * branchListDefault = new QListWidgetItem(QString("No branches found"), 0, 0);
        branchList->addItem(branchListDefault);

        QListWidgetItem * userListDefault = new QListWidgetItem(QString("No users found"), 0, 0);
        userList->addItem(userListDefault);
    }

    setLayout(layout);
}

INSTALL_TAB(statisticsTab, "Statistics");

}

windowheader.h

#ifndef WINDOWHEADER_H
#define WINDWOHEADER_H

#include <QListWidget>
#include <string>
#include <limits.h>
#include <unistd.h>
#include <QPushButton>
#include <QFileDialog>
#include <QMessageBox>

#include "globals.h"

class UserListWidget : public QListWidget {
    Q_OBJECT
public:
    UserListWidget(QListWidget * statsPage);

private slots:
    void updateStatsPage();
private:
    QListWidget * statsPage;
};

inline UserListWidget::UserListWidget(QListWidget * statsPageArg) : QListWidget() {
    connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(updateStatsPage()));
    statsPage = statsPageArg;
}

inline void UserListWidget::updateStatsPage() {
    GITPP::CONFIG config = cur_repo->config();
    GITPP::COMMITS commits = cur_repo->commits();


    QString statsTitle = QString("Here are some stats about the user ") + this->currentItem()->text();
    QListWidgetItem * statsTitleItem = new QListWidgetItem(statsTitle);
    statsPage->clear();
    statsPage->addItem(statsTitleItem);

    for(auto thing : config) {
        QString statsInfo = QString::fromStdString(thing.name());
        QListWidgetItem * statsInfoItem = new QListWidgetItem(statsInfo);
        statsPage->addItem(statsInfoItem);
    }

    selectionModel()->clear();
}

class BranchListWidget : public QListWidget {
    Q_OBJECT
public:
    BranchListWidget(QListWidget * statsPage);

private slots:
    void updateStatsPage();
private:
    QListWidget * statsPage;
};

inline BranchListWidget::BranchListWidget(QListWidget * statsPageArg) : QListWidget() {
    connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(updateStatsPage()));
    statsPage = statsPageArg;
}

inline void BranchListWidget::updateStatsPage() {
    GITPP::CONFIG config = cur_repo->config();
    GITPP::COMMITS commits = cur_repo->commits();

    QString statsTitle = QString("Here are some stats about the branch ") + this->currentItem()->text();
    QListWidgetItem * statsTitleItem = new QListWidgetItem(statsTitle);
    statsPage->clear();
    statsPage->addItem(statsTitleItem);

    for(auto thing : config) {
        QString statsInfo = QString::fromStdString(thing.name());
        QListWidgetItem * statsInfoItem = new QListWidgetItem(statsInfo);
        statsPage->addItem(statsInfoItem);
    }

    selectionModel()->clear();
}

#endif

Valgrind 输出:

Valgrind output:

==9475== Invalid read of size 8
==9475==    at 0x1158B5: UserListWidget::updateStatsPage() (in /home/alexis/Desktop/programming/uni_work/comp_2811/cw2/ui_cw3/2811_gui)
==9475==    by 0x5F5D5E8: QMetaObject::activate(QObject*, int, int, void**) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.7.1)
==9475==    by 0x5F5D5E8: QMetaObject::activate(QObject*, int, int, void**) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.7.1)
==9475==    by 0x5EE0BE6: QItemSelectionModel::selectionChanged(QItemSelection const&, QItemSelection const&) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.7.1)
==9475==    by 0x5EE544A: QItemSelectionModel::emitSelectionChanged(QItemSelection const&, QItemSelection const&) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.7.1)
==9475==    by 0x5EE8F91: QItemSelectionModel::select(QItemSelection const&, QFlags<QItemSelectionModel::SelectionFlag>) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.7.1)
==9475==    by 0x54DF9B4: QListView::setSelection(QRect const&, QFlags<QItemSelectionModel::SelectionFlag>) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.7.1)
==9475==    by 0x54C6B3E: QAbstractItemView::mouseMoveEvent(QMouseEvent*) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.7.1)
==9475==    by 0x54E6386: QListView::mouseMoveEvent(QMouseEvent*) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.7.1)
==9475==    by 0x52B8277: QWidget::event(QEvent*) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.7.1)
==9475==    by 0x53A0A0D: QFrame::event(QEvent*) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.7.1)
==9475==    by 0x54C7502: QAbstractItemView::viewportEvent(QEvent*) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.7.1)
==9475==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==9475==
==9475==
==9475== Process terminating with default action of signal 11 (SIGSEGV)
==9475==  Access not within mapped region at address 0x0
==9475==    at 0x1158B5: UserListWidget::updateStatsPage() (in /home/alexis/Desktop/programming/uni_work/comp_2811/cw2/ui_cw3/2811_gui)
==9475==    by 0x5F5D5E8: QMetaObject::activate(QObject*, int, int, void**) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.7.1)
==9475==    by 0x5F5D5E8: QMetaObject::activate(QObject*, int, int, void**) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.7.1)
==9475==    by 0x5EE0BE6: QItemSelectionModel::selectionChanged(QItemSelection const&, QItemSelection const&) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.7.1)
==9475==    by 0x5EE544A: QItemSelectionModel::emitSelectionChanged(QItemSelection const&, QItemSelection const&) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.7.1)
==9475==    by 0x5EE8F91: QItemSelectionModel::select(QItemSelection const&, QFlags<QItemSelectionModel::SelectionFlag>) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.7.1)
==9475==    by 0x54DF9B4: QListView::setSelection(QRect const&, QFlags<QItemSelectionModel::SelectionFlag>) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.7.1)
==9475==    by 0x54C6B3E: QAbstractItemView::mouseMoveEvent(QMouseEvent*) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.7.1)
==9475==    by 0x54E6386: QListView::mouseMoveEvent(QMouseEvent*) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.7.1)
==9475==    by 0x52B8277: QWidget::event(QEvent*) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.7.1)
==9475==    by 0x53A0A0D: QFrame::event(QEvent*) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.7.1)
==9475==    by 0x54C7502: QAbstractItemView::viewportEvent(QEvent*) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.7.1)

推荐答案

看来分段错误发生在 UserListWidget::updateStatsPage() 方法中.

It appears that the segmentation fault is occurring within the UserListWidget::updateStatsPage() method.

鉴于可用信息有限,并且您已经说过将鼠标从最初单击的项目上拖出时会出现此问题,我怀疑this->currentItem() 在方法调用 this->currentItem()->text() 的代码行中返回一个空指针.当您第一次单击小部件列表项时,我猜会调用 UserListWidget::updateStatsPage() 方法,并从 this->currentItem().但是随后您拖动鼠标,如果将其从当前项目中拖出,则会生成另一个 itemSelectionChanged() 信号.如果您将鼠标完全从 QListWidget 上拖开,我想该信号将在 this->currentItem() 返回空指针时被调​​用表示未选择任何内容.

Given the limited information available and that you've said this problem occurs when you drag the mouse off of the item originally clicked, I suspect that this->currentItem() is returning a null pointer in the line of code where the method calls this->currentItem()->text(). When you first click on a widget list item, I'm guessing that the UserListWidget::updateStatsPage() method is called with a non-null pointer being returned from this->currentItem(). But then you drag the mouse and if you drag it off of the current item, another itemSelectionChanged() signal is generated. If you've dragged the mouse off of the QListWidget entirely, I imagine the signal would be called at a time when this->currentItem() will return a null pointer indicating that nothing is selected.

尝试检查 this->currentItem() 是否为 null,如果不为 null,则仅取消引用它.

Try checking whether this->currentItem() is null and only dereference it if not null.

这篇关于QListWidget 在多个项目之间单击和拖动时导致分段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-26 15:38