Qt中提供了以QMainWindow类为核心的主窗口框架,它包含了众多相关的类,它们的继承关系如下:
主窗口框架
主窗口为建立应用程序用户界面提供了一个框架,Qt提供了QMainWindow和其他一些相关的类共同完成主窗口的管理。QMainWindow类拥有自己的布局,包含以下组件:
①菜单栏(QMenuBar):包含一个下拉菜单项的列表,这些菜单项由QAction动作类。菜单栏位于主窗口的顶部,一个主窗口只能有一个菜单栏。
②工具栏(QToolBar):工具栏一般用于显示一些常用的菜单项目,也可以插入其他窗口部件,并且是可以移动的。一些主窗口可以拥有多个工具栏。
③中心部件(Central Widget):在主窗口的中心区域可以放入一个窗口部件作为中心部件,是应用程序的主要功能实现区域。一个主窗口只能拥有一个中心部件。
④Dock部件(QDock Widget):Dock部件常被称为停靠窗口,因为可以停靠在中心部件的四周,用来放置一些部件来实现一些功能,就像个工具箱一样。一个主窗口可以拥有多个Dock部件。
⑤状态栏(QStatusBar):状态栏用于显示程序的一些状态信息,在主窗口的最底部。一个主窗口只能拥有一个状态栏。
Qt资源系统、菜单栏和工具栏
1.资源的使用
当图片放在可执行程序外部且图片位置发生变化时,程序将无法显示图片,这里可以使用Qt的资源系统来存储图片,就可以嵌入到可执行文件之中了。步骤如下:
①添加Qt资源文件。往项目中添加新文件,选择Qt分类中的Qt Resource File,文件名改为myimages,其他选项默认即可。
②添加资源。建立好资源文件后会默认进入资源管理界面,打开myiamges.qrc文件。先到项目文件夹mymainwindow中新建一个名为images的文件,并在其中放入两张图标图片,比如放入了一个new.png和一个open.png图片。然后回到Qt Creator中,在资源管理界面单击“添加”按钮,选择"添加前缀",然后将其属性栏中的前缀改"/image",再单击“添加”按钮选择“添加文件”,在弹出的对话框中进入到前面新建的image文件夹中,选中那两张图片,单击"打开"即可。这时myimages.qrc文件中救出回西安了添加的图片列表。最后按下Ctrl+S快捷键保存对文件的修改。
③使用图片。先使用Ctrl+Tab快捷键转到mainwindow.ui文件,回到设计模式。在Action编辑器中双击"新建文件"动作,这时会弹出编辑动作对话框,将对象名称改为action_New,工具提示ToolTip改为“新建文件”,然后摁下“图标”后面的按钮进入选择资源界面。第一次进入该界面时,如果没有显示可用的资源,则可以单击左上角的重新加载绿色箭头图标,这时图片资源就显示出来了。这里选择new.png图片并单击OK按钮,最后在快捷键Shortcut后面的输入栏上单击并摁下Ctrl+N组合键,就可以将它设为这个动作的快捷键了。这样就为动作添加了图标和快捷键,单击OK按钮关闭对话框。因为设置了工具提示,所以运行程序时可以将鼠标停在工具栏的一个动作上来显示提示信息。
前面在使用资源时添加的qrc资源文件其实是一个XML格式的文本文件,现在进入编辑模式,在myimages.qrc文件上右击,在弹出的级联菜单中选择"Open With->普通文本编辑器",这时就会看到myimage.qrc的内容,这里指明了文件类型为RCC,表明是Qt资源文件。然后是资源前缀,其下面罗列了添加的图片路径。如果在编写代码时要使用new.png图片,那么就可以将其路径指定为“:/image/images/new.png”,这样就表明在使用资源文件中的图片;其中添加的前缀“/image”只是用来表明这是图片资源,可以改为别的名字,也可以为空。
往项目中添加了一个资源文件时,会自动往工程文件mymainwindow.pro中添加代码:
RESOURCES +=
myimages.qrc
这表明项目中使用了资源文件myimages.qrc。在前面的过程中这是自动生成的,但是如果时自己添加的已有的资源文件,要想在项目中使用,那么就要手动添加这行代码。其实资源可以是任意类型的,不只是图片文件。编译时会对加入的资源进行自动压缩,这也就是为什么有时生成的release版本可执行文件比添加进去的资源还要小的原因。
2.编写代码方式添加菜单
前面在设计器中添加了文件菜单,然后添加了新建文件子菜单,其实这些都可以使用代码来实现。下面使用代码来添加一个菜单:
QMenu *editMenu = ui->menuBar->addMenu(tr(“编辑(&E)”)); //添加编辑菜单
QAction *action_Open = editMenu ->addAction(QIcon(":/image/images/new.png"),tr(“打开文件(&O)”));//添加打开菜单
action_Open->setShortcut(QKeySequence(“Ctrl+O”); //设置快捷键
ui->mainToolBar->addAction(action_Open);//在工具栏中添加动作
3.菜单栏
QMenuBar类提供了一个水平的菜单栏,在QMainWindow中可以直接获取默认的菜单栏,向其中添加QMenu类型的菜单对象,然后向弹出的菜单中添加QAction类型的动作对象作为菜单项。QMenu中还提供了间隔器,可以在设计器中添加菜单那样直接添加间隔器,或者在代码中使用addSeparator()函数来添加,它是一条水平线,可以将菜单进行分组,使得布局很整齐。应用程序中很多普通的命令都是通过菜单来实现的,而我们也希望能将这些菜单命令放到工具栏中以方便使用。QAction就是这样一个命令动作,可以同时放在菜单和工具栏中。一个QAction做东包含了图标、菜单显示文本、快捷键、状态栏显示文本、"What’s This?"显示文本和工具显示文本,这些都可以在构建QAction类对象时在构造函数中指定。另外,还可以设置QAction的checkable属性,如果指定这个动作的checkable为true,那么选中这个菜单时就会在它的前面显示“√”之类的表示选中状态的符号;如果该菜单有图标,就会用线框将图标围住,,用来表示该动作被选中了。
QActionGroup类可以包含一组动作QAction,可以设置这组动作中是否只能有一个动作处于选中状态,这对于互斥型动作很有用。代码如下:
QActionGroup *group = new QActionGroup(this);//建立动作组
QAction *action_L=group->addAction(tr(“左对齐(&L)”));//向动作组中添加动作
action_L->setCheckable(true);//设置动作checkable属性为true;
QAction *action_R = group->addAction(tr(“右对齐(&R)”));
action_R->setCheckable(true);
QAction *action_C = group->addAction(tr(“居中(&C)”));
action_C->setCheckable(true);
action_L->setChecked(true);//最后指定action_L为选中状态
editMenu->addSeparator();//向菜单中添加间隔器
editMenu->addAction(action_L);//向菜单中添加动作
editMenu->addAction(action_R);
editMenu->addAction(action_C);
4.工具栏
工具栏QToolBar类提供了一个包含了一组控件的、可以移动的面板。前面已经看到可以将QAction对象添加到工具栏中,默认只是显示一个动作的图标,可以在QToolBar的属性栏中进行更改。在前面QAction对象添加到工具栏中,默认只是显示一个动作的图标,可以在QToolBar的属性栏中进行更改。在设计器查看QToolBar的属性栏,其中,toolButtonStyle属性用来设置图标和相应文本的显示及其相对位置;movabel属性用来设置状态栏是否可以移动;allowedArea用来设置允许停靠的位置;iconsize属性用来设置图标的大小;floatable属性用来设置是否可以悬浮。
工具栏中除了可以添加动作外,还可以添加其它的窗口部件,代码如下:
QToolButton *toolBtn = new QToolButton(this);//创建QToolButton
toolBtn->setText(tr(“颜色”));
QMenu *colorMenu = new QMenu(this);//创建一个菜单
colorMenu->addAction(tr(“红色”));
colorMenu->addAction(tr(“绿色”));
toolBtn->setMenu(colorMenu);//添加菜单
toolBtn->setPopupMode(QToolButton::MenuButtonPopup);//设置弹出模式
ui->mainToolBar->addWidget(toolBtn);//向工具栏添加QToolButton按钮
QSpinBox *spinBox = new QSpinBox(this);//创建QSpinBox;
ui->mainToolBar->addWidget(spinBox);//向工具栏添加QSpinBox部件
这里需要注意的是QToolButton类,其实当往工具栏中添加一个QAction类对象时就回自动创建一个QToolButton实例,所以说工具栏上的动作就是一个QToolButton,这就是属性栏会有toolButtonStyle的原因。
中心部件
主窗口的中心区域可以放置一个中心部件,它一般是一个编辑器或者浏览器。这里支持单文档部件,也支持多文档部件。一般的,我们会在这里放置一个部件,然后使用布局管理器使其充满整个中心区雪,并可以随窗口的大小变化而变化。
下面开始在设计模式里进行实例操作:在设计模式中,往中心区域拖入一个Text Edit,然后单击界面,按下Ctrl+G,使其处于一个栅格布局中。
QTextEdit是一个高级的WYSIWYG(所见即所得)浏览器和编辑器,支持富文本的处理,为用户提供了强大的文本编辑功能。而与QTextEdit对应的是QPlainTextEdit类,它提供了一个纯文本编辑器,这个类与QTextEdit类的很多功能都很相似,只不过无法处理富文本。还有一个QTextBrowser类,它是一个富文本浏览器,可以看作是QTextEdit的只读模式。
中心区域还可以使用多文档部件。Qt中的QMdiArea部件就是用来提供一个可以显示MDI(Multiple Document Interface)多文档界面的区域,从而有效地管理多个窗口。QMdiArea中地子窗口由QMdiSubWindow类提供,这个类有自己的布局,包含一个标题栏和一个中心区域,可以向它的中心区域添加部件。
下面开始进行实例操作:首先在设计模式中拖入一个MDI Area部件,在Action编辑器中的“新建文件”动作上右击,在弹出地级联菜单中选择“转到槽”,然后在弹出地对话框中选择triggered()触发信号,单击OK按钮后便转到mainwindow.cpp文件中的该信号的槽的定义出,更改如下:
void MainWindow::on_action_New_triggered()
{
QTextEdit *edit = new QTextEdit(this);//新建文本编辑器部件
QMdiSubWindow *child = ui->mdiArea->addSubWindow(edit);//使用QMdiArea类的addSubWindow()函数创建子窗口,以文本编辑器为中心部件
child->setWindowTitle(tr(“多文档编辑器子窗口”));
child->show();
}
Dock部件
Dock部件又叫做停靠窗口,可以停靠在QMainWindow中,也可以悬浮起来作为桌面顶级窗口,由QDockWidget类提供。Dock部件一般用于存放一些其他部件来实现特殊功能,就像一个工具箱。在主窗口中可以停靠在中心部件的四周,也可以悬浮起来被拖动到任意的地方,还可以被关闭或隐藏起来。一个Dock部件包含一个标题栏和一个内容区域,可以向Dock部件中放入任何部件。
在设计模式中向中心区域拖入一个Dock Widget部件,然后再向Dock中随意拖入几个部件,比如这里拖入一个Push Button和一个Font Combo Box。在DockWidget的属性栏中更改其windowTitle为“工具箱”,另外还可以设置它的features属性,包含是否可以关闭、移动和悬浮等;还有allowedArea属性,用来设置可以停靠的区域。
具体的实例操作为:在文件菜单中添加“显示Dock”菜单项,然后在Action编辑器中转到“显示Dock”动作的触发信号triggered()的槽函数,更改如下:
void MainWindow::on_action_Dock_triggered()
{
ui->dockWidget->show();
}
状态栏
QStatusBar类提供了一个水平条部件,用来显示状态信息。QMainWindow中默认提供一个状态栏。状态信息可以被分为3类:临时信息,如一般的提示信息;正常信息,如显示页数和行号;永久信息,如显示版本号或日期。可以使用showMessage()函数显示一个临时信息,它会出现状态栏的最左边。一般用addWidget()函数添加一个QLable到状态栏上,用于显示正常信息,他会生成到状态栏的最左边,可能被临时消息掩盖。如果要显示永久信息,则要使用addPermanentWidget()函数来添加一个QLabel一样的可以显示消息的部件,它会生成在状态栏的最右端,不会被临时消息掩盖。状态栏的最右端还有一个QSizeGrip部件,用来调整窗口的大小,可以使用setSizeGripEnabled()函数来禁用它。使用样例为:
ui->statusBar->showMessage(tr(“欢迎使用多文档编辑器”),2000);//显示临时消息,显示2000毫秒即2秒
//创建标签,设置标签样式并显示信息,然后以永久部件的形式添加到状态栏
QLabel *permanent = new QLabel(this);
permanent->setFrameStyle(QFrame::Box|QFrame::Sunken);
permanent->setText(“www.qter.org”);
ui->statusBar->addPermanentWidget(permanent);
自定义菜单
为了实现自定义菜单,需要新建一个类,它继承自QWidgetAction类,并且在其中重新实现createWidget()函数。下面的例子中实现了这样一个菜单项:包含一个标签和一个行编辑器,可以在行编辑器中输入字符串,按下回车键就可以自动将字符串输入到中心部件文本编辑器中。 点此查看例子
富文本处理
富文本(Rich Text)或者较富文本格式,简单来说就是在文档中可以使用多种格式,比如字体颜色、图片和表格等。它是与纯文本(Plain Text)相对而言的,比如Windows上的记事本就是纯文本编辑器,而Word就是富文本编辑器。Qt中提供了对富文本处理的支持,可以在帮助中通过Rich Text Processing关键字查看,那里详细讲解了富文本处理的相关内容。
富文本文档结构
Qt对富文本的处理分为编辑操作和只读操作两种方式。编辑操作使用基于光标的一些接口函数,更好地模拟了用户地编辑操作,更加容易理解,而且不会丢失底层的文档框架;而对于文档结构的概览,则使用了只读的分层次的接口函数,有利于文档的检索和输出。可见,对于文档的读取和编辑要使用不同的两组接口。文档的光标主要基于QTextCursor类,而文档的框架主要基于QTextDocument类。一个富文本文档的结构分为几种元素来表示,分别是框架(QTextFrame)、文本块(QTextBlock)、表格(QTextTable)和列表(QTextList)。每种元素的格式又使用相应的format类来表示,分别是框架格式(QTextFrameFormat)、文本块格式(QTextBlockFormat)、表格格式(QTextTableFormat)和列表格式(QTextListFormat)。这些格式一般在编辑文档时使用,所以常和QTextCursor类配合使用。QTextEdit类就是一个富文本编辑器,所以在构建QTextEdit类的对象就已经构建了一个QTextDocument类对象和一个QTextCursor类对象,只需调用它们进行相应的操作即可。
一个空的文档包含了一个根框架(Root frame),这个跟框架又包含了一个空的文本块(Block)。框架将一个文档分为多个部分,在根框架里可以再添加文本块、子框架和表格等,文档结构图如下:
使用样例:在设计界面拖入一个Text Edit部件之后在MainWindow类的构造函数中添加如下代码:
QTextDocument* document = ui->textEdit->document();//获取文档对象
QTextFrame* rootFrame = document->rootFrame(); //获取根框架
QTextFrameFormat format; //创建框架格式
format.setBorderBrush(Qt::red); //边界颜色
format.setBorder(3); //边界宽度
rootFrame->setFrameFormat(format);
//使用光标类对象,在根框架中再添加一个子框架
QTextFrameFormat frameFormat;
frameFormat.setBackground(Qt::lightGray); //设置背景颜色
frameFormat.setMargin(10); //设置边距
frameFormat.setPadding(5); //设置映衬
frameFormat.setBorder(2); //边界宽度
frameFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Dotted);//设置边框样式
QTextCursor cursor = ui->textEdit->textCursor(); //获取光标
cursor.insertFrame(frameFormat);//在光标处插入框架
文本块
文本块QTextBlock类为文本文档QTextDocument提供了一个文本片段(QTextFragment)的容器。一个文本块可以看作一个段落,但是不能使用回车换行,因为一个回车换行就表示创建一个新的文本块。QTextBlock提供了只读接口,是前面提到的文档分层次的接口的一部分,如果QTextFrame看作一层,那么其中的QTextBlock就是另一层。文本块的格式由QTextBlockFormat类来处理,他主要涉及对齐方式、文本块四周边距、缩进等内容。而文本快的文本内容的格式,比如字体大小、加粗、下划线等,由QTextCharFormat类来设置。
表格、列表与图片
在编辑器中插入表格、列表和图片的例子为:
void MainWindow::insertTable() //插入表格
{
QTextCursor cursor = ui->textEdit->textCursor();
QTextTableFormat format;//表格格式
format.setCellSpacing(2);//表格外边白
format.setCellPadding(10);//表格内边白
cursor.insertTable(2,2,format);//插入2行2列表格
}
void MainWindow::insertList()//插入列表
{
QTextListFormat format;//列表格式
format.setStyle(QTextListFormat::ListDecimal);//数字编号
ui->textEdit->textCursor().insertList(format);
}
void MainWindow::insertImage()//插入图片
{
QTextImageFormat format;//图片格式
format.setName(“E:/yanyanyan/lianxi/untitled6/1.png”);//图片路径
ui->textEdit->textCursor().insertImage(format);
}
查找功能
其实像字体格式设置等操作完全可以在QTextEdit类中直接进行。QTextEdit类提供了很多方便的函数,比如常用的复制、粘贴操作、撤销、恢复操作,放大、缩小操作等。关于这些使用起来非常简单,只需调用一个函数即可。接下来介绍文本查找功能,它使用的是QTextEdit类的find()函数。选项QTextDocument::FindBackward表示向后查找;默认的是向前查找;另外还有QTextDocument::FindCaseSensitively表示不区分大小写;QTextDocument::FindWholeWords表示匹配整个单词。其实QTextEdit中的find()函数只是为了方便使用而设计的,更多的查找功能可以使用QTextDocument类的find()函数,它有几种形式可以u西安则,其中还可以使用正则表达式。
QString string = lineEdit->text();
//使用查找函数查找指定字符串,查找方式为向后查找
bool isfind = ui->textEdit->find(string,QTextDocument::FindBackward);
if(isfind)
{
qDebug()<<tr(“行号:%1列号:%2”).arg(ui->textEdit->textCursor().blockNumber()).arg(ui->textEdit->textCursor().columnNumber());
}
}
语法高亮与HTML
使用Qt Creator编辑代码时可以发现,输入关键字时会显示不同的颜色,这就是所谓的语法高亮。Qt的富文本处理中提供了QSyntaxHighlighter类来实现语法高亮。为了实现这个功能,需要创建QSyntaxHighlighter类的子类,然后重新实现highBlock()函数,使用时直接将QTextDocument类对象指针作为其父部件指针,这样就可以直接自动调用highlightBlock()函数。其中highlightBlock()函数的样例为:
void MySyntaxHighlighter::highlightBlock(const QString &text)
{
QTextCharFormat myFormat;//字符格式
myFormat.setFontWeight(QFont::Bold);
myFormat.setForeground(Qt::green);
QString pattern ="\bchar\b"; //要匹配的字符,这里是“char”单词
QRegExp expression(pattern); //创建正则表达式
int index = text.indexOf(expression); //从位置0开始匹配字符串
while(index >=0)
{
int length = expression.matchedLength(); //要匹配字符串的长度
setFormat(index,length,myFormat); //对要匹配的字符串设置格式
index = text.indexOf(expression,index +length); //继续匹配
}
}
对于语法高亮,可以查看Syntax Highlighter Example示例程序。在富文本处理中还提供了对HTML子集的支持,可以在QLabel或者QTextEdit添加文本时使用HTML标签或者CSS属性,具体内容可以在帮助中心通过Supported HTML Subset关键字查看,下面举个例子,在mainwindow.cpp文件中的构造函数最后添加下面一行代码:
拖放功能
对于一个实用的应用程序,不仅希望能从文件菜单中打开一个文件,更希望可以通过拖动,直接将桌面上的文件拖入程序界面来打开,就像将源文件拖入Qt Creator中一样。Qt提供了强大的拖放功能,可以在帮助中通过Drag and Drop关键字查看。拖放操作分为拖放(Drag)和放下(Drop)两种操作,当数据拖动时会被存储为HIME(Multipurpose Internet Mail Extensions)类型。Qt中使用QMimeData类表示MIME类型的数据,并使用QDrag类来完成数据的转移,而整个拖放操作都是在几个鼠标事件和拖放事件中完成的。
使用拖放打开文件
下面举一个将桌面上的.txt文本文件拖入程序将其内容复制进创建出的TextEdit中例子。当鼠标拖拽一个数据进入主窗口时,就会触发dragEnterEvent()事件处理函数,从而获取其中的MIME数据;然后查看它是否包含URL路径,因为拖入的文本文件实际上就是拖入了它的路径,这就是event->mimeData()->hasUrls()实现的功能。如果有这样的数据就接收它,否则忽略该事件。QMimeData类中提供了几个人函数来处理产挺管用的MIME数据,如下表。当松开鼠标左键,将数据放入主窗口时就会触发dropEvent()事件处理函数,这里获取MIME数据中的URL列表。因为拖入的只有一个文件,所以获取了列表中的第一个条目,并使用toLocalFile()函数将它转换为本地文件路径,然后使用QFile和QTextStream将文件中的数据读入编辑器中。
//拖放进入事件
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
if(event->mimeData()->hasUrls()) //数据中是否包含URL
event->acceptProposedAction(); //如果是则接收动作
else
event->ignore(); //否则忽略该事件
}
//放下事件
void MainWindow::dropEvent(QDropEvent *event)
{
const QMimeData *mimeData = event->mimeData(); //获取MIME数据
if(mimeData->hasUrls()) //如果数据中包含URL
{
QListurlList = mimeData->urls();
//将其中第一个URL表示为本地文件路径
QString fileName = urlList.at(0).toLocalFile();
if(!fileName.isEmpty()) //如果文件路径不为空
{
QFile file(fileName); //建立QFile对象并且以只读方式打开该文件
if(!file.open(QIODevice::ReadOnly))
return;
QTextStream in(&file); //建立文本流对象
ui->textEdit->setText(in.readAll()); //将文件中所有内容读入编辑器
}
}
}
以下是常用MIME类型数据处理函数
测试函数 | 获取函数 | 设置函数 | MIME类型 |
---|---|---|---|
hasText() | text() | setText() | text/plain |
hasHtml() | html() | setHtml() | text/html |
hasUrls() | urls() | setUrls() | text/uri-list |
hasImage() | imageData() | setImageData() | image/* |
hasColor() | ColorData() | setColorData() | application/x-color |
自定义拖放操作
下面实现的功能就是在窗口中有一张照片可以随意拖动它。这里需要使用到自定义的MIME类型。鼠标按下时会触发鼠标按下事件,进而执行其处理函数。然后是拖动进入事件,如果有我们定义的MIME类型数据,则进行移动操作,然后是拖动事件,最后是放下事件,使用字节数组获取拖放的数据,然后将其中的图片数据和位置读取到两个变量中,并使用它们来设置新建的标签。
void MainWindow::mousePressEvent(QMouseEvent *event)
{
//第1步:获取图片
//将鼠标指针所在位置的部件强制转换为QLabel类型
QLabel child = static_cast<QLabel>(childAt(event->pos()));
//如果不见不是QLabel则直接返回
if(!child->inherits(“QLabel”))
return;
QPixmap pixmap = *child->pixmap();//获取QLabel中的图片
//第2步:自定义MIME类型
QByteArray itemData;
QDataStream dataStream(&itemData,QIODevice::WriteOnly); //创建数据流
//将图片信息,位置信息输入到字节数组中
dataStream<<pixmap<<QPoint(event->pos()-child->pos());
//第3步:将数据放入QMimeData中
QMimeData *mimeData = new QMimeData; //创建QMimeData用来存放要移动的数据
//将字节数组放入QMimeData中,这里的MIME类型是我们自己定义的
mimeData->setData(“myimage/png”,itemData);
//第4步:将QMimeData数据放入QDrag中
QDrag *drag = new QDrag(this); //创建QDrag,它用来移动数据
drag->setMimeData(mimeData);
drag->setPixmap(pixmap); //在移动过程中显示图片,若不设置则默认显示一个小矩形
drag->setHotSpot(event->pos()-child->pos()); //拖动时鼠标指针的位置不变
//第5步:给原图片添加阴影
QPixmap tempPixmap =pixmap; //使原图片添加阴影
QPainter painter;
painter.begin(&tempPixmap);
//在图片的外接矩形中添加一层透明的淡黑色形成阴影效果
painter.fillRect(pixmap.rect(),QColor(127,127,127,127));
painter.end();
child->setPixmap(tempPixmap);//在移动图片过程中,让原图片添加一层黑色阴影
//第6步:执行拖放操作
//设置拖放可以是移动和复制操作,默认是复制操作
if(drag->exec(Qt::CopyAction|Qt::MoveAction,Qt::CopyAction)==Qt::MoveAction)
child->close();//如果是移动操作,那么拖放完成后关闭原标签
else {
child->show();//如果是复制操作,那么拖放完成后显示标签
child->setPixmap(pixmap);//显示原图片,不再使用阴影
}
}
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
//如果有我们定义的MIME类型数据,则进行移动操作
if(event->mimeData()->hasFormat(“myimage/png”))
{
event->setDropAction(Qt::MoveAction);
event->accept();
}
else {
event->ignore();
}
}
void MainWindow::drapMoveEvent(QDragMoveEvent *event)
{
if(event->mimeData()->hasFormat(“myimage/png”))
{
event->setDropAction(Qt::MoveAction);
event->accept();
}
else {
event->ignore();
}
}
void MainWindow::dropEvent(QDropEvent *event)
{
if(event->mimeData()->hasFormat(“myimage/png”))
{
QByteArray itemData = event->mimeData()->data(“myimage/png”);
QDataStream dataStream(&itemData,QIODevice::ReadOnly);
QPixmap pixmap;
QPoint offset;
//使用数据流将字节数据中的数据读入到QPixmap和QPoint变量中
dataStream>>pixmap>>offset;
//新建标签,为其添加照片,并根据图片大小设置标签的大小
QLabel *newLabel = new QLabel(this);
newLabel->setPixmap(pixmap);
newLabel->resize(pixmap.size());
//让图片移动到放下的位置,不设置的话,图片会默认显示在(0,0)点,即窗口左上角
newLabel->move(event->pos()-offset);
newLabel->show();
newLabel->setAttribute(Qt::WA_DeleteOnClose);
event->setDropAction(Qt::MoveAction);
event->accept();
}
else {
event->ignore();
}
}
打印文档
Qt5中的Qt Print Support模块提供了对打印的支持。最简单的,只需要使用一个QPrinter类和一个打印对话框QPrintDialog类就可以完成文档的打印操作。可以在帮助中通过Qt Print Support关键字查看。
现在简单介绍一个例子:
void MainWindow::doPrint()
{
QPrinter printer; //创建打印机对象
QPrintDialog dlg(&printer,this);//创建打印对话框
//如果编辑器中有选中区域,则打印选中区域
if(ui->textEdit->textCursor().hasSelection())
dlg.addEnabledOption(QAbstractPrintDialog::PrintSelection);
//如果在对话框中按下了打印大牛,则执行打印操作
if(dlg.exec() == QDialog::Accepted)
ui->textEdit->print(&printer);
}
void MainWindow::doPrintPreview()
{
QPrinter printer;
QPrintPreviewDialog preview(&printer,this);//创建打印预览对话框
//当要生成预览页面时,发射paitRequested()信号
connect(&preview,&QPrintPreviewDialog::paintRequested,this,&MainWindow::printPreview);
preview.exec();
}
void MainWindow::printPreview(QPrinter printer)
{
ui->textEdit->print(printer);
}
void MainWindow::createPdf()
{
QString fileName = QFileDialog::getSaveFileName(this,tr(“导出PDF文件”),QString(),".pdf");
if(!fileName.isEmpty())
{
if(QFileInfo(fileName).suffix().isEmpty())
{
fileName.append(".pdf");//如果文件后缀为空,则默认使用.pdf
}
QPrinter printer;
printer.setOutputFormat(QPrinter::PdfFormat);//指定输出格式为pdf
printer.setOutputFileName(fileName);
ui->textEdit->print(&printer);
}
}