【问题标题】:QT Checking multiple boxes with click and dragQT通过单击和拖动检查多个框
【发布时间】:2022-01-13 00:29:43
【问题描述】:

所以我试图弄清楚你将如何制作它,你可以点击 QListView 中的复选框并将鼠标(仍然被点击)拖动到多个复选框上,它也会检查它们。因为现在我必须单击所有要检查的复选框,如果我需要连续检查几个复选框,我更愿意单击并拖动到我需要检查的最后一个。

我也不是指全选方法,我只需要说明在 100 个复选框中可能有 25 个连续需要检查,并且不想一次检查所有复选框。

【问题讨论】:

  • 考虑将所有复选框放在一个自定义小部件中,该小部件覆盖 dragMoveEvent 等。

标签: c++ qt


【解决方案1】:

您可以使用自定义委托来监视鼠标点击/移动并对模型数据进行操作。

带有列表视图和一系列复选框的基本窗口:
MainWindow.cpp

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow),
      m_model(new QStandardItemModel(9, 2))
{
    ui->setupUi(this);

    for (int row = 0; row < m_model->rowCount(); ++row) {
        QStandardItem *Item = new QStandardItem();
        Item->setCheckable( true );
        Item->setCheckState( Qt::Checked );
        m_model->setItem(row, Item);
    }

    ui->listView->setItemDelegateForColumn(0, new CustomDelegate(this));
    ui->listView->setModel(m_model);

}

带有绘制事件的自定义委托(将其替换为您当前正在绘制复选框的内容)和 editorEvent。
在 `editorEvent` 中,在 `MouseButtonPress` 上,我们根据需要选中/取消选中复选框,然后记住我们是否在选中或取消选中 `MouseMove` 中的参考。
然后在“MouseMove”中,当我们通过它们时,我们选中/取消选中复选框。

CustomDeletage.h

#ifndef CUSTOMDELEGATE_H
#define CUSTOMDELEGATE_H

#include <QApplication>
#include <QEvent>
#include <QMouseEvent>
#include <QPainter>
#include <QStyledItemDelegate>

class CustomDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    CustomDelegate(QObject *parent );

    void paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
    {
        Q_ASSERT(index.isValid());

        // Get value from model.
        bool  state = index.data( Qt::DisplayRole ).toInt();
        QStyleOptionButton optBtn;

        optBtn.state = QStyle::State_Enabled; // CheckBox enabled
        if ( option.state & QStyle::State_MouseOver )
            optBtn.state |= QStyle::State_MouseOver; // Mouse over cell

        // If value is true - checked box, otherwise - unchecked box.
        if(state) {
            optBtn.state |= QStyle::State_On;
        } else {
            optBtn.state |= QStyle::State_Off;
        }

        // Check box rect, centered.
        optBtn.rect = QApplication::style()->subElementRect( QStyle::SE_CheckBoxIndicator, &optBtn, Q_NULLPTR );
        const int x = option.rect.center().x() - optBtn.rect.width() / 2;
        const int y = option.rect.center().y() - optBtn.rect.height() / 2;
        optBtn.rect.moveTo( x, y );

        // Draw the background color.
        if (option.state & QStyle::State_Selected && option.state & QStyle::State_Active)
            painter->fillRect(option.rect, option.palette.highlight());
        else if (option.state & QStyle::State_Selected)
            painter->fillRect(option.rect, option.palette.background());

        // Draw the check box.
        QApplication::style()->drawControl( QStyle::CE_CheckBox, &optBtn, painter );
    }


    bool editorEvent( QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index )
    {
        Q_UNUSED(option)
        switch ( event->type() )
        {
        case QEvent::MouseButtonPress:
        {
            // Do nothing if edit model is not editable.
            Qt::ItemFlags flags = model->flags(index);
            if(! flags.testFlag(Qt::ItemIsEditable) ) break;

            // Only accept left clicks.
            QMouseEvent *e = static_cast< QMouseEvent * >( event );
            if ( e->button() != Qt::LeftButton ) break;

            // Invert the current value.
            bool currentValue = model->data(index, Qt::DisplayRole).toBool();
            model->setData(index, !currentValue, Qt::EditRole);

            // Set the process as either checking, or unchecking.
            currentValue ? m_checkingOrUnchecking = 2 : m_checkingOrUnchecking = 1;
            break;
        }

        case QEvent::MouseMove:
        {
            // Do nothing if edit model is not editable.
            Qt::ItemFlags flags = model->flags(index);
            if(! flags.testFlag(Qt::ItemIsEditable) ) break;

            // If we are at the same index as the last time, break so we do not continuously invert the state of a single check box.
            if (index == m_lastPassedOverIndex) break;

            // If mouse is moved while clicked, set the box we pass over to the current checking or unchecking state.
            if(m_checkingOrUnchecking == 1) {
                model->setData(index, true, Qt::EditRole);
            } else if(m_checkingOrUnchecking == 2) {
                model->setData(index, false, Qt::EditRole);
            }

            // Make sure we are not double-inverting an index.
            m_lastPassedOverIndex = index;
            break;
        }

        case QEvent::MouseButtonRelease:
        {
            m_checkingOrUnchecking = 0;
            break;
        }

        default:
            break;
        }

        return true;
    }

private:
        QModelIndex m_lastPassedOverIndex; // The index last passed over, so while clicking over a check box, we do not continupusly invert its state.
        int m_checkingOrUnchecking = 0;  // Is the user currently checking, or unchecking boxes?  0 = do nothing, 1 = checking, 2 = unchecking.
};

#endif // CUSTOMDELEGATE_H

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-16
    • 2014-07-25
    • 1970-01-01
    相关资源
    最近更新 更多