混合编程
- 一.准备工作
- 1.创建项目
- 2.添加项目资源
 
- 二.ui界面设计
- 1.menuBar菜单栏
- 2.action ▲
- 3.toolBar工具栏
- 4.中心组件
 
- 三.代码界面设计
- 1.toolBar添加组件
- 2.statusBar状态栏添加组件
 
- 四.完成界面的功能
- 1.对action配置信号槽
- 2.对action转到信号槽
- 3.代码添加的组件手动关联槽函数
 
- 五.补充
- 1.样式选择问题
- 2.复制粘贴剪切可选
- 3.图标
 
- 六.总结
前言:为了让大家直观的感受到混合编程的界面设计,这里以做一个项目来,边做边学。
目标图:
 
 可以实现相应的功能哦,接下来我们开干!
一.准备工作
1.创建项目
因为我们的项目是有菜单栏,工具栏和状态栏的所以说我们要选择mainwindow为基类。
 
2.添加项目资源
我们这个项目可以看到有图片的显示,因此我们要先添加资源。
需要资源的可以dd我

 选择Qt里的Qt Resource File
 
 就会出现这样
 
 然后点击Add Prefix进行分组:

 然后点击Add Files添加资源
 
 咱们的资源就添加好了!
二.ui界面设计
1.menuBar菜单栏
打开设计器,菜单栏在界面的左上角这里
 
 可以输入名字,输完姚点击回车,才可保存!
 
 接下来可以填入选项
 这里不能输入汉字,但是可以粘贴进去
 也可以把类型的放在一起添加分隔符
 
 
 
 我们可以先看一下运行效果:
 
2.action ▲
这个时候我们会发现,下面出现了许多的action
 
 action是一个可用于菜单栏、工具栏和其他地方的可执行操作的对象.相当于我们可以从这里对刚刚写的菜单在这里进行操作!
 双击action可以对这些属性进行操作!
 
 我们可以把对象名字改成我们容易看得懂的。
 然后把我们的图标资源添加上。
 Shortcut可以设置我们的快捷键。
 
 然后把下面的action都进行修改!
 注意对于粗体斜体下划线是复选,可以打开也可以不打开。
 所以姚将Checkable选上。
 
 这就全部添加完了
 
 这是我们创建菜单时,自动创建的action
 我们也可以先创建action然后拖到相应的栏。
 
 我们可以看看效果:
 
 有图片了,哈哈是不是很高兴,嘿嘿嘿。
3.toolBar工具栏
在界面的右边可以看到我们界面当前有的东西
 
 默认是没有工具栏的,所有我们要进行手动的添加
右击MainWindow,添加工具栏

 这个时候就有工具栏了
 
界面上的工具栏在这里:
 
 然后我们可以将刚刚的action拖到工具栏中
 也可以右键添加分隔符
 

 这就拖完了,但是没有文字,我们可以先在右边的工具栏里的属性中找到toolButtonStyle进行设置
 
 选择
 
 就会出现:
 
然后添加一个文本编辑器组件
运行结果:
 
4.中心组件
看到我们的运行结果就感到很丑陋,文本编辑器都不能随着窗口的变化而变化。
 这个时候我们就姚开始加布局的操作了。
 选择整个窗口,添加水平布局。
 
 此时我们中心组件就是文本编辑器了
 
 可以自适应大小了,但是有边距
 
 可以在centralwidget里面的Layout里把边距都设置为0
 
 此时的运行结果:
 
 完美,下面的是状态栏,不是边距。
三.代码界面设计
1.toolBar添加组件
现在距离我们的界面目标还差工具栏里面的字体大小和字体选择,这两个组件是QSpinBox和QFontComboBox是不能够直接拖放到工具栏的,因此我们只能使用代码去进行操作。
 对于用代码写界面还是老样子
 先定义指针,注意头文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSpinBox>//整数选择
#include <QFontComboBox>//字体选择
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private:
    Ui::MainWindow *ui;
    QSpinBox*spinBoxFontSize;
    QFontComboBox*fontBox;
};
#endif // MAINWINDOW_H
然后对指针进行初始化
void MainWindow::initUI()
{
    spinBoxFontSize=new QSpinBox;
    fontBox=new QFontComboBox;
    spinBoxFontSize->setMinimumWidth(60); //设置字体大小选择的最小宽度
    spinBoxFontSize->setMinimum(8);//设置字体的最小尺寸
    spinBoxFontSize->setMaximum(60);//设置字体的最大尺寸
    spinBoxFontSize->setValue(ui->textEdit->fontPointSize());//开始拿到当前字体的大小
    ui->toolBar->addWidget(new QLabel("字体大小"));//向工具栏添加标签
    ui->toolBar->addWidget(spinBoxFontSize);//向工具栏中添加字体的大小选择
    fontBox->setMinimumWidth(160);//设置字体样式组件的最小宽度
    ui->toolBar->addSeparator();//添加一个分割符
    ui->toolBar->addWidget(new QLabel("字体"));//向工具栏中添加字体
    ui->toolBar->addWidget(fontBox);//向工具栏中添加字体
}
同时对组件进行一些基础的属性设置
 toolBar->addWiget这就是向工具栏进行添加组件的接口
 运行结果:
 
 OK,在工具栏中就出现了,我们需要的组件了。
