QtCreator学习(3)

应用程序主窗口

应用程序主窗口关系图:
主窗口关系图

主窗口框架

主窗口为建立应用程序用户界面提供了一个框架,Qt提供了QMainWindow和其他一些相关类共同完成主窗口的管理。QMainWindow类拥有自己的布局,包含以下部件:

  • 菜单栏(QMenuBar)。菜单栏包含了一个下拉菜单项的列表,这些菜单项由QAction动作类实现。菜单栏位于主窗口的顶部,一个主窗口只能有一个菜单栏。
  • 工具栏(QToolBar)。工具栏一般用于显示一一些常用的菜单项目,也可以插入其他窗口部件,并且是可以移动的。一个主窗口可以拥有多个工具栏。
  • 中心部件(Central Widget)。在主窗口的中心区域可以放入一个窗口部件作为中心部件,是应用程序的主要功能实现区域。一个主窗口只能拥有一个中心部件。
  • Dock部件(QDockWidget)。Dock 部件常被称为停靠窗口,因为可以停靠在中心部件的四周,用来放置- -些部件来实现- -些功能,就像个工具箱一样。一个主窗口可以拥有多个Dock部件。
  • 状态栏(QStatusBar)。状态栏用于显示程序的一.些状态信息,在主窗口的最底部。一个主窗口只能拥有一个状态栏。
    主窗口界面布局

    本节知识可以在帮助索引中通过Application Main Window关键字查看。

Qt资源系统、菜单栏和工具栏

