Juce实现Table自定义

Juce实现Table自定义

一.总体展示概及概述

在项目中Juce中TableList往往无法满足用户需求,头部和背景及背景颜色设置以及在Cell中添加自定义按钮,所以需要自己实现自定义TabelList,该示例是展示实现自定义TableList,实现自定义标题头及Item,程序员在使用过程中可以自己修改颜色皮肤,按需求实现相关功能。总体展示示例如下:

请添加图片描述

二.实现步骤

1.实现自定义TableListModel

实现TableListModel的背景绘制,绘制单元格,及重新实现单元格生成的控件函数,绘制单元格边线。

#pragma once#include <JuceHeader.h>
#include "TabelLookAndFeel.h"
#include "TableLabel.h"
#include "TabelOperCell.h"
#include <vector>
using namespace juce;class CustomTableModel :public juce::TableListBoxModel,public Label::Listener,public TabelOperComponent::Listener
{
public:struct TableItemInfo{std::string str_time_;std::string str_name_;bool b_checked = false;TableItemInfo(const std::string& str_time, const std::string& str_name,bool bChecked=false):str_time_(str_time), str_name_(str_name),b_checked(bChecked){}};public:CustomTableModel(std::vector<TableItemInfo>& items):vec_table_item_(items){}~CustomTableModel(){}int getNumRows() override{return vec_table_item_.size();}void paintRowBackground(juce::Graphics& g, int rowNumber, int width, int height, bool rowIsSelected) override{// 绘制行背景颜色juce::Colour bgColour(2,75,96);// = juce::Colour(8, 82.120);/* rowNumber % 2 ? juce::Colours::white//: juce::Colour(0xfff8f8f8);*/if (rowIsSelected)bgColour = Colour(127,191,127);g.fillAll(bgColour);// 绘制行底部分隔线//g.setColour(Colour(52,110,127));//g.drawLine(0, height - 1, width, height - 1);}void paintCell(juce::Graphics& g, int rowNumber, int columnId, int width, int height, bool rowIsSelected) override{//if (columnId != 1) // 非复选框列{// 设置文本样式g.setFont(juce::Font(14.0f));//g.setColour(rowIsSelected ? juce::Colours::black : juce::Colours::darkgrey);g.setColour(Colours::white);if (vec_table_item_.size() > rowNumber){if (columnId == 1){g.drawText(std::to_string(rowNumber+1), juce::Rectangle<int>(0, 0, width, height),juce::Justification::centred, true);}//else if (columnId == 2)//    g.drawText(vec_table_item_[rowNumber].str_name_.c_str(), juce::Rectangle<int>(0, 0, width, height),//        juce::Justification::centred, true);else if (columnId == 3)g.drawText(vec_table_item_[rowNumber].str_time_.c_str(), juce::Rectangle<int>(0, 0, width, height),juce::Justification::centred, true);}}// 绘制方格线g.setColour(Colour(52, 110, 127));//g.drawRect(0, 0, width, height);//g.drawLine(0, 0, width, 0, 2); // 绘制上边线g.drawLine(0, 0, 0, height, 2); // 绘制左边线g.drawLine(0, height, width, height, 2);// 绘制下边线if (columnId == 4)g.drawLine(width, 0, width, height, 2); // 绘制右边线}juce::Component* refreshComponentForCell(int rowNumber, int columnId, bool isRowSelected,juce::Component* existingComponentToUpdate) override{if (columnId == 2) // 复选框列{TabelLabel* label = static_cast<TabelLabel*>(existingComponentToUpdate);if (label == nullptr){label = new TabelLabel();label->setRow(rowNumber);label->setText(vec_table_item_[rowNumber].str_name_.c_str(),dontSendNotification);label->setEditable(true, true, false);label->addListener(this);}if (rowNumber < data.size()){label->setText(data[rowNumber][columnId - 1], juce::dontSendNotification);}return label;}else if (columnId == 4){TabelOperComponent* oper = static_cast<TabelOperComponent*>(existingComponentToUpdate);if (oper == nullptr){oper = new TabelOperComponent();oper->setRow(rowNumber);}return oper;}return nullptr;}// 设置 TableListBox 指针void setTable(juce::TableListBox* tableListBox){table = tableListBox;}// 处理标签文本更改事件void labelTextChanged(juce::Label* label) override{TabelLabel* label_new = static_cast<TabelLabel*>(label);int row = label_new->getRow();}void itemClicked(TabelOperComponent* oper, int type) override{int row = oper->getRow();}
private:juce::Array<juce::StringArray> data;juce::TableListBox* table = nullptr;std::vector<TableItemInfo>& vec_table_item_;juce::Array<bool> toggleStates;//CustomToggleLookAndFeel customToggleLookAndFeel;JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CustomTableModel)
};
2.实现TableList的标题头

继承自LookAndFeel_V4 绘制Border,绘制列及绘制背景色

#pragma once
#include <JuceHeader.h>
using namespace juce;class CustomTableHeaderLookAndFeel : public juce::LookAndFeel_V4
{
public:void drawTableHeaderBackground(juce::Graphics& g, juce::TableHeaderComponent& header) override{// 绘制表头背景//auto color = ;auto color = Colours::black.fromFloatRGBA(0, 0, 0, 0.25);g.fillAll(color);}// 新增绘制表格边框的方法void drawTableBorder(juce::Graphics& g, juce::TableListBox& table){g.setColour(juce::Colour(52, 110, 127)); // 设置边框颜色juce::Rectangle<int> bounds = table.getLocalBounds();// 绘制上边框g.drawLine(bounds.getX(), bounds.getY(), bounds.getRight(), bounds.getY(), 1);// 绘制下边框//g.drawLine(bounds.getX(), bounds.getBottom(), bounds.getRight(), bounds.getBottom(), 1);// 绘制左边框//g.drawLine(bounds.getX(), bounds.getY(), bounds.getX(), bounds.getBottom(), 1);// 绘制右边框//g.drawLine(bounds.getRight(), bounds.getY(), bounds.getRight(), bounds.getBottom(), 1);}void drawTableHeaderColumn(juce::Graphics& g, juce::TableHeaderComponent& header,const juce::String& columnName, int columnId,int width, int height, bool isMouseOver,bool isMouseDown, int columnFlags) override{{// 其他列的文本绘制(与item文本样式一致)g.setFont(juce::Font(14.0f)); // 设置与item相同的字体大小g.setColour(juce::Colours::white);g.drawText(columnName, juce::Rectangle<int>(0, 0, width, height),juce::Justification::centred, true);}// 绘制列的边框线g.setColour(Colour(52, 110, 127)); // 设置边框线颜色//g.drawRect(0, 0, width, height, 1); // 绘制1px宽的边框线g.drawLine(0, 0, width, 0, 2); // 绘制上边线g.drawLine(0, 0, 0, height, 2); // 绘制左边线g.drawLine(0, height, width, height,2);if(columnId == 4)g.drawLine(width, 0, width, height, 2); // 绘制右边线}
};
3.在列中实现自定义button

在对应列中实现自定义component创建,如下所示:
请添加图片描述

对应自定义component的代码示例:简单实现了三个按钮,同学可以根据自己情况修改按钮,可以增加图标增加美观

class TabelOperComponent : public juce::Component,public juce::ToggleButton::Listener
{
public:static const int BTN_NUM = 3;class JUCE_API  Listener{public:/** Destructor. */virtual ~Listener() = default;virtual void itemClicked(TabelOperComponent* oper,int type) = 0;};void addListener(Listener* newListener) {const ScopedLock sl(listenerLock);listeners.addIfNotAlreadyThere(newListener);}void removeListener(Listener* listenerToRemove) {const ScopedLock sl(listenerLock);listeners.removeFirstMatchingValue(listenerToRemove);}TabelOperComponent();~TabelOperComponent() override {}void setRow(int row) { row_ = row; }int  getRow() { return row_; }void paint(juce::Graphics& g) override;void resized() override;virtual void buttonClicked(Button*) override;
private:int row_ = 0;CriticalSection listenerLock;Array<Listener*> listeners;juce::ToggleButton toggleButtons[BTN_NUM];JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(TabelOperComponent)
};
#include "TabelOperCell.h"
TabelOperComponent::TabelOperComponent()
{for (int i = 0; i < 3; ++i){addAndMakeVisible(toggleButtons[i]);}
}
void TabelOperComponent::paint(juce::Graphics& g)
{//g.fillAll(getLookAndFeel().findColour(juce::ResizableWindow::backgroundColourId));auto area = getLocalBounds().toFloat();g.setColour(Colour(52, 110, 127));int width = area.getWidth();int height = area.getHeight();g.drawLine(0, 0, 0, height, 2); g.drawLine(width, 0, width, height, 2); g.drawLine(0, height, width, height, 2);
}void TabelOperComponent::resized()
{auto area = getLocalBounds();int width = (area.getWidth()-6)/3;for (auto& button : toggleButtons){button.setBounds(area.removeFromLeft(width).withSizeKeepingCentre(16,16));area.removeFromLeft(2);}
}void TabelOperComponent::buttonClicked(Button* ptr_btn)
{for (int i = 0; i < BTN_NUM; i++){if (ptr_btn == &toggleButtons[i]){ScopedLock lock(listenerLock);for (int j = listeners.size(); --j >= 0;)if (auto* l = listeners[j])l->itemClicked(this,i);}}
}
4.在MainCompoent中使用自定义TableList

使用Table和LookAndFeel并自定义了Item参数结构体,设置TableList的属性,并自定义添加Item条数。

请添加图片描述
请添加图片描述

请添加图片描述

示例代码如下:

#pragma once#include <JuceHeader.h>
#include "PresetTableComponent.h"
#include "TabelLookAndFeel.h"//==============================================================================
/*This component lives inside our window, and this is where you should put allyour controls and content.
*/
class MainComponent  : public juce::Component
{
public://==============================================================================MainComponent();~MainComponent() override;//==============================================================================void paint (juce::Graphics&) override;void resized() override;private://==============================================================================// Your private member variables go here...juce::TableListBox table_;CustomTableModel* table_model_ = nullptr;CustomTableHeaderLookAndFeel customLookAndFeel;std::vector<CustomTableModel::TableItemInfo> vec_table_item_;//TableDemoComponent table;JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
};
#include "MainComponent.h"//==============================================================================
MainComponent::MainComponent()
{//addAndMakeVisible(&table);table_.setLookAndFeel(&customLookAndFeel);table_.getHeader().addColumn("ID", 1, 10);table_.getHeader().addColumn("Name", 2, 10);table_.getHeader().addColumn("Time", 3, 10 * 4);table_.getHeader().addColumn("Operation", 4, 60);table_.getHeader().setSize(getWidth(), 32);table_.setColour(juce::TableListBox::backgroundColourId, Colour(2, 75, 96));table_.getViewport()->setScrollBarsShown(false, false);table_.getHeader().setPopupMenuActive(false);table_.getHeader().addMouseListener(this, false);table_.getHeader().setColumnVisible(7, false); // hide the "length" column until the user shows ittable_.setMultipleSelectionEnabled(true);addAndMakeVisible(&table_);setSize(500, 500);
}MainComponent::~MainComponent()
{
}//==============================================================================
void MainComponent::paint (juce::Graphics& g)
{// (Our component is opaque, so we must completely fill the background with a solid colour)g.fillAll (getLookAndFeel().findColour (juce::ResizableWindow::backgroundColourId));g.setFont (juce::Font (16.0f));g.setColour (juce::Colours::white);g.drawText ("Hello World!", getLocalBounds(), juce::Justification::centred, true);
}void MainComponent::resized()
{auto area = getLocalBounds();if (table_model_){table_.setModel(nullptr);delete table_model_;table_model_ = nullptr;}vec_table_item_.clear();for (int i = 0; i < 10; i++){vec_table_item_.emplace_back("2025-04-17 13:56:00", "Name1");}if (!table_model_){table_model_ = new CustomTableModel(vec_table_item_);table_.setModel(table_model_);table_model_->setTable(&table_);}auto tab_area = area;int colum_with = tab_area.getWidth() / 8;table_.setRowHeight(32);table_.getHeader().setColumnWidth(1, tab_area.removeFromLeft(colum_with).getWidth()); table_.getHeader().setColumnWidth(2, tab_area.removeFromLeft(colum_with).getWidth());table_.getHeader().setColumnWidth(3, tab_area.removeFromLeft(4 * colum_with).getWidth());table_.getHeader().setColumnWidth(4, tab_area.getWidth());table_.getHeader().setSize(getWidth(), 32);table_.getHeader().getProperties().set("allSelected", false);table_.setBounds(area);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/82391.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++ set数据插入、set数据查找、set数据删除、set数据统计、set排序规则、代码练习1、2

set数据插入&#xff0c;代码见下 #include<iostream> #include<set> #include<vector>using namespace std;void printSet(const set<int>& s) {for (set<int>::const_iterator it s.begin(); it ! s.end(); it) {cout << *it <…

深度学习赋能图像识别:技术、应用与展望

论文&#xff1a; 一、引言​ 1.1 研究背景与意义​ 在当今数字化时代&#xff0c;图像作为信息的重要载体&#xff0c;广泛存在于各个领域。图像识别技术旨在让计算机理解和识别图像内容&#xff0c;将图像中的对象、场景、行为等信息转化为计算机能够处理的符号或数据 &am…

深入解析C++引用:从别名机制到函数特性实践

1.C引用 1.1引用的概念和定义 引用不是新定义⼀个变量&#xff0c;而是给已存在变量取了⼀个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同⼀块内存空间。比如四大名著中林冲&#xff0c;他有一个外号叫豹子头&#xff0c;类比到C里就…

【从0-1的HTML】第1篇:HTML简介

1 HTML简介 HTML是用来描述网页的一种语言,是超文本标记语言的缩写(Hyper Text Markup Language),不属于编程语言的范畴&#xff0c;属于一种标记语言。 标记语言使用一套标记标签(Markup tag)&#xff0c;又称为标签,HTML就是使用标记标签来描述网页。 1.2 HTML标签 1、HTM…

vue+cesium示例:地形开挖(附源码下载)

基于cesium和vue绘制多边形实现地形开挖效果&#xff0c;适合学习Cesium与前端框架结合开发3D可视化项目。 demo源码运行环境以及配置 运行环境&#xff1a;依赖Node安装环境&#xff0c;demo本地Node版本:推荐v18。 运行工具&#xff1a;vscode或者其他工具。 配置方式&#x…

qwen大模型在进行词嵌入向量时,针对的词表中的唯一数字还是其他的?

qwen大模型在进行词嵌入向量时,针对的词表中的唯一数字还是其他的? Qwen大模型进行词嵌入向量时,针对的是词表中每个 Token 对应的唯一数字(Token ID) ,核心逻辑结合词表构建、嵌入过程展开 一、Qwen 词表与 Token ID Qwen 用 BPE 分词器(基于 tiktoken,以 cl100k 为…

动态规划-1143.最长公共子序列-力扣(LeetCode)

一、题目解析 对于给定了两个字符串中&#xff0c;需要找到最长的公共子序列&#xff0c;也就是两个字符串所共同拥有的子序列。 二、算法原理 1、状态表示 dp[i][j]&#xff1a;表示s1的[0,i]和s2的[0,j]区间内所有子序列&#xff0c;最长子序列的长度 2、状态转移方程 根…

互联网c++开发岗位偏少,测开怎么样?

通过这标题&#xff0c;不难看出问这个问题的&#xff0c;就是没工作过的。如果工作过&#xff0c;那就是不断往深的钻研&#xff0c;路越走越窄&#xff0c;找工作一般就是找原来方向的。没工作过的&#xff0c;那一般就是学生。 学生找什么方向的工作比较好&#xff1f; 学生…

推荐算法八股

跑路了&#xff0c;暑期0offer&#xff0c;华为主管面挂了&#xff0c;真幽默&#xff0c;性格测评就挂了居然给我一路放到主管面&#xff0c;科大迅飞太嚣张&#xff0c;直接跟人说后面要面华为&#xff0c;元戎启行&#xff0c;学了C后python完全忘了怎么写&#xff0c;挺尴尬…

Spring Boot微服务架构(九):设计哲学是什么?

一、Spring Boot设计哲学是什么&#xff1f; Spring Boot 的设计哲学可以概括为 ​​“约定优于配置”​​ 和 ​​“开箱即用”​​&#xff0c;其核心目标是​​极大地简化基于 Spring 框架的生产级应用的初始搭建和开发过程​​&#xff0c;让开发者能够快速启动并运行项目…

前端导入Excel表格

前端如何在 Vue 3 中导入 Excel 文件&#xff08;.xls 和 .xlsx&#xff09;&#xff1f; 在日常开发中&#xff0c;我们经常需要处理 Excel 文件&#xff0c;比如导入数据表格、分析数据等。文章将在 Vue 3 中实现导入 .xls 和 .xlsx 格式的文件&#xff0c;并解析其中的数据…

C++和C#界面开发方式的全面对比

文章目录 C界面开发方式1. **MFC&#xff08;Microsoft Foundation Classes&#xff09;**2. **Qt**3. **WTL&#xff08;Windows Template Library&#xff09;**4. **wxWidgets**5. **DirectUI** C#界面开发方式1. **WPF&#xff08;Windows Presentation Foundation&#xf…

刷leetcode hot100返航必胜版--链表6/3

链表初始知识 链表种类&#xff1a;单链表&#xff0c;双链表&#xff0c;循环链表 链表初始化 struct ListNode{ int val; ListNode* next; ListNode(int x): val&#xff08;x&#xff09;,next(nullptr) {} }; //初始化 ListNode* head new ListNode(5); 删除节点、添加…

软考 系统架构设计师系列知识点之杂项集萃(78)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之杂项集萃&#xff08;77&#xff09; 第139题 以下关于软件测试工具的叙述&#xff0c;错误的是&#xff08;&#xff09;。 A. 静态测试工具可用于对软件需求、结构设计、详细设计和代码进行评审、走查和审查 B. 静…

【Unity】云渲染

1 前言 最近在搞Unity云渲染的东西&#xff0c;所以研究了下官方提供的云渲染方案Unity Renderstreaming。注&#xff1a;本文使用的Unity渲染管线是URP。 2 文档 本文也只是介绍基本的使用方法&#xff0c;更详细内容参阅官方文档。官方文档&#xff1a;Unity Renderstreamin…

组相对策略优化(GRPO):原理及源码解析

文章目录 PPO vs GRPOPPO的目标函数GRPO的目标函数KL散度约束与估计ORM监督RL的结果PRM监督RL的过程迭代RL算法流程 GRPO损失的不同版本GRPO源码解析 DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models PPO vs GRPO PPO的目标函数 J P P O…

Linux或者Windows下PHP版本查看方法总结

确定当前服务器或本地环境中 PHP 的版本,可以通过以下几种方法进行操作: 1. 通过命令行检查 这是最直接且常用的方法,适用于本地开发环境或有 SSH 访问权限的服务器。 方法一:php -v 命令 php -v输出示例:PHP 8.1.12 (cli) (built: Oct 12 2023 12:34:56) (NTS) Copyri…

[Linux] MySQL源码编译安装

目录 环境包安装 创建程序用户 解压源码包 配置cmake ​编辑编译 安装 配置修改属性 属主和属组替换成mysql用户管理 系统环境变量配置 初始化数据库 服务管理 启动 环境包安装 yum -y install ncurses ncurses-devel bison cmake gcc gcc-c 重点强调&#xff1a;采…

【C++项目】负载均衡在线OJ系统-1

文章目录 前言项目结果演示技术栈&#xff1a;结构与总体思路compiler编译功能-common/util.hpp 拼接编译临时文件-common/log.hpp 开放式日志-common/util.hpp 获取时间戳方法-秒级-common/util.hpp 文件是否存在-compile_server/compiler.hpp 编译功能编写&#xff08;重要&a…

转战海外 Web3 远程工作指南

目录 一、明确职业目标和技能 二、准备常用软件 &#xff08;一&#xff09;通讯聊天工具 &#xff08;二&#xff09;媒体类平台 &#xff08;三&#xff09;线上会议软件 &#xff08;四&#xff09;办公协作工具 &#xff08;五&#xff09;云存储工具 &#xff08;六…