本人首先学习了一下QDrag,然后没学懂,
于是就自己重写QTreeWidget的MousePressEvent,MouseMoveEvent以及MouseReleaseEvent来实现了。
大概的思路就是:
①在MousePressEvent中获取要拖拽的项目,记为pSource;
②在MouseMoveEvent中显示一个Label,用来更加显性的表示拖拽;
③在MouseReleaseEvent中获取拖拽到的项目,记为pTarget,然后将pSource插入到pTarget周围。
代码如下
(在每个代码块后面会有简短的说明帮助理解)
class DragTreeWidget : public QTreeWidget
Q_OBJECT
public:
DragTreeWidget(QWidget* parent = nullptr);
private:
//初始化函数
void initTreeWidget();
void mousePressEvent(QMouseEvent* ev) override;
void mouseMoveEvent(QMouseEvent* ev) override;
void mouseReleaseEvent(QMouseEvent* ev) override;
private:
//用来显示label,显性表示拖拽
QLabel label;
//表示被拖拽的item
QTreeWidgetItem* pSource;
//表示被拖拽的item的父节点
QTreeWidgetItem* pParent;
//表示被拖拽的item在父节点中的索引
int originIndex;
//用于判断在mouseMoveEvent中是否已经移除了组件
bool isJudged;
头文件,没什么好说的。
void DragTreeWidget::initTreeWidget()
for(int i=0;i<10;i++){
QTreeWidgetItem* pTopItem = new QTreeWidgetItem(this);
pTopItem->setText(0,QString::number(114514+i));
addTopLevelItem(pTopItem);
for(int i=0;i<10;i++){
QTreeWidgetItem* pChildItem = new QTreeWidgetItem(topLevelItem(0));
pChildItem->setText(0,QString::number(191981+i));
topLevelItem(0)->addChild(pChildItem);
用来插入一些item用来进行实验。
DragTreeWidget::DragTreeWidget(QWidget *parent)
:QTreeWidget(parent),
label(this),
pSource(nullptr)
initTreeWidget();
setHeaderHidden(true);
label.resize(100,30);
label.setText("");
label.hide();
类构造函数,隐藏了QTreeWidget的头部,设置label大小并隐藏label。
void DragTreeWidget::mousePressEvent(QMouseEvent *ev)
qDebug()<<"in mousePressEvent"<<endl;
pSource = itemAt(ev->pos());
qDebug()<<pSource->text(0)<<endl;
if(pSource->parent()){
qDebug()<<"source parent is "<<pSource->parent()->text(0)<<endl;
label.setText(pSource->text(0));
isJudged = false;
QTreeWidget::mousePressEvent(ev);
在mousePressEvent之中,主要是确定被拖拽的目标。
因为如果这个时候就将item从列表中take出来的话,那么将无法实现将列表展开的功能。
所以具体将列表take出来的行为,放入到mouseMoveEvent之中进行。
然后,这就导致了mouseMoveEvent中的下一个坑(悲
void DragTreeWidget::mouseMoveEvent(QMouseEvent *ev)
if(pSource==nullptr){
QTreeWidget::mouseMoveEvent(ev);
return;
qDebug()<<"in mouseMoveEvent"<<endl;
label.show();
label.move(ev->pos());
if(isJudged==false){
isJudged = true;
if(pSource->parent()){
qDebug()<<"isSubItem"<<endl;
pParent = pSource->parent();
originIndex = pParent->indexOfChild(pSource);
pParent->takeChild(originIndex);
else{
qDebug()<<"isMainItem"<<endl;
pParent = nullptr;
takeTopLevelItem(indexOfTopLevelItem(pSource));
qDebug()<<"source = "<<pSource->text(0)<<endl;
因为需要在mouseMoveEvent之中将被拖拽的目标给take出来,所以会出现一个问题:
mouseMoveEvent并不是只执行一次,而是每隔一段时间就会执行一次,也就是执行多次。
将item从列表中take出来后,其parent会为nullptr。这样的话就无法判断出被拖拽的item究竟是父节点还是子节点了。
所以这里需要使用一个变量,判断是否有被判断过。
那么为什么不在mousePressEvent中进行判别呢?
。。。有道理,回头实践一下。
void DragTreeWidget::mouseReleaseEvent(QMouseEvent *ev)
qDebug()<<"in mouseReleaseEvent"<<endl;
label.hide();
QTreeWidgetItem* pTarget = itemAt(ev->pos());
if(pTarget==nullptr){
if(pParent){
pParent->insertChild(originIndex,pSource);
else{
addTopLevelItem(pSource);
setCurrentItem(pSource);
return;
// qDebug()<<"is child = "<<isChild<<endl;
if(pTarget->parent()){
qDebug()<<"PTarget parent = "<<pTarget->parent()->text(0)<<endl;
//如果是父节点
if(pTarget->parent()==nullptr){
if(pParent){
pTarget->addChild(pSource);
else{
insertTopLevelItem(indexOfTopLevelItem(pTarget)+1,pSource);
//如果是子节点
else{
if(pParent){
QTreeWidgetItem* parent = pTarget->parent();
parent->insertChild(parent->indexOfChild(pTarget)+1,pSource);
else{
setCurrentItem(pSource);
mouseReleaseEvent写的比较臃肿冗长,因为其实按道理这地方应该分为几个函数分开写的,不过因为是demo,所以不管那么多了。
mouseReleaseEvent中大致做了如下几件事:
①判断被拖拽的item(pSource)、拖拽到的item(pTarget)是否有效
②判断pSource、pTarget的类型
③根据类型(父类节点被拖拽到父类节点、子类节点被拖拽到子类节点、子类节点被拖拽到父类节点。。。)来执行对应的行为
以后也许会补全一下注释,让其更加容易理解。
整个源文件代码如下:
DragTreeWidget::DragTreeWidget(QWidget *parent)
:QTreeWidget(parent),
label(this),
pSource(nullptr)
initTreeWidget();
setHeaderHidden(true);
label.resize(100,30);
label.setText("");
label.hide();
void DragTreeWidget::initTreeWidget()
for(int i=0;i<10;i++){
QTreeWidgetItem* pTopItem = new QTreeWidgetItem(this);
pTopItem->setText(0,QString::number(114514+i));
addTopLevelItem(pTopItem);
for(int i=0;i<10;i++){
QTreeWidgetItem* pChildItem = new QTreeWidgetItem(topLevelItem(0));
pChildItem->setText(0,QString::number(191981+i));
topLevelItem(0)->addChild(pChildItem);
void DragTreeWidget::mousePressEvent(QMouseEvent *ev)
qDebug()<<"in mousePressEvent"<<endl;
pSource = itemAt(ev->pos());
qDebug()<<pSource->text(0)<<endl;
if(pSource->parent()){
qDebug()<<"source parent is "<<pSource->parent()->text(0)<<endl;
label.setText(pSource->text(0));
isJudged = false;
QTreeWidget::mousePressEvent(ev);
void DragTreeWidget::mouseMoveEvent(QMouseEvent *ev)
if(pSource==nullptr){
QTreeWidget::mouseMoveEvent(ev);
return;
qDebug()<<"in mouseMoveEvent"<<endl;
label.show();
label.move(ev->pos());
if(isJudged==false){
isJudged = true;
if(pSource->parent()){
qDebug()<<"isSubItem"<<endl;
pParent = pSource->parent();
originIndex = pParent->indexOfChild(pSource);
pParent->takeChild(originIndex);
else{
qDebug()<<"isMainItem"<<endl;
pParent = nullptr;
takeTopLevelItem(indexOfTopLevelItem(pSource));
qDebug()<<"source = "<<pSource->text(0)<<endl;
void DragTreeWidget::mouseReleaseEvent(QMouseEvent *ev)
qDebug()<<"in mouseReleaseEvent"<<endl;
label.hide();
QTreeWidgetItem* pTarget = itemAt(ev->pos());
if(pTarget==nullptr){
if(pParent){
pParent->insertChild(originIndex,pSource);
else{
addTopLevelItem(pSource);
setCurrentItem(pSource);
return;
// qDebug()<<"is child = "<<isChild<<endl;
if(pTarget->parent()){
qDebug()<<"PTarget parent = "<<pTarget->parent()->text(0)<<endl;
//如果是父节点
if(pTarget->parent()==nullptr){
if(pParent){
pTarget->addChild(pSource);
else{
insertTopLevelItem(indexOfTopLevelItem(pTarget)+1,pSource);
//如果是子节点
else{
if(pParent){
QTreeWidgetItem* parent = pTarget->parent();
parent->insertChild(parent->indexOfChild(pTarget)+1,pSource);
else{
setCurrentItem(pSource);
public class Calculator {
public static void main(String[] args) {
System.out.println("只支持整数计算,并且一次输入一个字符!");
Scanner scanner1 = new Scanner(System.in)
python画2维数组 python写二维数组
之前学C/C++建二维数组就是直接写,python就必须要自己建立建立一个m行n列的数组寻址方式:test2[ i ][ j ]为test2这个列表的第 i 行 j 列(字符串可以像数组一样直接下标寻址)#直接建
test1 = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
# 列表生成
test2 = [[0] * n for i in range(m)]
test4 =