新建Qt Widgets应用,项目名称mymainwindow ,类名默认为MainWindow,基类默认为QMainWindow,不改动。建立好项目后,在文件列表中双击mainwindow. ui文件进人设计模式,这时在设计区域出现的便是主窗口界面。下面来添加菜单,双击左上角的“在这里输人”,修改为“文件(&F)”,这里要使用英文半角的括号,“&F”被称为加速键,表明程序运行时可以按下Alt+F键来激活该菜单。修改完成后按下回车键,并在弹出的下拉菜单中将第一项改为“新建文件(&N)”,并按下回车键(由于版本原因,如果这里无法直接输人中文,则可以通过复制粘贴完成),这时可以看到,下面的Action编辑器中已经有了“新建文件”动作。选中该动作并将其拖入菜单栏下面的工具栏中。运行程序
为菜单添加图标:

  1. 使用资源
    这里将使用Qt的资源系统来存储图片,就可以嵌人到可执行文件之中了。避免图片位置发生变化,程序将无法显示图片这个问题。步骤如下:
  • 添加Qt资源文件。往项目中添加新文件,选择Qt分类中的Qt ResourceFile,文件名称改为myimages,其他选项默认即可。
  • 添加资源。建立好资源文件后会默认进人资源管理界面,打开myimages.qrc文件。现在先到项目文件夹mymainwindow中新建一个名为images的文件夹,并在其中放人两张图标图片,比如放人了一个new. png和一个open. png图片。(注意:Qt资源系统要求资源文件必须放在与qre文件同级或子级目录下,如果放在其他地方,则添加资源时会提示将文件复制到有效的位置。)
  • 回到QtCreator中,在资源管理界面单击“添加”按钮,选择“添加前缀”,然后将属性栏中的前缀改为“/image”,再单击“添加”按钮选择添加文件”,在弹出的对话框中进人到前面新建的images文件夹中,选中那两张图片,单击“打开”即可。这时myimages. qre文件中就出现了添加的图片列表。最后,按下Ctrl+S快捷键保存对文件的修改(注意:这一点很重要,如果没有保存,下面使用图片时将看不到图片)。
  • 使用图片。先使用Ctrl+ Tab快捷键转到mainwindow. ui文件.回到设计模式(如果先前没有打开过mainwindow. ui文件,那么该快捷键无法切换,需要直接双击该文件进行打开)。在Action编辑器中双击“新建文件”动作,这时会弹出编辑动作对话框。将对象名称改为action_New,工具提示ToolTip改为“新建文件”,然后按下“图标”后面的按钮进人选择资源界面。第一次进入该界面时,如果没有显示可用的资源,则可以单击左上角的重新加载绿色箭头图标 ,这时图片资源就显示出来了。这里选择new.png图片并单击OK按钮。最后在快捷键Shortcut后面的输入栏上单击并按下Ctrl+N组合键.就可以将它设为这个动作的快捷键了。这样就为动作添加了图标和快捷键,单击OK按钮关闭对话框。因为设置了工具提示,所以运行程序时可以将鼠标停在工具栏的一个动作上来显示提示信息。
  1. 编写代码方式添加菜单
    下面使用代码来添加一个菜单,在mainwindow. cpp文件的MainWin-dow类构造函数中添加代码:

    1
    2
    3
    4
    5
    6
    7
    8
    QMenu *editMenu=ui->menuBar->addMenu(tr("编辑(&E)"));            //添加编辑菜单
    QAction *action_Open=editMenu->addAction(
    QIcon(":/image/images/open.png"),tr("打开文件(&O)")); //添加打开菜单
    QAction *action_Open2=editMenu->addAction(
    QIcon(":/image/images/open.png"),tr("删除文件(&D)"));
    action_Open->setShortcut(QKeySequence("ctrl+O")); //设置快捷键
    ui->mainToolBar->addAction(action_Open); //在工具栏中添加动作
    ui->mainToolBar->addAction(action_Open2);

    这里使用ui→menuBar来获取QMainWindow的菜单栏,使用ui→mainToolBar来获取QMainWindow的工具栏,然后分别使用相应的函数添加菜单和动作

  2. 菜单栏
    QMenu中还提供了间隔器.可以在设计器中向添加菜单那样直接添加间隔器,或者在代码中使用addSeparator()函数来添加,它是一条水平线,可以将菜单进行分组,使得布局很整齐。应用程序中很多普通的命令都是通过菜单来实现的,而我们也希望能将这些菜单命令放到工具栏中以方便使用。QAction 就是这样一种命令动作,可以同时放在菜单和工具栏中。一个QAction动作包含了图标、菜单显示文本、快捷键、状态栏显示文本、“What’s This?”显示文本和工具提示文本。这些都可以在构建QAction类对象时在构造函数中指定。另外,还可以设置QAction的checkable属性,如果指定这个动作的checkable为true,那么选中这个菜单时就会在它的前面显示小圆点之类的表示选中状态的符号;如果该菜单有图标.就会用线框将图标围住.用来表示该动作被选中了。
    下面再介绍一个动作组QActionGroup类。它可以包含一组动作QAction,可以设置这组动作中是否只能有一个动作处于选中状态,这对于互斥型动作很有用。在前面程序的MainWindow类构造函数中继续添加如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
QActionGroup *group=new QActionGroup(this);           //建立动作组
QAction *action_L=group->addAction(tr("左对齐(&L)")); //向动作组中添加动作
action_L->setCheckable(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);
  1. 工具栏
    工具栏QToolBar类提供了一-个包含了一组控件的、可以移动的面板。前面已经看到可以将QAction对象添加到工具栏中,默认只是显示一个动作的图标,可以在QToolBar的属性栏中进行更改。在设计器中查看QToolBar的属性栏:
  • toolButtonStyle属性用来设置图标和相应文本的显示及其相对位置;
  • movabel属性用来设置状态栏是否可以移动;
  • allowedArea用来设置允许停靠的位置;
  • iconsize属性用来设置图标的大小;
  • floatable属性用来设置是否可以悬浮。

    工具栏中除了可以添加动作外,还可以添加其他的窗口部件,下面在前面的程序中的mainwindow.cpp文件中添加头文件:

    1
    2
    #include<QToolButton>
    #include<QSpinBox>

    在构造函数中继续添加代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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类对象,并为它添加了一个弹出菜单,设置了弹出方式是在按钮旁边有一个向下的小箭头,可以按下这个箭头弹出菜单(默认的弹出方式是按下按钮一段时间才弹出菜单)。最后将它添加到了工具栏中。下面又在工具栏中添加了一个QSpinBox部件,可以看到,往工具栏中添加部件可以使用addWidget()函数。

    这里还要再说明一下QToolButton类。其实,当往工具栏中添加一个QAction类对象时就会自动创建了一个QToolButton实例,所以说工具栏上的动作就是一个QToolButton,这就是属性栏中会有toolButtonStyle的原因。

