QTableWideget 整行拖动&委托限制编辑&无法响应鼠标事件

QTableWidget的用法总结 - findumars - 博客园

Qt QTableWidget 样式表_漫步繁华街的博客-CSDN博客_qtablewidget 样式

QT模型视图MVC系列教程(5)---自定义委托Delegate编辑时显示_setitemdelegateforrow_暴躁的野生猿的博客-CSDN博客

前言:QT内置了它的两个子类QItemDelegate and QStyledItemDelegate,其中QItemDelegate不支持样式表,QStyledItemDelegate会使用当前样式绘制内容,支持样式表,推荐继承QStyledItemDelegate 来实现自定义委托。

一、实现整行上下拖动

1.写一个继承于 QTableWidget的ProSelectTableWidget类

2.重写拖拽事件dropEvent(QDropEvent *event
3.将TableWidget控件提升为ProSelectTableWidget

ProSelectTableWidget.cpp/.h 资源如下

QTableWidget实现整行拖动-C++文档类资源-CSDN下载

ProSelectTableWidget::ProSelectTableWidget(QWidget *parent)
    : QTableWidget{parent}
{
       //拖拽设置
       this->setDragDropMode(QAbstractItemView::InternalMove);  // 内部移动
       this->setDropIndicatorShown(true);  // drop位置 提示
       this->setSelectionBehavior(QAbstractItemView::SelectRows);//选中整行
}
//重写拖拽事件
void ProSelectTableWidget::dropEvent(QDropEvent *event)
{
    qDebug()<<"dropEvent";
    // 原行号与目标行号的确定
    int row_src,row_dst;
    row_src = this->currentRow();                        // 原行号 可加if
    QTableWidgetItem *item = this->itemAt(event->position().toPoint()); // 获取落点的item
    if(item !=nullptr){                                        // 判断是否为空
        row_dst = item->row();                                 // 不为空 获取其行号
        // 保证鼠标落下的位置 就是拖拽的一行最后所移动到的位置(考虑插入新行 移除原行的上下变化)
        row_src = (row_src > row_dst?    row_src + 1:row_src); // 如果src在dst的下方(行号大),后续插入dst会影响src的行号
        row_dst = (row_src < row_dst?    row_dst + 1:row_dst); // 如果src在dst的上方(行号小),后续移除src会影响dst的行号
        this->insertRow(row_dst);                              // 插入一行
    }
    else{                          // 落点没有item 说明拖动到了最下面
        row_dst = this->rowCount();// 获取行总数
        this->insertRow(row_dst);  // 在最后新增一行
    }
    // 执行移动 并移除原行
    for(int i = 0;i < this->columnCount();i++){            // 遍历列
        this->setItem(row_dst,i,this->takeItem(row_src,i));// 每一列item的移动
    }
    this->removeRow(row_src);                              // 删除原行
}

 二、使用委托类限制整行/列输入内容

函数:
2.1 createEditor
返回在 QTableView 中使用的控件,就在这边用正则限制输入的数据。

2.2 setEditorData
从指定的数据模型设置要由编辑器显示和编辑的数据

2.3 setModelData
从 editor 小部件获取数据,并将数据存储在项目索引处的数据模型中。

2.4 updateEditorGeometry
根据给定的样式选项,更新 index 指定项的编辑器。

2.5void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const

思路:

1.使用委托(直接写函数在头文件),写继承于QItemDelegate的GenderComboBoxDelegate类

2.重新实现 QAbstractItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const

"GenderComboBoxDelegate.h"//限制只能选男或女

#ifndef GENDER_COMBO_BOX_DELEGATE_HPP_
#define GENDER_COMBO_BOX_DELEGATE_HPP_
#include <QItemDelegate>
#include <QComboBox>
class GenderComboBoxDelegate: public QItemDelegate {
    Q_OBJECT
public:
    using QItemDelegate::QItemDelegate;
    QWidget *GenderComboBoxDelegate::createEditor
(QWidget *parent,
 const QStyleOptionViewItem & /*option*/,
const QModelIndex & /*index*/) const
{
   //在tablewidget设置控件
    QComboBox *editor = new QComboBox{parent};
    editor->addItem(tr("男"));
    editor->addItem(tr("女"));
    return editor;
}

#endif

ReadOnlyDelegate.h//限制不可编辑 

#ifndef READONLYDELEGATE_H
#define READONLYDELEGATE_H

#include <QItemDelegate>

class ReadOnlyDelegate : public QItemDelegate

{
    Q_OBJECT
public:
    explicit ReadOnlyDelegate(QObject *parent = nullptr);
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
    const QModelIndex &index) const
        {
            Q_UNUSED(parent)
            Q_UNUSED(option)
            Q_UNUSED(index)
            return NULL;
        }
signals:

};

#endif // READONLYDELEGATE_H

 调用:

GenderComboBoxDelegate  *limitnum = new GenderComboBoxDelegate{this};
//限制第二列编辑
m_ui->userinfoTableWidget->setItemDelegateForColumn(1, limitnum);

参考:QT:在QTableView中使用各种自定义委托_Keycer的博客-CSDN博客

三、解决在QTableWidget控件中无法响应鼠标事件——安装事件过滤器

由于鼠标事件被父窗口拦截,QTableWidget无法捕获鼠标事件,使用Qt的事件过滤器,捕获QTableWidget的视窗(viewPort)所发生的事件。

//在构造函数中为QTableWidget安装事件过滤器
m_ui->userinfoTableWidget->viewport()->installEventFilter(this);

bool eventFilter(QObject *obj, QEvent *event)
{
if (obj == m_ui->userinfoTableWidget->viewport())
    {
        QMouseEvent *e = static_cast<QMouseEvent *>(event);
        if (e == nullptr) {
            return QWidget::eventFilter(obj, event);
        }
        //判断事件类型为鼠标点击
        if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease) {
            deselect(e);
        }
    }
    return QWidget::eventFilter(obj, event);
}

