12.QT-Combo Box|Spin Box|模拟点餐|从文件中加载选项|调整点餐份数(C++)

Combo Box

QComboBox 表⽰下拉框

核⼼属性

属性说明
currentText当前选中的⽂本
currentIndex当前选中的条⽬下标.
从0开始计算.如果当前没有条⽬被选中,值为-1
editable是否允许修改
设为true时, QComboBox 的⾏为就⾮常接近 QLineEdit ,也可以
设置 validator
iconSize下拉框图标(⼩三⻆)的⼤⼩
maxCount最多允许有多少个条⽬

核⼼⽅法

⽅法说明
addItem(const QString&)添加⼀个条⽬
currentIndex()获取当前条⽬的下标
从0开始计算.如果当前没有条⽬被选中,值为-1
currentText()获取当前条⽬的⽂本内容.

核⼼信号

方法说明
activated(int)
activated(const QString& text)
当⽤⼾选择了⼀个选项时发出.
这个时候相当于⽤⼾点开下拉框,并且⿏标划过某个选项.
此时还没有确认做出选择.
currentIndexChanged(int)
currentIndexChanged(const QString
& text)
当前选项改变时发出.
此时⽤⼾已经明确的选择了⼀个选项.
⽤⼾操作或者通过程序操作都会触发这个信号.
editTextChanged(const QString &
text)
当编辑框中的⽂本改变时发出
(editable为true时有效
代码⽰例:使⽤下拉框模拟⻨当劳点餐

1)在界⾯上创建三个下拉框,和⼀个按钮.
![[Pasted image 20250421084752.png]]

2)编写widget.cpp,初始化三个下拉框的内容

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
  
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
  
    ui->comboBox->addItem("麦辣鸡腿堡");
    ui->comboBox->addItem("巨无霸");
    ui->comboBox->addItem("培根蔬脆双层牛堡");
    ui->comboBox_2->addItem("中薯条");
    ui->comboBox_2->addItem("麦乐鸡翅");
    ui->comboBox_2->addItem("麦乐鸡块");
    ui->comboBox_3->addItem("可乐");
    ui->comboBox_3->addItem("雪碧");
}
  
Widget::~Widget()
{
    delete ui;
}
  
  
void Widget::on_pushButton_clicked()
{
    qDebug() << ui->comboBox->currentText() << ", " << ui->comboBox_2->currentText() << ", " << ui->comboBox_3->currentText();
}

![[Pasted image 20250421085244.png]]

也可以在图形界面,右键添加项目
![[Pasted image 20250421085414.png]]

代码⽰例:从⽂件中加载下拉框的选项

很多时候下拉框的选项并⾮是固定的,⽽是通过读取⽂件/读取⽹络获取到的
1)在界⾯上创建⼀个下拉框
![[Pasted image 20250421091056.png]]

2)创建⽂件config.txt ,编写选项.每个选项占⼀⾏.
![[Pasted image 20250421091046.png]]

3)修改widget.cpp,从⽂件中读取选项.

  • 使⽤ ifstream 打开⽂件
  • 使⽤ getline 读取每⼀⾏
  • 使⽤ QString::fromStdString 把 std::string 转成 QString
#include "widget.h"
#include "ui_widget.h"
  
#include <fstream>
#include <QDebug>
  
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
  
    //读取文件内容,把文件中的每一行读取出来,作为选项
    std::ifstream file("F:/Qt/QT Work/qcombobox1/config.txt");
    if (!file.is_open()) {
        qDebug() << "文件打开失败";
        return;
    }
    //按行读取文本内容getline
    std::string line;
    while (std::getline(file, line)) {
        //取到的内容都设置到下拉框中
        ui->comboBox->addItem(QString::fromStdString(line));
    }
    file.close();
}
  
Widget::~Widget()
{
    delete ui;
}

![[Pasted image 20250421092805.png]]