以上运行结果如图所示:
主窗口界面布局运行结果

中心部件

主窗口的中心区域可以放置一个中心部件,它一般是一个编辑器或者浏览器。这里支持单文档部件,也支持多文档部件。一般的,我们会在这里放置一个部件,然后使用布局管理器使其充满整个中心区域,并可以随着窗口的大小变化而变化。下面在前面的程序中添加中心部件。在设计模式中,往中心区域拖人一个Text Edit,然后单击界面,按下Ctrl+G,使其处于一个栅格布局中。现在可以运行程序查看效果。

  • QTextEdit是一个高级的WYSIWYG(所见即所得)浏览器和编辑器,支持富文本的处理,为用户提供了强大的文本编辑功能。
  • 与QTextEdit对应的是QPlainTextEdit类,它提供了一个纯文本编辑器,这个类与QTextEdit类的很多功能都很相似,只不过无法处理富文本。
  • 还有一个QTextBrowser类,它是一一个富文本浏览器,可以看作是QTextE-dit的只读模式。
  • 这3个类的用法大同小异。

    中心区域还可以使用多文档部件。Qt中的QMdiArea部件就是用来提供一个可以显示MDI( Multiple Document Interface)多文档界面的区域,从而有效地管理多个窗口。QMdiArea中的子窗口由QMdiSubWindow类提供,这个类有自己的布局,包含一个标题栏和一个中心区域,可以向它的中心区域添加部件。

    下面更改前面的程序,在设计模式将前面添加的TextEdit部件删除,然后拖入一个MDI Area部件。在Action编辑器中的“新建文件”动作上右击,在弹出的级联菜单中选择“转到槽”,然后在弹出的对话框中选择triggered()触发信号,单击OK按钮后便转到mainwindow. cpp文件中的该信号的槽的定义处,更改如下:

1
2
3
4
5
6
7
8
9
void MainWindow::on_action_New_triggered()
{
//新建文本编辑器
QTextEdit *edit=new QTextEdit(this);
//使用QMdiArea类的addSubWindow()函数创建子窗口,以文本编辑器为中心部件。
QMdiSubWindow *child=ui->mdiArea->addSubWindow(edit);
child->setWindowTitle(tr("多文档编辑器子窗口"));
child->show();
}

这里需要先添加井include < QTextEdit>和井include < QMdiSubWindow>头文件在新建文件菜单动作的触发信号槽on_action_New_trigered()中创建了多文档区域的子窗口。这时运行程序,然后按下工具栏上的新建文件动作图标,每按下一次,就会生成一个子窗口,如图所示。

中心部件运行结果

Dock部件

QDockWidget类提供了这样一个部件,可以停靠在QMainWindow中,也可以悬浮起来作为桌面顶级窗口,称为Dock部件或者停靠窗口。Dock部件一般用于存放一些其他部件来实现特殊功能,就像一个工具箱。在主窗口中可以停靠在中心部件的四周,也可以悬浮起来被拖动到任意的地方,还可以被关闭或隐藏起来。一个Dock部件包含一个标题栏和一个内容区域,可以向Dock部件中放人任何部件。