2.statusBar状态栏添加组件
接下来就差状态栏的界面了
 添加的原理跟工具栏差不多
 先定义指针;
#include <QMainWindow>
#include <QSpinBox>//整数选择
#include <QFontComboBox>//字体选择
#include <QLabel>
#include <QProgressBar>//进度条
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private:
    Ui::MainWindow *ui;
    QSpinBox*spinBoxFontSize;
    QFontComboBox*fontBox;
    
    QLabel*fileName;
    QProgressBar*progressBar;
    void initUI();
};
接下来在initUI里面进行初始化
void MainWindow::initUI()
{
    spinBoxFontSize=new QSpinBox;
    fontBox=new QFontComboBox;
    fileName=new QLabel;
    progressBar=new QProgressBar;
    spinBoxFontSize->setMinimumWidth(60); //设置字体大小选择的最小宽度
    spinBoxFontSize->setMinimum(8);//设置字体的最小尺寸
    spinBoxFontSize->setMaximum(60);//设置字体的最大尺寸
    spinBoxFontSize->setValue(ui->textEdit->fontPointSize());//开始拿到当前字体的大小
    ui->toolBar->addWidget(new QLabel("字体大小"));//向工具栏添加标签
    ui->toolBar->addWidget(spinBoxFontSize);//向工具栏中添加字体的大小选择
    fontBox->setMinimumWidth(160);//设置字体样式组件的最小宽度
    ui->toolBar->addSeparator();//添加一个分割符
    ui->toolBar->addWidget(new QLabel("字体"));//向工具栏中添加字体
    ui->toolBar->addWidget(fontBox);//向工具栏中添加字体
    
    fileName->setMinimumWidth(180);//设置标签的最小宽度
    fileName->setText("当前文字");
    ui->statusbar->addWidget(fileName);//将标签添加到状态栏
    
    progressBar->setMinimum(8);//设置进度条的最小值,与字体的尺寸相对应
    progressBar->setMaximum(60);//设置进度条的最大值
    progressBar->setMinimumWidth(80);//设置进度条的最小宽度
    progressBar->setMaximumWidth(200);//设置进度条的最大宽度
    progressBar->setValue(ui->textEdit->fontPointSize());//用字体的大小来设置当前进度条的值
    ui->statusbar->addWidget(progressBar);//将进度条添加到状态栏
}
运行结果:
 
 OK我们的界面就全部完成了,这就是代码与ui设计器的结合,ok,接下来我们来实现功能!
四.完成界面的功能
1.对action配置信号槽
在这里有一个信号槽编辑器
 
 这里可以进行信号槽的添加
 对于信号和槽函数,qt内部都已经实现好的,才可以在这里直接进行配置。

 这里我们就对剪切,复制,退出,清空,粘贴进行了添加
 因为这些槽函数对应的接收者有对应的槽函数
 对于action有一个共同的信号就是triggered触发器
 
 运行结果:
 
 点击清空就没了

2.对action转到信号槽
OK,接下来,就是我们想要实现的功能,qt组件内部没有对应的函数,那就只能我们手动去写了
 但是还是有action的触发器信号
 我们可以直接在action上点击转到槽
 
 对于下划线,粗体,斜体因为有两种状态,我们用triggered(bool)这个信号。
 
 新建的槽函:
void MainWindow::on_actionNew_triggered()
{
    ui->textEdit->clear();//将当前的文本清空
    fileName->setText("当前文件");//文件名也清空
}
打开文件的槽函数:
void MainWindow::on_actionOpen_triggered()
{
    //打开一个文件并获取路径
    QString FileName=QFileDialog::getOpenFileName(this,"打开一个文件");
    if(!FileName.isEmpty())//如果路径不为空
    {
        QFile file(FileName);//创建一个文件对象用路径名初始化
        if(file.open(QIODevice::ReadWrite|QIODevice::Text))//打开文件
        {
            QTextStream stream(&file);//创建一个文件流对象
            while(!stream.atEnd())//如果没有读到结尾
            {
                ui->textEdit->append(stream.readLine());//将读的每行添加到文件流中,然后尾部追加到文本编辑器中
            }
             fileName->setText("当前文件:"+FileName);//将当前的文件名进行修改
        }
        file.close();//关闭文件
    }
   
}
3个字体样式的槽函数:
void MainWindow::on_actionBold_triggered(bool checked)
{
    auto format=ui->textEdit->currentCharFormat();//获取光标位置的字体样式
    format.setFontWeight(checked?QFont::Bold:QFont::Normal);//根据状态修改成粗体样式
    ui->textEdit->mergeCurrentCharFormat(format);//将修改后样式合并到字体样式中
}
void MainWindow::on_actionItalic_triggered(bool checked)
{
    auto format=ui->textEdit->currentCharFormat();
    format.setFontItalic(checked);
    ui->textEdit->mergeCurrentCharFormat(format);
}
void MainWindow::on_actionUnderLine_triggered(bool checked)
{
    auto format=ui->textEdit->currentCharFormat();
    format.setFontUnderline(checked);
    ui->textEdit->mergeCurrentCharFormat(format);
}
我注释写的这么详细,我就不讲了,如果有不懂的地方可以问我。
 运行效果:
 
 打开一个文件和3种样式可以完了,你们可以多玩玩,哈哈。
3.代码添加的组件手动关联槽函数
像我们自己手动添加的组件,我们必须要手动的关联和定义槽函数
 字体大小和字体的样式本身有信号,所以不用我们进行手动的添加
 先定义槽函数:
void on_spinBoxFontSize_valueChanged(int size);
void on_fontBox_currentIndexChanged(const QString & fontStyle);
然后关联:
void MainWindow::initSignalSlots()
{
    connect(spinBoxFontSize,SIGNAL(valueChanged(int)),
            this,SLOT(on_spinBoxFontSize_valueChanged(int)));
    connect(fontBox,SIGNAL(currentIndexChanged(const QString &)),
            this,SLOT(on_fontBox_currentIndexChanged(const QString &)));
}
最后实现槽函数:
void MainWindow::on_spinBoxFontSize_valueChanged(int size)
{
    QTextCharFormat format;
    format.setFontPointSize(size);//根据发来的信号设置文本的大小
    ui->textEdit->mergeCurrentCharFormat(format);//将字体大小合并到文本
    progressBar->setValue(size);//设置进度条的值
}
void MainWindow::on_fontBox_currentIndexChanged(const QString &fontStyle)
{
    QTextCharFormat format;
    format.setFontFamily(fontStyle);
    ui->textEdit->mergeCurrentCharFormat(format);
}
运行效果:
 
 现在就可以尽情的玩耍了,功能都有了,你也试试看吧!
五.补充
1.样式选择问题
现在还是会有一点小bug,就是如果我点了斜体,粗体,下划线,我选择其他文本文字,他们的状态还是一直点着的。
 我们可以用文本编辑器的一个转到槽,有个文本选择改变信号
 
 实现槽函数:
void MainWindow::on_textEdit_selectionChanged()
{
    //先获取当前文本格式
    auto format=ui->textEdit->currentCharFormat();
    //根据当前的文本判断是否设置了样式
    ui->actionBold->setChecked(format.font().bold());
    ui->actionItalic->setChecked(format.fontItalic());
    ui->actionUnderLine->setChecked(format.fontUnderline());
}
效果:
 
2.复制粘贴剪切可选
现在有一个需求就是当我们选择文本才可以复制剪切
 文本编辑器也有一个信号就是能否复制
 
 实现槽函数:
void MainWindow::on_textEdit_copyAvailable(bool b)
{
    ui->actionCut->setEnabled(b);//如果可以复制就可以使用剪切
    
    ui->actionCopy->setEnabled(b);//如果可以复制就复制
    
    ui->actionPaste->setEnabled(ui->textEdit->canPaste());//如果可以粘贴的时候就设置可以
}
效果:
 现在剪切和复制就用不了了,选中就又可以复制和剪切了。
 
3.图标
扩充内容,最后咱们来搞一个图标。
 点击这里可以将图片转换成ico图标格式
 然后保存到项目同目录下
 在pro文件中加一个模块
 
 等于后面与保存在同目录下的名字相同
 
 顺便加一个窗口主题名:
 
运行结果:
 
 帅呆了,太酷了!
 哎呀,其他功能你们做好了,自己玩,我不想截图了…
六.总结
很明显,ui设计器的开发效率极快,但是有的界面只能用代码实现,如我们这个项目中,向工具栏和状态栏里面添加组件时,只能用代码来实现。
 总的来说一句话:能用ui设计器的就尽量用,不能用的就用代码!
花了一天的时间,终于写完了,今天星期天,咱们的设计界面就完结撒花了,真的是太累了。确实接口有点多,容易记混,不过慢慢来,重要的是思想!
OK,就到这里吧!(* ̄︶ ̄)



















