前言
老师给了一个任务,仿照jupyter notebook中可以动态添加、删除的cell,用c++的qt做一个类似的界面。具体来说,一个cell中有一个输入框,一个输出框,还有四个按钮,分别是运行
、添加
、删除
、清空
。此外,为了突出正在编辑的cell,要实现点击到cell的空白部分时,将背景颜色高亮。实现的效果如下:
虽然我压根就没学过qt,但是刚接到任务时,我觉得这玩意逻辑挺简单的,应该不难实现。但是后来发现我错了,要做这么一个小东西要用到很多知识。
实现
因为ui比较简单,所以用代码实现,没用designer。先整一个自定义组件叫cell(也就是一个类,继承自QWidget),cell里面包含了两个输入框和四个按钮,在public中定义这四个按钮,保证这四个按钮可以被外部访问到。
用一个QList把所有的cell存储起来,界面和这个QList一一对应,这样,添加和删除cell,就等于添加和删除QList。写一个渲染函数render,把已有的布局全删了,根据QList重新构建,每次进行一个操作之后都重新render。
怎么连接信号与槽呢?因为要实现的逻辑与全局有关,不能在cell内写connect,只能在外面的mainwindow里写,这就是为什么要保证四个按钮可以被外部访问到。因为按钮长得都一模一样,所以要区分按下的是哪一个cell的按钮,所以得用到传参的信号与槽,参数就是按钮的索引位置。这些都是写在render函数里的,别忘了在connect前先disconnect一下,清除原有的信号与槽。
最后,怎么点击背景改变颜色呢?先用groupbox把四个按钮和两个输入输出框包裹起来,然后想到直接用groupbox的click信号,但是我发现这玩意不生效(毕竟人家本来的作用不是拿来干这个的),所以换一种方法。我定义了一个myGroupBox类,继承自QGroupBox,然后重写了它的QMousePressEvent函数,点击就能发出bg_clicked信号(自定义信号),这个信号被mainwindow接收到就可以控制它的stylesheet啦。
代码:
cell.h
#ifndef CELL_H
#define CELL_H
#include <QWidget>
#include <QTextEdit>
#include <QPushButton>
#include <QVBoxLayout>
#include <QTextEdit>
#include "mygroupbox.h"
class Cell: public QWidget
{
Q_OBJECT
public:
explicit Cell(QWidget *parent = nullptr);
~Cell();
// 一些控件
myGroupBox *m_box;
QPushButton *m_btnAdd;
QPushButton *m_btnDelete;
QPushButton *m_btnClear;
QPushButton *m_btnRun;
QTextEdit *m_input;
QTextEdit *m_output;
// 属性:是否被选中
bool is_clicked=false;
private:
void init(); // 初始化内部控件
signals:
public slots:
};
#endif // CELL_H
mygroupbox.h
#ifndef MYGROUPBOX_H
#define MYGROUPBOX_H
#include <QGroupBox>
class myGroupBox : public QGroupBox
{
Q_OBJECT
public:
explicit myGroupBox(QWidget *parent = nullptr);
// 鼠标点击
virtual void mousePressEvent(QMouseEvent *ev);
signals:
void bg_clicked(); // 背景(groupbox)被点击后变色
public slots:
};
#endif // MYGROUPBOX_H
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTextEdit>
#include <QPushButton>
#include <QVBoxLayout>
#include <QTextEdit>
#include "mygroupbox.h"
#include "cell.h"
QT_BEGIN_NAMESPACE