在设计模式中向中心区域拖入一个Dock Widget 部件,然后再向Dock中随意拖人几个部件,比如这里拖入一个Push Button和一个Font Combo Box。在dock Widget的属性栏中更改其windowTitle为“工具箱”,另外还可以设置它的features属性,包含是否可以关闭、移动和悬浮等;还有allowedArea属性,用来设置可以停靠的区域。

下面在文件菜单中添加“显示Dock” 菜单项,然后在Action 编辑器中转到“显示Dock”动作的触发信号triggered()的槽函数,更改如下:

1
2
3
4
void MainWindow::on_action_Dock_triggered()
{
ui->dockWidget->show();
}

运行程序,关闭Dock部件后,按下显示Dock这个菜单项,就可以从新显示Dock了,运行结果如图:

停靠窗口工具箱运行结果

状态栏

QStatusBar类提供了一个水平条部件,用来显示状态信息。QMainWindow 中默认提供了一个状态栏。状态信息可以被分为3类:

  • 临时信息,如一般的提示信息;
  • 正常信息,如显示页数和行号;
  • 永久信息,如显示版本号或者日期。

显示函数:

  • 使用showMessage()函数显示一个临时消息,它会出现在状态栏的最左边。
  • 用addWidget()函数添加一个QLabel到状态栏上,用于显示正常信息,它会生成到状态栏的最左边,可能被临时消息掩盖。
  • 显示永久信息,则要使用addPermanentWidget()函数来添加一.个如QLabel–样的可以显示信息的部件,它会生成在状态栏的最右端,不会被临时消息掩盖。

    状态栏的最右端还有一个QSizeGrip部件,用来调整窗口的大小,可以使用set-SizeGripEnabled()函数来禁用它。
    因为目前的设计器还不支持直接向状态栏中拖放部件,所以需要使用代码来生成。向mainwindow.cpp文件中的构造函数里继续添加代码:

    1
    2
    3
    4
    5
    6
    7
    8
    #include <QLabel>
    //显示临时消息,时长为20000毫秒
    ui->statusBar->showMessage(tr("欢迎使用多文档编辑器"),20000);
    //创建标签,设置标签样式和显示信息,将其以永久部件形式添加到状态栏
    QLabel *permanent=new QLabel(this);
    permanent->setFrameStyle(QFrame::Box|QFrame::Sunken);
    permanent->setText("www.qter.org");
    ui->statusBar->addPermanentWidget(permanent);

    此时运行程序可以发现“欢迎使用多文档编辑器”字符串在显示一会儿后就自动消失了,而“www. qter. org”一直显示在状态栏最右端。如图所示:
    状态栏运行结果

自定义菜单

Qt中的QWidgetAction类就提供了在菜单中使用其他部件功能。为了实现自定义菜单,需要新建一个类,它继承自QWidgetAction 类,并且在其中重新实现create-Widget()函数。下面的例子中实现了这样一个菜单项:包含一个标签和一个行编辑器,可以在行编辑器中输人字符串,按下回车键就可以自动将字符串输入到中心部件文本编辑器中。
新建Qt Widgets应用,项目名称为myaction,类名默认为MainWindow ,基类默认为QMainWindow不改动。建好项目后往项目中添加新文件模板选择C++ Class, 类名设置为MyAction,基类设置为QWidgetAction。

  1. myaction.h中添加代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #ifndef MYACTION_H
    #define MYACTION_H
    #include<QWidgetAction>

    class QLineEdit; //前置声明
    class MyAction : public QWidgetAction
    {
    Q_OBJECT
    public:
    explicit MyAction(QObject *parent=0);
    protected:
    //声明函数,该函数是QWidgetAction类中的虚函数
    QWidget *createWidget(QWidget *parent);
    signals:
    //新建信号,用于在按下回车键时,将行编辑器中的内容发射出去
    void getText(const QString &string);
    private slots:
    //新建槽,它用来与行编辑器的按下回车键信号关联
    void sendText();
    private:
    //声明行编辑器对象的指针
    QLineEdit *lineEdit;
    };

    #endif // MYACTION_H
  2. myaction.cpp中添加代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "myaction.h"