Qt中也提供了QFile实现读写⽂件的功能.当然使⽤C++标准库的std::fstream也是完全可以的.
之所以存在两套,是因为Qt诞⽣较早(1991年左右),此时C++还没有完成"标准化"的⼯作,C++标准库这样的概念⾃然也没有诞⽣.
因此Qt就⾃⼰打造了⼀套库,实现了字符串,容器,⽂件操作,多线程,⽹络操作,定时器,正则表达式等内容.(由于C++标准委员会的不作为,⾄今仍然有些Qt提供的功能,是标准库不具备的)

Spin Box

使⽤ QSpinBox 或者 QDoubleSpinBox 表⽰"微调框",它是带有按钮的输⼊框.可以⽤来输⼊整数/浮点数.通过点击按钮来修改数值⼤⼩.
由于 SpinBox 和 QDoubleSpinBox ⽤法基本相同,就只介绍 SpinBox 的使⽤了.

关键属性

属性说明
value存储的数值.
singleStep每次调整的"步⻓".按下⼀次按钮数据变化多少.
displayInteger数字的进制.例如displayInteger设为10,则是按照10进制表⽰.设为2则为2进制表⽰.
minimum最⼩值
maximum最⼤值
suffix后缀
prefix前缀
wrapping是否允许换⾏
frame是否带边框
alignment⽂字对⻬⽅式.
readOnly是否允许修改
buttonSymbol按钮上的图标.
• UpDownArrows 上下箭头形式
• PlusMinus 加减号形式
• NoButtons 没有按钮
accelerated(加速的)按下按钮时是否为快速调整模式
correctionMode输⼊有误时如何修正.
• QAbstractSpinBox::CorrectToPreviousValue :如果⽤⼾输⼊了⼀个
⽆效的值(例如,在只能显⽰正整数的SpinBox中输⼊了负数),那么
SpinBox会恢复为上⼀个有效值。例如,如果SpinBox的初始值是1,⽤⼾输⼊了-1(⽆效),然后SpinBox会恢复为1。
• QAbstractSpinBox::CorrectToNearestValue :如果⽤⼾输⼊了⼀个
⽆效的值,SpinBox会恢复为最接近的有效值。例如,如果SpinBox的初始值是1,⽤⼾输⼊了-1(⽆效),那么SpinBox会恢复为0。
keyboardTrack是否开启键盘跟踪.
设为true,每次在输⼊框输⼊⼀个数字,都会触发⼀次valueChanged()和
textChanged()信号.
设为false,只有在最终按下enter或者输⼊框失去焦点,才会触发
valueChanged()和textChanged()信号.
核⼼信号
信号说明
textChanged(QString)微调框的⽂本发⽣改变时会触发.
参数QString带有前缀和后缀.
valueChanged(int)微调框的⽂本发⽣改变时会触发.
参数int,表⽰当前的数值.
代码⽰例:调整⻨当劳购物⻋中的份数

1)在界⾯上创建下列内容

  • 三个下拉框: objectName 为 comboBox 到 comboBox_3
  • 三个微调框: objectName 为 spinBox 到 spinBox_3
  • ⼀个按钮: objectName 为 pushButton
    ![[Pasted image 20250421100004.png]]

2)编写代码,修改widget.cpp,给下拉框设置初始值.

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
  
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
  
    //初始化下拉菜单
    ui->comboBox->addItem("麦辣鸡腿堡");
    ui->comboBox->addItem("巨无霸");
    ui->comboBox->addItem("培根蔬脆双层牛堡");
  
    ui->comboBox_2->addItem("中薯条");
    ui->comboBox_2->addItem("麦乐鸡翅");
    ui->comboBox_2->addItem("麦乐鸡块");
  
    ui->comboBox_3->addItem("可乐");
    ui->comboBox_3->addItem("雪碧");
}
  
Widget::~Widget()
{
    delete ui;
}
  
  
void Widget::on_pushButton_clicked()
{
    qDebug() << "当前下单的内容: "
             << ui->comboBox->currentText() << ": " << ui->spinBox->value()
             << ui->comboBox_2->currentText() << ": " << ui->spinBox_2->value()
             << ui->comboBox_3->currentText() << ": " << ui->spinBox_3->value();
}

