我们在编写文本编辑器的时候,可能会希望其具有支持这种功能,将文件直接拖入文本编辑器打开。
使用方法
- 1.包含头文件
//拖拽事件
#include <QDragEnterEvent>
//放下事件
#include <QDropEvent>
- 2.在类中加上如下声明
- 1)void dragEnterEvent(QDragEnterEvent *event);
- 2)void dropEvent(QDropEvent *event);
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
//复写”拖拽事件“函数
void dragEnterEvent(QDragEnterEvent *event);
//复写”放下事件“函数
void dropEvent(QDropEvent *event);
};
- 3.在类的构造函数中设置接受drop事件
//拖拽事件, 也就是可以直接将要打开的文件, 拖入此窗口打开
this->setAcceptDrops(true);
- 4.复写“拖拽事件”函数
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
if(event->mimeData()->hasUrls())
{
event->acceptProposedAction();
}
else
{
event->ignore();
}
}
- 5.复写“放下事件”函数
void MainWindow::dropEvent(QDropEvent *event)
{
const QMimeData *mimeData = event->mimeData();
if(!mimeData->hasUrls())
{
return;
}
QList<QUrl> urlList = mimeData->urls();
//如果同时拖入了多个资源,只选择一个
QString fileName = urlList.at(0).toLocalFile();
if(fileName.isEmpty())
{
return;
}
//打开拖入的文件
QFile file(fileName);
if(!file.open(QIODevice::ReadOnly))
{
QMessageBox::information(this, "错误", file.errorString(), QMessageBox::Ok);
return;
}
//将文件内容放入文本框
QByteArray ba;
ba = file.readAll();
ui->textEdit->setText(QString(ba));
}
- 6.效果
- 1)拖入mainWindow,也就是我的主窗口
这表示是成功的,注意这里拖入的是mainWindow - 2)拖入textEdit和mainWindow的重叠区域
这里显然是失败的,为什么会这样?
- 1)拖入mainWindow,也就是我的主窗口
- 7.分析
查看官方帮助文档,关于setAcceptDrops(bool on)有如下说明:
acceptDrops : bool
This property holds whether drop events are enabled for this widget
Setting this property to true announces to the system that this widget may be able to accept drop events.
If the widget is the desktop (windowType() == Qt::Desktop), this may fail if another application is using the desktop; you can call acceptDrops() to test if this occurs.
Warning: Do not modify this property in a drag and drop event handler.
By default, this property is false.
Access functions:
bool acceptDrops() const
void setAcceptDrops(bool on)
关键的地方是:设置这个属性有可能会失败
我的窗口里面有一个textEdit,textEdit也能接受drop事件,怀疑可能是这个原因
- 8.解决
我在构造函数将textEdit接受drop事件禁用掉
//禁用textEdit的拖拽事件
ui->textEdit->setAcceptDrops(false);
至此,能愉快的拖放了。
- 9.总结
1.这里只是打开了mainWindow接受drop事件,而没有打开textEdit接受drop事件。
2.就drop事件来说,默认是关闭的。
3.为什么textEdit的drop事件也被开启了,导致mainWindow的drop事件没触发。
4.怀疑“事件过滤器”在mainWindow/widget等窗口控件上,设置接受某个事件后,窗口上的子控件也能接受该事件。
5.如果想只是触发mainWindow的事件,而子部件不需要,则需要将子部件该事件禁用掉。