#include<QLineEdit>
#include<QSplitter>
#include<QLabel>

MyAction::MyAction(QObject *parent):
QWidgetAction(parent)
{
//创建行编辑器
lineEdit=new QLineEdit;
//将行编辑器按下回车键信号与发送文本槽关联
connect(lineEdit,&QLineEdit::returnPressed,this,&MyAction::sendText);
}

QWidget *MyAction::createWidget(QWidget *parent)
{
//这里使用inherits()函数判断父部件(是否继承)是否是菜单或工具栏
//如果是,则创建该父部件的子部件,并返回子部件
//如果不是,则直接返回0
if(parent->inherits("QMenu")||parent->inherits("QToolBar")){
QSplitter *splitter = new QSplitter(parent);// 创建分裂器
QLabel *label=new QLabel;
label->setText(tr("插入文本:"));
splitter->addWidget(label);
splitter->addWidget(lineEdit);
return splitter;
}
return 0;
}

void MyAction::sendText()
{
emit getText(lineEdit->text());//发射信号,将行编辑器中的内容发射出去
lineEdit->clear(); //清空行编辑器中的内容
}
  1. 双击mainwindow.ui文件进入设计模式,向中心区域拖入一个Text Edit部件,并使用ctrl+G使其处于一个栅格布局中。
  2. 在mainwindow.h中添加代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    #include <QMainWindow>

    namespace Ui {
    class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    private:
    Ui::MainWindow *ui;
    private slots:
    void setText(const QString &string);
    };

    #endif // MAINWINDOW_H
  3. 在mainwindow.cpp中添加代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "myaction.h"

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    MyAction *action =new MyAction;
    QMenu *editMenu=ui->menuBar->addMenu(tr("编辑(&E)"));
    editMenu->addAction(action);
    connect(action,SIGNAL(getText(QString)),this,SLOT(setText(QString)));
    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }
    void MainWindow::setText(const QString &string)
    {
    ui->textEdit->setText(string);//将获取的文本添加到编辑器中
    }

    现在运行程序,在编辑菜单中单击自定义的菜单动作,然后输人字符并按下回车键,可以看到输人的字符自动添加到了文本编辑器中。
    这个例子中设计了自己的信号和槽,整个过程是这样的:在行编辑器中输人文本,然后按下回车键,这时行编辑就会发射returnPressed()信号,而这时就调用了我们的sendText()槽,在sendText()槽中又发射了getText()信号,信号中包含了行编辑器中的文本,接着又会调用setText()槽,在setText()槽中将getText()信号发来的文本输人到文本编辑器中。这样就完成了按下回车键将行编辑器中的文本输人到中心部件的文本编辑器中的操作。

富文本处理

富文本(Rich Text)或者叫富文本格式,简单来说就是在文档中可以使用多种格式,比如字体颜色、图片和表格等。它是与纯文本(Plain Text)相对而言的,比如Windows.上的记事本就是纯文本编辑器,而Word就是富文本编辑器。Qt中提供了对富文本处理的支持,可以在帮助中通过Rich Text Processing关键字查看。

富文本文档结构

富文本处理:

  • 编辑操作->基于光标的一些接口函数->textCursor()函数->基于QTextCursor类
    • QTextFrameFormat
    • QTextBlockFormat
    • QTextTableFormat
    • QTextListFormat
  • 只读操作->基于文档结构,使用了只读的分层次的接口函数->document()函数->基于QTextDocument类
    • QTextFrame
    • QTextBlock
    • QTextTable
    • QTextList
      文本块
      表格、列表与图片
      查找功能
      语法高亮与HTML

拖放操作

使用拖放打开文件
自定义拖放操作

打印文档

为什么后面没内容了呢?发现看电子档太无聊了啊,然后开始看视频了。。。。

你可以对我进行打赏哦