4)执⾏程序,可以看到当⽤⼾选择不同的内容时,点击按钮就能获取到对应的结果
![[Pasted image 20250421100624.png]]

    //针对QSpinBox的范围进行设置
    ui->spinBox->setRange(1, 5);
    ui->spinBox_2->setRange(1, 5);
    ui->spinBox_3->setRange(1, 5);
  
    ui->spinBox->setValue(1);
    ui->spinBox_2->setValue(1);
    ui->spinBox_3->setValue(1);

![[Pasted image 20250421101633.png]]

分析路由器客户端对路由器上ftp服务器一次ftp读写的perf报告结果,分析如何处理优化USB读写性能。 91.19% 0.00% proftpd [kernel.kallsyms] [k] el0_svc_compat | ---el0_svc_compat el0_svc_compat_handler | --91.10%--el0_svc_common | |--50.27%--__arm64_sys_read | | | --50.22%--ksys_read | | | --50.06%--vfs_read | | | --49.76%--__vfs_read | | | --49.62%--sock_read_iter | | | --49.50%--inet_recvmsg | | | --49.21%--tcp_recvmsg | | | |--22.17%--tcp_cleanup_rbuf | | | | | --22.08%--tcp_send_ack | | | | | --22.02%--__tcp_send_ack.part.0 | | | | | |--20.97%--__tcp_transmit_skb | | | | | | | --20.26%--ip_queue_xmit | | | | | | | --20.15%--__ip_queue_xmit | | | | | | | |--14.61%--ip_output | | | | | | | | | |--13.77%--ip_finish_output | | | | | | | | | | | --13.54%--ip_finish_output2 | | | | | | | | | | | --13.10%--dev_queue_xmit | | | | | | | | | | | --13.04%--__dev_queue_xmit | | | | | | | | | | | --12.42%--dev_hard_start_xmit | | | | | | | | | | | --12.05%--br_dev_xmit | | | | | | | | | | | --10.85%--br_forward | | | | | | | | | | | --10.24%--__br_forward | | | | | | | | | | | |--8.91%--br_forward_finish | | | | | | | | | | | | | |--6.53%--br_dev_queue_push_xmit | | | | | | | | | | | | | | | --6.46%--dev_queue_xmit | | | | | | | | | | | | | | | --6.42%--__dev_queue_xmit | | | | | | | | | | | | | | | --5.87%--dev_hard_start_xmit | | | | | | | | | | | | | | | --5.76%--bcmVlan_devHardStartXmit | | | | | | | | | | | | | | | |--4.22%--dev_queue_xmit | | | | | | | | | | | | | | | | | --4.16%--__dev_queue_xmit | | | | | | | | | | | | | | | | | --3.61%--__qdisc_run | | | | | | | | | | | | | | | | --3.13%--sch_direct_xmit | | | | | | | | | | | | | | | | --2.80%--dev_hard_start_xmit | | | | | | | | | | | | | | | | --2.50%--enet_xmit | | | | | | | | | | | | | | | | --1.59%--dispatch_pkt_sf2_lan | | | | | | | | | | | | | | | | --1.32%--cpu_queues_tx_send | | | | | | | | | | | | | | | | --1.25%--archer_dma_cpu_tx_queue_notifier | | | | | | | | | | | | | | | | --1.13%--archer_task_schedule | | | | | | | | | | | | | | | | --1.10%--archer_thread_wakeup | | | | | | | | | | | | | | | | --1.09%--__wake_up | | | | | | | | | | | | | | | | --1.02%--_raw_spin_unlock_irqrestore | | | | | | | | | | | | | | | --0.97%--bcmVlan_processFrame | | | | | | | | | | | | | --2.19%--nf_hook_slow | | | | | | | | | | | | | --1.93%--br_hook | | | | | | | | | | | | | --1.46%--sprintf | | | | | | | | | | | | | --1.39%--vsnprintf | | | | | | | | | | | --1.09%--nf_hook_slow | | | | | | | | | --0.53%--nf_hook_slow | | | | | | | --4.97%--__ip_local_out | | | | | | | --4.74%--nf_hook_slow | | | | | | | |--2.41%--ipv4_conntrack_local | | | | | | | | | --2.14%--nf_conntrack_in | | | | | | | | | --0.80%--tcp_packet | | | | | | | |--0.69%--iptable_filter_hook | | | | | | | | | --0.64%--ipt_do_table | | | | | | | |--0.59%--iptable_raw_hook | | | | | | | | | --0.57%--ipt_do_table | | | | | | | --0.54%--iptable_mangle_hook | | | | | --0.56%--__alloc_skb | | | |--16.16%--skb_copy_datagram_iter | | | | | |--12.56%--_copy_to_iter | | | | | | | --12.20%--__arch_copy_to_user | | | | | --3.05%--__check_object_size | | | |--5.14%--__kfree_skb | | | | | |--2.72%--skb_release_data | | | | | | | --2.44%--bcm_skb_free_head | | | | | | | --2.33%--enet_recycle_handler | | | | | | | --2.02%--_raw_spin_unlock_irqrestore | | | | | |--1.05%--kfree_skbmem.part.0 | | | | | | | --0.96%--kmem_cache_free | | | | | --0.90%--skb_release_head_state | | | |--3.64%--release_sock | | | | | --3.45%--__release_sock | | | | | --3.18%--tcp_v4_do_rcv | | | | | --2.88%--tcp_rcv_established | | | | | |--0.60%--tcp_queue_rcv | | | | | --0.53%--__tcp_ack_snd_check | | | --0.66%--tcp_rcv_space_adjust | |--27.87%--__arm64_sys_write | | | --27.84%--ksys_write | | | --27.59%--vfs_write | | | --27.19%--__vfs_write | | | --26.98%--generic_file_write_iter | | | --26.63%--__generic_file_write_iter | | | |--25.00%--generic_perform_write | | | | | |--16.76%--exfat_write_begin | | | | | | | --16.49%--tp_cont_write_begin | | | | | | | --16.15%--tp_block_write_begin | | | | | | | |--8.53%--__tp_block_write_begin_int.constprop.0 | | | | | | | | | |--5.06%--tp_exfat_get_block | | | | | | | | | | | --4.47%--exfat_map_cluster | | | | | | | | | | | |--1.84%--exfat_get_cluster | | | | | | | | | | | | | --0.84%--exfat_ent_get | | | | | | | | | | | --1.32%--exfat_alloc_cluster | | | | | | | | | | | --0.57%--exfat_ent_set | | | | | | | | | |--1.57%--create_empty_buffers | | | | | | | | | | | --1.15%--alloc_page_buffers | | | | | | | | | | | --1.05%--alloc_buffer_head | | | | | | | | | | | --0.59%--kmem_cache_alloc | | | | | | | | | --0.97%--clean_bdev_aliases | | | | | | | | | --0.77%--pagevec_lookup_range | | | | | | | | | --0.52%--radix_tree_next_chunk | | | | | | | |--6.83%--grab_cache_page_write_begin | | | | | | | | | --6.54%--pagecache_get_page | | | | | | | | | |--2.88%--add_to_page_cache_lru | | | | | | | | | | | |--1.37%--_raw_spin_unlock_irq | | | | | | | | | | | --1.15%--lru_cache_add | | | | | | | | | | | --0.77%--_raw_spin_unlock_irqrestore | | | | | | | | | |--2.43%--__alloc_pages_nodemask | | | | | | | | | | | --1.90%--get_page_from_freelist | | | | | | | | | --0.69%--find_get_entry | | | | | | | --0.53%--memset | | | | | |--3.96%--iov_iter_copy_from_user_atomic | | | | | | | --3.63%--__arch_copy_from_user | | | | | --3.15%--exfat_write_end | | | | | --3.02%--generic_write_end | | | | | --2.46%--block_write_end | | | | | --2.12%--__block_commit_write.constprop.0.isra.0 | | | | | --1.68%--mark_buffer_dirty | | | | | --1.48%--_raw_spin_unlock_irqrestore | | | --0.94%--iov_iter_fault_in_readable | |--4.84%--__arm64_compat_sys_select | | | --4.50%--do_compat_select | | | --3.24%--compat_core_sys_select | | | --2.25%--do_select | | | --0.81%--sock_poll | | | --0.61%--tcp_poll | |--3.85%--__arm64_compat_sys_setitimer | | | --2.53%--_raw_spin_unlock_irq | |--0.74%--__arm64_compat_sys_aarch32_pwrite64 | | | --0.73%--ksys_pwrite64 | vfs_write | | | --0.62%--__vfs_write | | | --0.58%--generic_file_write_iter | | | --0.51%--__generic_file_write_iter | --0.66%--__arm64_compat_sys_clock_gettime
10-11
<think>我们首先分析perf报告。从报告中可以看出,主要的时间消耗在读取(read)和写入(write)操作上,其中读取操作占用了大部分时间(50.27%在__arm64_sys_read中,而写入操作占27.87%在__arm64_sys_write中)。 具体到读取操作(read): - 主要的调用路径是:`tcp_recvmsg` (49.21%),其中又分为: - `tcp_cleanup_rbuf` (22.17%) -> 主要是发送ACK(`tcp_send_ack`)和传输数据包(`__tcp_transmit_skb`),然后通过网络栈(IP层、设备层等)发送。 - `skb_copy_datagram_iter` (16.16%) -> 主要是在用户空间和内核空间之间复制数据(`_copy_to_iter`和`__arch_copy_to_user`)。 - `__kfree_skb` (5.14%) -> 释放SKB内存,其中涉及到一些内存释放操作(如`bcm_skb_free_head`、`enet_recycle_handler`等)。 写入操作(write): - 主要调用路径是:`__generic_file_write_iter` (26.63%),其中: - `generic_perform_write` (25.00%):这里面主要涉及文件系统的写操作,使用的是exfat文件系统(因为看到`exfat_write_begin`等函数)。 - `exfat_write_begin` (16.76%):写开始操作,其中主要时间在`tp_block_write_begin`(16.15%),这个函数内部又调用了文件系统相关的函数(如`exfat_map_cluster`、`exfat_alloc_cluster`等)以及页缓存操作(如`grab_cache_page_write_begin`、`__alloc_pages_nodemask`等)。 - 此外,还有`exfat_write_end`(3.15%)等。 从上述分析,我们可以看出性能瓶颈可能出现在: 1. 网络栈处理(特别是TCP的ACK发送和数据包传输)消耗了大量时间(约22%在read路径中)。 2. 数据从内核空间复制到用户空间(16%左右)也是read路径中的一个瓶颈。 3. 文件系统的写操作(主要是exfat文件系统)消耗了大量时间(约25%在write路径中),特别是文件系统元数据操作(如分配簇、映射簇等)。 针对USB读写性能优化,我们可以考虑以下方向: 1. **网络栈优化**: - 调整TCP参数,例如减少ACK发送的频率(如启用TCP_DELAY_ACK)或者调整接收窗口大小,以减少ACK的数量。 - 检查是否可以使用更大的MTU(最大传输单元),以减少数据包的数量。 - 考虑使用网络加速技术(如TSO、GSO等)来减轻CPU负担。 2. **减少数据复制**: - 使用零拷贝技术,例如使用`splice`或`sendfile`系统调用,避免数据在用户空间和内核空间之间的复制。但注意,这需要应用程序的支持。 3. **文件系统优化**: - 由于使用exfat文件系统,并且写操作中元数据操作(如簇的分配和映射)占比较高,可以考虑以下措施: - 确保文件系统块大小与USB存储设备的块大小对齐,减少碎片。 - 如果可能,使用更高效的文件系统(如ext4)或者优化exfat驱动(例如,使用异步I/O)。 - 增加文件系统的预读(readahead)设置,减少小文件读写次数。 - 使用更高效的块设备驱动或者优化USB驱动。 4. **内存管理优化**: - 在释放SKB内存(`__kfree_skb`)时,我们看到有内存释放操作(如`kmem_cache_free`)消耗了一定时间。可以考虑使用内存池(例如,预先分配好SKB)来减少内存分配/释放的开销。 5. **硬件相关优化**: - 检查USB控制器驱动是否是最新版本,或者是否有优化版本。 - 确认USB存储设备本身的速度(如USB2.0/3.0),确保使用高速接口。 6. **应用程序优化**: - 调整FTP服务器的配置,例如增加缓冲区大小,减少读写次数。 - 考虑使用异步I/O或多线程处理,以避免阻塞。 由于perf报告中显示写操作中exfat文件系统的操作占了很大比例,我们应重优化文件系统。同时,网络栈的优化也不容忽视。 具体步骤建议: 1. 调整TCP参数,例如设置`net.ipv4.tcp_delack_min`和`net.ipv4.tcp_no_metrics_save`等。 2. 检查exfat文件系统的挂载参数,例如使用`noatime`、`nodiratime`等减少元数据更新。 3. 考虑使用更快的存储介质(如果USB设备本身较慢)或者更换USB端口(确保使用USB3.0及以上)。 4. 如果可能,在内核中启用exfat的日志以减少元数据操作的开销(但目前exfat默认不支持日志)。 5. 测试使用不同的文件系统(如ext4、f2fs等)对比性能。 注意:优化前应备份数据,并逐步测试每个优化步骤的效果。 §§相关问题§§ 1. 如何调整TCP参数以减少ACK发送频率? 2. 在exFAT文件系统中,有哪些挂载选项可以优化读写性能? 3. 如何在内核中实现零拷贝以提高文件传输效率? 4. 如何检测USB设备的实际传输速度以及是否被正确识别为高速设备? 5. 对于FTP服务器软件(如proftpd),有哪些配置选项可以优化大文件传输? </think>### Perf报告分析与USB读写性能优化建议 根据提供的perf报告,分析结果如下: 1. **主要性能瓶颈分布**: - **读操作(50.27%)**:主要在TCP协议栈处理(`tcp_recvmsg`占49.21%) - **写操作(27.87%)**:集中在exFAT文件系统操作(`exfat_write_begin`占16.76%) - **网络ACK处理(22.17%)**:`tcp_send_ack`及协议栈开销显著 - **内存复制开销(16.16%)**:`skb_copy_datagram_iter`数据复制消耗大 2. **关键性能问题**: - **ACK风暴问题**:`tcp_send_ack`调用链占整体22.02%,频繁ACK响应拖慢传输 - **文件系统元数据瓶颈**:exFAT的簇管理(`exfat_map_cluster`/`exfat_alloc_cluster`)占写操作5.38% - **内存操作延迟**:SKB缓冲区释放(`__kfree_skb`)占5.14%,包含多次锁操作 - **页缓存竞争**:`grab_cache_page_write_begin`文件页锁争用占6.83% 3. **USB读写优化方案**: - **TCP协议栈优化**: - 启用TCP延迟ACK:`sysctl -w net.ipv4.tcp_delack_min=40`(减少ACK频率) - 增大TCP接收窗口:`sysctl -w net.core.rmem_max=16777216` - **文件系统调优**: - 使用exFAT挂载优化:`mount -o noatime,nodiratime,errors=remount-ro` - 预分配大文件:`fallocate -l 1G file.bin`减少实时簇分配 - **零拷贝改进**: - 启用`sendfile`系统调用替代read/write - 配置FTP服务器使用`AllowRetrieveRestart`/`AllowStoreRestart` - **内存管理优化**: - 调整SKB内存池:`sysctl -w net.core.high_order_alloc_disable=1` - 启用页面回收:`vm.vfs_cache_pressure=150` - **驱动层优化**: - 更新USB控制器驱动(如xhci-hcd) - 启用USB3.0 UASP模式(若硬件支持) 4. **验证方法**: ```bash # 确认优化效果 iperf3 -c <server> # 网络吞吐测试 sysbench fileio --file-test-mode=rndwr run # 存储性能测试 ftperf -s <server> -f 1GB.dat # FTP传输基准 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值