void deselect(QMouseEvent *e)
{
   ...
}

参考:QTableWidget无法响应鼠标点击(QMousePressEvent)的问题_flist的博客-CSDN博客_mousepressevent不响应

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Unity中,我们可以使用以下步骤来实现鼠标拖拽物体移动,并限制拖动范围: 1.创建一个空物体作为拖拽物体的父级,将需要拖拽的物体作为子级添加到其中。 2.在父级上添加一个Box Collider组件,将其设置为Is Trigger。 3.添加一个脚本来控制拖拽为。在脚本中声明一个变量来存储拖拽物体的初始位置,一个变量来存储鼠标按下时的屏幕坐标,以及一个变量来存储拖拽物体的限制范围。 4.在Update()函数中检测鼠标是否按下。如果按下,记录下鼠标按下时的屏幕坐标,并将拖拽物体的初始位置设置为当前位置。 5.如果鼠标一直按下,计算鼠标移动的距离,并将拖拽物体的位置设置为初始位置加上鼠标移动的距离。同时,检测拖拽物体是否超出了限制范围,如果超出了,将其位置设置为限制范围内的最近位置。 6.最后,将脚本添加到父级物体上,运游戏即可实现鼠标拖拽物体移动,并限制拖动范围。 下面是示例代码: ``` using UnityEngine; public class DragObject : MonoBehaviour { private Vector3 initialPosition; private Vector3 mousePosition; private Vector3 limitMin; private Vector3 limitMax; private void Start() { // 设置拖拽物体的限制范围 limitMin = gameObject.GetComponent<BoxCollider>().bounds.min; limitMax = gameObject.GetComponent<BoxCollider>().bounds.max; } private void OnMouseDown() { // 记录鼠标按下时的屏幕坐标和拖拽物体的初始位置 mousePosition = Input.mousePosition; initialPosition = transform.position; } private void OnMouseDrag() { // 计算鼠标移动的距离,并设置拖拽物体的位置 Vector3 offset = Input.mousePosition - mousePosition; Vector3 newPosition = initialPosition + offset; // 检测拖拽物体是否超出限制范围,如果超出了,将其位置设置为限制范围内的最近位置 newPosition.x = Mathf.Clamp(newPosition.x, limitMin.x, limitMax.x); newPosition.y = Mathf.Clamp(newPosition.y, limitMin.y, limitMax.y); newPosition.z = Mathf.Clamp(newPosition.z, limitMin.z, limitMax.z); transform.position = newPosition; } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值