QT自定义优雅的表单控件,简单实现设置界面布局
一、实现效果
表单工具类FormView
FormView.h
#pragma once
#include <QVBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QStyleOption>
#include <QPainter>
#include <QApplication>
#include <QScreen>
#include <QCheckBox>
#include "QString"
#include "QMap"
#include <functional>
class FormView : public QWidget
{
Q_OBJECT
public:
//指定大小的表单,用于纯代码编写UI
FormView(int width, int height, QWidget* parent = nullptr);
//不指定大小的表单,用于在designer中使用
FormView(QWidget* parent = nullptr);
~FormView();
//在表单中插入一个控件
void addWidgetToForm(QWidget* widget);
//在表单中插入一个可填写项
void addEditableItem(QString title, QString place_holder);
//在表单中插入一个可勾选项
void addCheckableItem(QString title, QString content, bool init_status, std::function<void(bool)> call_back);
//设置表单控件的可用性
void setItemEnabled(QString item_title, bool enabled);
//获取具体控件的句柄
QLineEdit* getEditableItem(QString title);
QCheckBox* getCheckableItem(QString title);
//在表单头部添加一个弹簧(使表单靠下)
void startForm();
//在表单尾部添加一个弹簧(使表单靠上)
void endForm();
//start end 同时使用,表单居中
//清空表单所有可填写项
void Clear();
protected:
void Init(int width, int height);
void Init();
void paintEvent(QPaintEvent* event) override;
private:
QVBoxLayout* mainLayout;
QMap<QString, QWidget*> editItems;
QMap<QString, QWidget*> checkItems;
};
FormView.cpp
#include "FormView.h"
FormView::FormView(int width, int height, QWidget* parent) : QWidget(parent)
{
Init(width, height);
}
FormView::FormView(QWidget* parent /*= nullptr*/) : QWidget(parent)
{
Init();
}
FormView::~FormView()
{
}
void FormView::Clear()
{
for(auto widget : editItems)
{
QLineEdit* l = widget->findChild<QLineEdit*>();
if (l != nullptr)l->clear();
}
}
void FormView::Init(int width, int height)
{
setFixedSize(width, height);
Init();
}
void FormView::Init()
{
setObjectName(QStringLiteral("form_view"));
setStyleSheet(QStringLiteral("QWidget#form_view{border:none;background-color:white;border-top-right-radius:8px;border-bottom-right-radius:8px;}"));
mainLayout = new QVBoxLayout(this);
}
void FormView::paintEvent(QPaintEvent* event)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
QWidget::paintEvent(event);
}
void FormView::addWidgetToForm(QWidget* widget)
{
mainLayout->addSpacing(10);
mainLayout->addWidget(widget, 0, Qt::AlignLeft);
}
void FormView::addEditableItem(QString title, QString place_holder)
{
int height = 30;//调整输入框大小
QWidget* formItem = new QWidget;
formItem->setFixedSize(width() * 0.8, height+10);
QHBoxLayout* layout = new QHBoxLayout(formItem);
QLabel* label = new QLabel(title);
label->setStyleSheet(QStringLiteral("QLabel{font-size:16px;font-family:Microsoft Yahei;color:#000000;}"
"QLabel:disabled{font-size:16px;font-family:Microsoft Yahei;color:#828488;}"));
QLineEdit* edit = new QLineEdit(this);
edit->setPlaceholderText(place_holder);
edit->setFixedSize(width() * 0.5, height);
edit->setStyleSheet(QStringLiteral("QLineEdit{padding-left:22px;padding-right:22px;font-size:15px;font-family:Microsoft Yahei;border-radius:3px;border:1px solid #dcdfe6;color:#606266;}"
"QLineEdit:hover{border:1px solid #909399;}"
"QLineEdit:focus{border:1px solid #409EFF;}"));
edit->setFocusPolicy(Qt::FocusPolicy::ClickFocus);
layout->addWidget(label, 0, Qt::AlignLeft);
layout->addStretch();
layout->addWidget(edit, 0, Qt::AlignRight);
editItems.insert(title, formItem);
addWidgetToForm(formItem);
}
void FormView::addCheckableItem(QString title, QString content, bool init_status, std::function<void(bool)> call_back)
{
int height = 30;
QWidget* formItem = new QWidget;
formItem->setFixedSize(width() * 1, height+10);
QHBoxLayout* layout = new QHBoxLayout(formItem);
QLabel* label = new QLabel(content);
label->setStyleSheet(QStringLiteral("QLabel{font-size:16px;font-family:Microsoft Yahei;color:#000000;}"
"QLabel:disabled{font-size:16px;font-family:Microsoft Yahei;color:#828488;}"));
QCheckBox* check = new QCheckBox();
check->setStyleSheet(QStringLiteral("QCheckBox{font-size:16px;font-family:Microsoft Yahei;border:none;}"
"QCheckBox::indicator{width:20px;height:20px;border-radius:4px;border:1px solid #dcdfe6;}"
"QCheckBox::indicator:hover{border-radius:4px;border:2px solid #409EFF;}"
"QCheckBox::indicator:checked{border-radius:4px;border:1px solid #409EFF;background-color:#409EFF;image:url(./icons/checked.png);}"
"QCheckBox::indicator:disabled{background-color:#C2C2C2;image:url(./icons/disable.png);}"));
check->setChecked(init_status);
layout->addWidget(check, 0, Qt::AlignLeft);
layout->addWidget(label, 0, Qt::AlignLeft);
layout->addStretch();
connect(check, &QCheckBox::stateChanged, this, [=]() {
call_back(check->isChecked());
});
checkItems.insert(title, formItem);
addWidgetToForm(formItem);
}
void FormView::setItemEnabled(QString item_title, bool enabled)
{
QWidget* w = editItems.value(item_title);
if (w != nullptr)w->setEnabled(enabled);
QWidget* w2 = checkItems.value(item_title);
if (w2 != nullptr)w2->setEnabled(enabled);
}
QLineEdit* FormView::getEditableItem(QString title)
{
QWidget* w = editItems.value(title);
if (w == nullptr)return nullptr;
return w->findChild<QLineEdit*>();
}
QCheckBox* FormView::getCheckableItem(QString title)
{
QWidget* w = checkItems.value(title);
if (w == nullptr)return nullptr;
return w->findChild<QCheckBox*>();
}
void FormView::startForm()
{
if (mainLayout == nullptr)mainLayout = new QVBoxLayout(this);
mainLayout->addStretch();
}
void FormView::endForm()
{
mainLayout->addStretch();
}
核心函数
函数 | 变量 | 功能 |
---|---|---|
addEditableItem | title: 输入框前面的提示文字,同时作为该控件的标识符 place_holder: 输入框中的提示文字 |
在表单中插入一个可填写项 |
addCheckableItem | title: 不显示在UI中,仅作为该控件的标识符 content: 勾选框后面的内容 init_status: 勾选框的初始状态 call_back: 勾选状态变化后的回调函数 |
在表单中插入一个可勾选项 |
三、使用方法
1、纯代码使用
新建一个UITest类作为窗体,部分代码如下:
UITest::UITest(QWidget *parent)
: QMainWindow(parent)
{
Init();
//ui.setupUi(this);
}
UITest::~UITest()
{}
void UITest::Init()
{
int nScreenWidth = QApplication::primaryScreen()->geometry().width();
int nScreenHeight = QApplication::primaryScreen()->geometry().height();
setFixedSize(nScreenWidth * 0.8, nScreenHeight * 0.8);
FormView* form = new FormView(nScreenWidth*0.2,nScreenHeight * 0.4,this);
}
然后再main函数中使其显示即可:
UITest t;
t.show();
2、在designer中使用
新建一个qt widget类,在UI中添加Widget控件并提升为FormView:
需要注意的是,本表单工具仅能排成一列,若需要多列则应如图中所示设计多个表单控件。文章来源:https://www.toymoban.com/news/detail-506056.html
3、添加表格内容
为避免表格内项目大小出错,建议在paintEvent中初始化表格:文章来源地址https://www.toymoban.com/news/detail-506056.html
void SettingsView::paintEvent(QPaintEvent* event)
{
QWidget::paintEvent(event);
if (!isInited)
{
InitUI();
}
}
void SettingsView::InitUI()
{
QSize size(40, 40);
QPixmap mipmap_setting("./icons/setting_icon.png");
ui.setting_icon->setPixmap(mipmap_setting.scaled(size));
ui.btn_setting_confirm->setText(QStringLiteral("确认"));
//left form
//ui.settings_left->startForm();
ui.settings_left->addEditableItem(QStringLiteral("参考站IP"), QStringLiteral("127.0.0.1"));
ui.settings_left->addEditableItem(QStringLiteral("参考站端口"), QStringLiteral("8080"));
ui.settings_left->addEditableItem(QStringLiteral("流动站IP"), QStringLiteral("127.0.0.1"));
ui.settings_left->addEditableItem(QStringLiteral("流动站端口"), QStringLiteral("8080"));
ui.settings_left->addEditableItem(QStringLiteral("卫星系统"), QStringLiteral("B&C&G&E"));
ui.settings_left->addCheckableItem(QStringLiteral("偏差模式"), QStringLiteral("定位结果以偏差形式显示"), true,[=](bool ischecked) {
ui.settings_left->setItemEnabled(QStringLiteral("流动站坐标X"), ischecked);
ui.settings_left->setItemEnabled(QStringLiteral("流动站坐标Y"), ischecked);
ui.settings_left->setItemEnabled(QStringLiteral("流动站坐标Z"), ischecked);
});
ui.settings_left->addEditableItem(QStringLiteral("流动站坐标X"), QStringLiteral("地心坐标系X轴"));
ui.settings_left->addEditableItem(QStringLiteral("流动站坐标Y"), QStringLiteral("地心坐标系Y轴"));
ui.settings_left->addEditableItem(QStringLiteral("流动站坐标Z"), QStringLiteral("地心坐标系Z轴"));
ui.settings_left->endForm();
//right form
isInited = true;
//fill forms
fillForms();
}
到了这里,关于QT自定义优雅的表单控件,简单实现设置界面布局的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!