MVS下载链接:https://www.hikrobotics.com/cn/machinevision/service/download/?module=0
CMake工程构建参考:CMake|VS2017+CMake3.8搭建Qt项目
文章目录
- 效果图
- 整体结构
- 实现代码
- 最外层CMakeLists.txt
- 代码实现及CMakeLists.txt搭建
- CMakeLists.txt搭建
- 主函数
- MainWindow
- DeviceListDockWidget
- Struct.h
- ImageShowDockWidget
- OneImageWindow
- AttributeListDockWidget
效果图
只用Qt实现了显示效果,并没有实现具体功能,仅供学习使用,如有侵权请私信我删除。
整体结构
实现代码
最外层CMakeLists.txt
# CMakeList.txt : Top-level CMake project file, do global configuration
# and include sub-projects here.
#
cmake_minimum_required (VERSION 3.8)project ("MVSImitateCMake")# Include sub-projects.
add_subdirectory ("MVSImitateCMake")
代码实现及CMakeLists.txt搭建
CMakeLists.txt搭建
# CMakeList.txt : CMake project for MVSImitateCMake, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.8)# 设置C++标准 C++17
set(CMAKE_CXX_STANDARD 17)# 自动把ui转化为C++代码
# uic qtcmake.ui > ui_qtcmake.h
set(CMAKE_AUTOUIC ON)# 自动生成元对象的C++代码
set(CMAKE_AUTOMOC ON)# 自动生成资源文件
set(CMAKE_AUTORCC ON)# --- 执行文件输出路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)set(INCLUDE_DIR ./include)
set(SRC_DIR ./src)include_directories(${INCLUDE_DIR})
file(GLOB_RECURSE HEADER "${INCLUDE_DIR}/*.h")
file(GLOB_RECURSE SOURCES "${SRC_DIR}/*.cpp")# Add source to this project's executable.
add_executable (MVSImitateCMake MVSImitateCMake.cpp ${HEADER} ${SOURCES})# TODO: Add tests and install targets if needed.
# find_package 查找内部库
# 导入qt的库
# cmake通过qt5提供的查找方案,去查找对应的库
# 这里以查找 Widgets库 为例
find_package(Qt5 COMPONENTS Widgets REQUIRED)# 根据自己电脑的环境,写死的指定Qt5_DIR这个变量
# 目的是寻找 Qt5Config.cmake 这个文件
set(Qt5_DIR C:/Qt/Qt5.14.2/5.14.2/msvc2017_64/lib/cmake/Qt5)# 指定qt依赖的动态库
# Qt5 自带连接头文件
target_link_libraries(${PROJECT_NAME}Qt5::Widgets
)
主函数
头文件
// MVSImitateCMake.h : Include file for standard system include files,
// or project specific include files.#pragma once#include <iostream>
#include <QtWidgets>
#include <QApplication>#include "MainWindow.h"// TODO: Reference additional headers your program requires here.
源文件
// MVSImitateCMake.cpp : Defines the entry point for the application.
//#include "MVSImitateCMake.h"using namespace std;int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow main_window;main_window.show();return a.exec();
}
从主函数引用顺序来展示各个类的代码
MainWindow
搭建整体UI架构,创建DeviceListDockWidget类、ImageShowDockWidget类、AttributeListDockWidget类,分别为设备列表、图像显示区域、属性窗口区域。
头文件
#pragma once
#include <qmainwindow.h>
#include <QSplitter>
#include "DeviceList.h"
#include "ImageShow.h"
#include "AttributeList.h"class MainWindow :public QMainWindow
{Q_OBJECT
public:MainWindow();~MainWindow();private:void Init();DeviceListDockWidget* device_list_;ImageShowDockWidget* image_show_;AttributeListDockWidget* attribute_list_;
};
源文件
#include "MainWindow.h"
#include<QMenuBar>
#include<QToolBar>
#include <QLabel>
#include <QStatusBar>
#include <QHBoxLayout>MainWindow::MainWindow()
{Init();
}MainWindow::~MainWindow()
{
}void MainWindow::Init()
{resize(1700, 950);QSplitter* main_widget = new QSplitter(this);this->setCentralWidget(main_widget);//包含菜单栏,只能有一个QMenuBar * bar = menuBar();//将菜单栏放入到窗口中this->setMenuBar(bar);//创建文件菜单QMenu * dockWidgetMenu = bar->addMenu(QStringLiteral("窗口"));//QMenu * editMenu = bar->addMenu(QStringLiteral("编辑"));//添加菜单项QAction * deviceAction = dockWidgetMenu->addAction(QStringLiteral("设备列表"));deviceAction->setCheckable(true);//添加分割线//dockWidgetMenu->addSeparator();QAction * ImageAction = dockWidgetMenu->addAction(QStringLiteral("图像显示"));ImageAction->setCheckable(true);//添加分割线//dockWidgetMenu->addSeparator();QAction * AttributeAction = dockWidgetMenu->addAction(QStringLiteral("属性信息"));AttributeAction->setCheckable(true);//工具栏,可以有多个QToolBar * toolBar = new QToolBar(this);addToolBar(Qt::TopToolBarArea, toolBar);//默认停靠范围//只允许左右侧停靠//toolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);//设置浮动toolBar->setFloatable(false);//设置移动(总开关)toolBar->setMovable(false);//工具栏添加菜单项toolBar->addAction(deviceAction);//添加分割线toolBar->addSeparator();toolBar->addAction(ImageAction);toolBar->addSeparator();toolBar->addAction(AttributeAction);//状态栏,只能有一个//QStatusBar * stBar = statusBar();//setStatusBar(stBar);//QLabel * label = new QLabel(QStringLiteral("提示信息"), this);//stBar->addWidget(label);//添加提示信息到左侧//QLabel * label2 = new QLabel(QStringLiteral("右侧提示信息"), this);//stBar->addPermanentWidget(label2);device_list_ = new DeviceListDockWidget;QHBoxLayout* main_layout = new QHBoxLayout;main_layout->addWidget(device_list_,1);image_show_ = new ImageShowDockWidget;main_layout->addWidget(image_show_,5);attribute_list_ = new AttributeListDockWidget;main_layout->addWidget(attribute_list_, 2);main_widget->setLayout(main_layout);// 设备列表显隐connect(deviceAction, &QAction::toggled, device_list_, [=](bool state) {device_list_->setHidden(!state);});connect(device_list_, &QDockWidget::visibilityChanged, deviceAction, &QAction::setChecked);// 图像显示区域显隐connect(ImageAction, &QAction::toggled, image_show_, [=](bool state) {image_show_->setHidden(!state);});connect(image_show_, &QDockWidget::visibilityChanged, ImageAction, &QAction::setChecked);;// 属性列表显隐connect(AttributeAction, &QAction::toggled, attribute_list_, [=](bool state) {attribute_list_->setHidden(!state);});connect(attribute_list_, &QDockWidget::visibilityChanged, AttributeAction, &QAction::setChecked);
}
DeviceListDockWidget
设备列表类继承QDockWidget类
头文件
#pragma once
#include <QApplication>
#include <QClipboard>
#include <QDockWidget>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QVBoxLayout>
#include <QMenu>
#include <QMenuBar>
#include <QAction>
#include <QToolBar>
#include <QLabel>
#include <QStatusBar>
#include <QLabel>
#include <QTableWidget>
#include <QTableWidgetItem>
#include <QSplitter>
#include <QHeaderView>
#include <Struct.h>class DeviceListDockWidget :public QDockWidget
{Q_OBJECT
public:DeviceListDockWidget();~DeviceListDockWidget();private:void Init();void InitSlot();void InitDeviceInfoTable();void AddGigECameraTreeItem(QString _camera_name);void AddUSBCameraTreeItem(QString _camera_name);void RefreshDeviceInfoTable(QString _camera_name,DeviceInfo _device_info);void RefreshGigEInfo(GigEDeviceInfo _gige_info);void RefreshUSBInfo(USBDeviceInfo _usb_info);DeviceInfo GetDeviceInfo(QString _camera_name);private slots:void SlotClickedDeviceList(QTreeWidgetItem* _item);void SlotShowMenuPos(const QPoint &pos);void SlotMenu(QAction* _action);private://QMap<QString, DeviceInfo> all_device;QVBoxLayout* main_layout;QTreeWidget *device_list;QTreeWidgetItem* GigE_root;QTreeWidgetItem* USB_root;QTableWidget* device_info_table;QMenu* copy_menu;QAction* copy_select;QAction* copy_all;
};
源文件
#include "DeviceList.h"DeviceListDockWidget::DeviceListDockWidget()
{Init();InitSlot();
}DeviceListDockWidget::~DeviceListDockWidget()
{
}void DeviceListDockWidget::Init()
{//QWidget * main_widget = new QWidget;QSplitter * main_widget = new QSplitter(Qt::Vertical, nullptr);main_layout = new QVBoxLayout;main_widget->setLayout(main_layout);device_list = new QTreeWidget();device_list->resize(350, 700);device_list->setHeaderLabel(QStringLiteral("设备列表"));GigE_root = new QTreeWidgetItem(device_list);GigE_root->setText(0, "GigE");device_list->addTopLevelItem(GigE_root);AddGigECameraTreeItem("GigECamera1");AddGigECameraTreeItem("GigECamera2");USB_root = new QTreeWidgetItem(device_list);USB_root->setText(0, "USB");device_list->addTopLevelItem(USB_root);device_list->expandAll();main_layout->addWidget(device_list);AddUSBCameraTreeItem("USBCamera1");AddUSBCameraTreeItem("USBCamera2");InitDeviceInfoTable();this->setWidget(main_widget);}void DeviceListDockWidget::InitSlot()
{// 切换设备信息connect(device_list, &QTreeWidget::itemClicked, this, &DeviceListDockWidget::SlotClickedDeviceList);// 右键设备信息显示菜单复制connect(device_info_table, &QTableWidget::customContextMenuRequested, this, &DeviceListDockWidget::SlotShowMenuPos);// 将内容复制到剪切板connect(copy_menu, &QMenu::triggered, this, &DeviceListDockWidget::SlotMenu);
}void DeviceListDockWidget::InitDeviceInfoTable()
{//QVBoxLayout* table_layout = new QVBoxLayout;device_info_table = new QTableWidget(2, 2);// 设置水平滚动条策略为按需显示device_info_table->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);// 获取水平表头QHeaderView *hHeaderView = device_info_table->horizontalHeader();// 设置列的调整模式为根据内容自动调整大小hHeaderView->setSectionResizeMode(QHeaderView::Stretch);device_info_table->verticalHeader()->setVisible(false);device_info_table->horizontalHeader()->setVisible(false);// 起始行 起始列 合并的行数 合并的列数device_info_table->setSpan(0, 0, 1, 2);device_info_table->setSpan(1, 0, 1, 2);device_info_table->setEditTriggers(QAbstractItemView::NoEditTriggers);QTableWidgetItem *item1 = new QTableWidgetItem(QStringLiteral("设备信息"));item1->setTextAlignment(Qt::AlignCenter);device_info_table->setItem(0, 0, item1);QTableWidgetItem *item2 = new QTableWidgetItem(QStringLiteral("暂无设备信息"));item2->setTextAlignment(Qt::AlignCenter);device_info_table->setItem(1, 0, item2);// 设置列宽device_info_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);device_info_table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Interactive);//device_info_table->setColumnWidth(0, 75);// 设置菜单栏右键复制device_info_table->setContextMenuPolicy(Qt::CustomContextMenu);copy_menu = new QMenu(device_info_table);copy_select = new QAction(copy_menu);copy_select->setText(QStringLiteral("复制"));copy_menu->addAction(copy_select);copy_all = new QAction(copy_menu);copy_all->setText(QStringLiteral("复制全部"));copy_menu->addAction(copy_all);//table_layout->addWidget(device_info_table);main_layout->addWidget(device_info_table);}void DeviceListDockWidget::AddGigECameraTreeItem(QString _camera_name)
{QTreeWidgetItem* GigE_camera = new QTreeWidgetItem(GigE_root);GigE_camera->setText(0, _camera_name);GigE_root->addChild(GigE_camera);
}void DeviceListDockWidget::AddUSBCameraTreeItem(QString _camera_name)
{QTreeWidgetItem* usb_camera = new QTreeWidgetItem(USB_root);usb_camera->setText(0, _camera_name);USB_root->addChild(usb_camera);
}void DeviceListDockWidget::RefreshDeviceInfoTable(QString _camera_name, DeviceInfo _device_info)
{// 删除第一行外所有内容for (int i = device_info_table->rowCount() - 1; i >= 1; --i){device_info_table->removeRow(i);}if (_camera_name == "GigECamera1" || _camera_name == "GigECamera2"){RefreshGigEInfo(_device_info.gige_info);}else if (_camera_name == "USBCamera1" || _camera_name == "USBCamera2"){RefreshUSBInfo(_device_info.usb_info);}else{int rowCount = device_info_table->rowCount();device_info_table->insertRow(rowCount);QTableWidgetItem *item2 = new QTableWidgetItem(QStringLiteral("暂无设备信息"));item2->setTextAlignment(Qt::AlignCenter);device_info_table->setItem(1, 0, item2);device_info_table->setSpan(1, 0, 1, 2);}
}void DeviceListDockWidget::RefreshGigEInfo(GigEDeviceInfo _gige_info)
{int rowCount = device_info_table->rowCount();QStringList gige_info_list;gige_info_list << QStringLiteral("设备名称")<< QStringLiteral("物理地址")<< QStringLiteral("IP地址")<< QStringLiteral("子网掩码")<< QStringLiteral("网关")<< QStringLiteral("厂商")<< QStringLiteral("型号")<< QStringLiteral("序列号")<< QStringLiteral("设备版本")<< QStringLiteral("占用者IP");QStringList gige_info_list2;gige_info_list2 << _gige_info.device_name << _gige_info.physical_address << _gige_info.ip_address<< _gige_info.net_mask << _gige_info.gateway << _gige_info.manufacturer<< _gige_info.device_model << _gige_info.serial_num << _gige_info.device_version<< _gige_info.occupant_ip;for (int i=0;i<gige_info_list.size();++i){device_info_table->insertRow(rowCount + i);device_info_table->setItem(rowCount + i, 0, new QTableWidgetItem(gige_info_list.at(i)));device_info_table->setItem(rowCount + i, 1, new QTableWidgetItem(gige_info_list2.at(i)));}//device_info_table->resizeColumnsToContents();
}void DeviceListDockWidget::RefreshUSBInfo(USBDeviceInfo _usb_info)
{int rowCount = device_info_table->rowCount();QStringList usb_info_list;usb_info_list << QStringLiteral("设备名称") << QStringLiteral("型号") << QStringLiteral("序列号")<< QStringLiteral("GUID") << QStringLiteral("厂商") << QStringLiteral("设备版本");QStringList usb_info_list2;usb_info_list2 << _usb_info.device_name<< _usb_info.device_model<< _usb_info.serial_num<< _usb_info.usb_guid<< _usb_info.manufacturer<< _usb_info.device_version;for (int i = 0; i < usb_info_list.size(); ++i){device_info_table->insertRow(rowCount + i);device_info_table->setItem(rowCount + i, 0, new QTableWidgetItem(usb_info_list.at(i)));device_info_table->setItem(rowCount + i, 1, new QTableWidgetItem(usb_info_list2.at(i)));}//device_info_table->resizeColumnsToContents();
}DeviceInfo DeviceListDockWidget::GetDeviceInfo(QString _camera_name)
{DeviceInfo device_info;if ("GigECamera1" == _camera_name || "GigECamera2" == _camera_name){if ("GigECamera1" == _camera_name)device_info.gige_info.device_name = "GigECamera1";else if ("GigECamera2" == _camera_name)device_info.gige_info.device_name = "GigECamera2";device_info.gige_info.physical_address = "ff:ff:ff:ff:ff:ff"; device_info.gige_info.ip_address = "10.1.1.111";device_info.gige_info.net_mask = "255.255.0.0";device_info.gige_info.gateway = "0.0.0.0";device_info.gige_info.manufacturer = "--------------";device_info.gige_info.device_model = "-------------";device_info.gige_info.serial_num = "-------";device_info.gige_info.device_version = "-------";device_info.gige_info.occupant_ip = "0.0.0.0";}else if ("USBCamera1" == _camera_name || "USBCamera2" == _camera_name){if ("USBCamera1" == _camera_name)device_info.usb_info.device_name = "USBCamera1";else if ("USBCamera2" == _camera_name)device_info.usb_info.device_name = "USBCamera2";device_info.usb_info.device_model = "-----";device_info.usb_info.serial_num = "-----";device_info.usb_info.usb_guid = "-----";device_info.usb_info.manufacturer = "U3V";device_info.usb_info.device_version = "-----";}return device_info;
}void DeviceListDockWidget::SlotClickedDeviceList(QTreeWidgetItem* _item)
{QString item_name = _item->text(0);RefreshDeviceInfoTable(item_name,GetDeviceInfo(item_name));
}void DeviceListDockWidget::SlotShowMenuPos(const QPoint &pos)
{QTableWidgetItem* item = device_info_table->itemAt(pos);if (item != nullptr) {if (item->column() == 1){copy_menu->exec(QCursor::pos());}}
}void DeviceListDockWidget::SlotMenu(QAction* _action)
{if (_action == copy_select){QStringList select_strs;QList<QTableWidgetItem *> select_items = device_info_table->selectedItems();for (auto item:select_items){select_strs.append(item->text());}QString select_str = select_strs.join('\n');// 将数据放入剪切板QApplication::clipboard()->setText(select_str);}else if (_action == copy_all){QStringList select_strs;for (int i=1;i<device_info_table->rowCount();++i){auto item = device_info_table->item(i, 1);select_strs.append(item->text());}QString select_str = select_strs.join('\n');// 将数据放入剪切板QApplication::clipboard()->setText(select_str);}
}
Struct.h
设备列表显示信息结构体构建
#pragma oncestruct GigEDeviceInfo
{QString device_name; // 设备名称QString physical_address; // 物理地址QString ip_address; // IP地址QString net_mask; // 子网掩码QString gateway; // 网关QString manufacturer; // 厂商QString device_model; // 型号QString serial_num; // 序列号QString device_version; // 设备版本QString occupant_ip; // 占用者IPGigEDeviceInfo(){device_name = "";physical_address = "";ip_address = "";net_mask = "";gateway = "";manufacturer = "";device_model = "";serial_num = "";device_version = "";occupant_ip = "";}
};struct USBDeviceInfo
{QString device_name; // 设备名称QString device_model; // 型号QString serial_num; // 序列号QString usb_guid; // GUIDQString manufacturer; // 厂商QString device_version; // 设备版本USBDeviceInfo(){device_name = "";device_model = "";serial_num = "";usb_guid = "";manufacturer = "";device_version = "";}
};struct DeviceInfo
{GigEDeviceInfo gige_info;USBDeviceInfo usb_info;
};
ImageShowDockWidget
图像显示区域,继承QDockWidget,包含子类OneImageWindow,用于多窗口显示,单窗口子类。
头文件
#pragma once
#include <QDockWidget>
#include <QGridLayout>
#include <qDebug>
#include "OneImageWindow.h"class ImageShowDockWidget : public QDockWidget
{Q_OBJECT
public:ImageShowDockWidget();~ImageShowDockWidget();private:void InitUI();private slots:void btnClicked(const QString &objName);private:QVector<OneImageWindow*> all_imagewindow_map;QGridLayout* main_layout;QWidget* main_widget;
};
源文件
#include "ImageShow.h"ImageShowDockWidget::ImageShowDockWidget()
{InitUI();
}ImageShowDockWidget::~ImageShowDockWidget()
{
}void ImageShowDockWidget::InitUI(){main_widget = new QWidget();main_layout = new QGridLayout();for (int i=0;i<4;++i){OneImageWindow* image_window = new OneImageWindow;image_window->setFlowEnable(true);connect(image_window, SIGNAL(btnClicked(QString)), this, SLOT(btnClicked(QString)));all_imagewindow_map.push_back(image_window);}main_layout->addWidget(all_imagewindow_map.at(0), 0, 0, 1, 1);main_layout->addWidget(all_imagewindow_map.at(1), 0, 1, 1, 1);main_layout->addWidget(all_imagewindow_map.at(2), 1, 0, 1, 1);main_layout->addWidget(all_imagewindow_map.at(3), 1, 1, 1, 1);main_widget->setLayout(main_layout);this->setWidget(main_widget);}void ImageShowDockWidget::btnClicked(const QString &objName){OneImageWindow *videoWindow = (OneImageWindow *)sender();QString str = QString("当前单击了控件 %1 的按钮 %2").arg(videoWindow->objectName()).arg(objName);//ui->label->setText(str);qDebug() << str;}
OneImageWindow
单窗口显示图像子类继承QWidget
头文件
#pragma once
#include <QWidget>
#include <QImage>
#include <QColor>
#include <QHBoxLayout>
#include <QFont>
#include <QFontDatabase>
#include <QPushButton>
#include <qDebug>
#include <QDropEvent>
#include <QDragEnterEvent>
#include <QPainter>class OneImageWindow : public QWidget
{Q_OBJECTpublic:explicit OneImageWindow(QWidget *parent = 0);~OneImageWindow();signals://工具栏单击void btnClicked(const QString &objName);public:QImage getImage() const;public slots://设置是否启用悬浮条void setFlowEnable(bool flowEnable);protected:void resizeEvent(QResizeEvent *);void enterEvent(QEvent *);void leaveEvent(QEvent *);void dropEvent(QDropEvent *event);void dragEnterEvent(QDragEnterEvent *event);void paintEvent(QPaintEvent *);void drawBorder(QPainter *painter);void drawBg(QPainter *painter);void drawImg(QPainter *painter, QImage img);
private://初始化悬浮条void initFlowPanel();//初始化悬浮条样式void initFlowStyle();
private slots://处理按钮单击void btnClicked();private:QImage image; //要显示的图片QWidget *flowPanel; //悬浮条面板bool copyImage; //是否拷贝图片bool drawImage; //是否绘制图片bool fillImage; //自动拉伸填充bool flowEnable; //是否显示悬浮条QColor flowBgColor; //悬浮条背景颜色QColor flowPressColor; //悬浮条按下颜色int borderWidth; //边框宽度QColor borderColor; //边框颜色QColor focusColor; //有焦点边框颜色QColor bgColor; //背景颜色QString bgText; //默认无图像显示文字QImage bgImage; //默认无图像背景图片
};
源文件
#include "OneImageWindow.h"OneImageWindow::OneImageWindow(QWidget *parent) : QWidget(parent)
{//设置强焦点setFocusPolicy(Qt::StrongFocus);//设置支持拖放setAcceptDrops(true);image = QImage();copyImage = false;drawImage = true;fillImage = true;flowEnable = false;flowBgColor = "#000000";flowPressColor = "#5EC7D9";borderWidth = 5;borderColor = "#000000";focusColor = "#22A3A9";bgColor = Qt::transparent;bgText = QStringLiteral("实时图像");bgImage = QImage();//初始化悬浮条this->initFlowPanel();//初始化悬浮条样式this->initFlowStyle();
}
OneImageWindow::~OneImageWindow()
{
}void OneImageWindow::setFlowEnable(bool flowEnable)
{this->flowEnable = flowEnable;
}void OneImageWindow::resizeEvent(QResizeEvent *)
{//重新设置顶部工具栏的位置和宽高,可以自行设置顶部显示或者底部显示int height = 20;flowPanel->setGeometry(borderWidth, borderWidth, this->width() - (borderWidth * 2), height);//flowPanel->setGeometry(borderWidth, this->height() - height - borderWidth, this->width() - (borderWidth * 2), height);
}void OneImageWindow::enterEvent(QEvent *)
{//这里还可以增加一个判断,是否获取了焦点的才需要显示//if (this->hasFocus()) {}if (flowEnable) {flowPanel->setVisible(true);}
}void OneImageWindow::leaveEvent(QEvent *)
{if (flowEnable) {flowPanel->setVisible(false);}
}void OneImageWindow::dropEvent(QDropEvent *event)
{//拖放完毕鼠标松开的时候执行
}void OneImageWindow::dragEnterEvent(QDragEnterEvent *event)
{//拖曳进来的时候先判断下类型,非法类型则不处理}void OneImageWindow::paintEvent(QPaintEvent *)
{//如果不需要绘制if (!drawImage) {return;}//qDebug() << TIMEMS << "paintEvent" << objectName();QPainter painter(this);painter.setRenderHints(QPainter::Antialiasing);//绘制边框drawBorder(&painter);if (!image.isNull()) {//绘制背景图片drawImg(&painter, image);}else {//绘制背景drawBg(&painter);}
}void OneImageWindow::drawBorder(QPainter *painter)
{painter->save();QPen pen;pen.setWidth(borderWidth);pen.setColor(hasFocus() ? focusColor : borderColor);//边框宽度=0则不绘制边框painter->setPen(borderWidth == 0 ? Qt::NoPen : pen);//顺带把背景颜色这里也一并处理if (bgColor != Qt::transparent) {painter->setBrush(bgColor);}painter->drawRect(rect());painter->restore();
}void OneImageWindow::drawBg(QPainter *painter)
{painter->save();//背景图片为空则绘制文字,否则绘制背景图片if (bgImage.isNull()) {painter->setFont(this->font());painter->setPen(palette().windowText().color());painter->drawText(rect(), Qt::AlignCenter, bgText);}else {//居中绘制int x = rect().center().x() - bgImage.width() / 2;int y = rect().center().y() - bgImage.height() / 2;QPoint point(x, y);painter->drawImage(point, bgImage);}painter->restore();
}void OneImageWindow::drawImg(QPainter *painter, QImage img)
{painter->save();int offset = borderWidth * 1 + 0;if (fillImage) {QRect rect(offset / 2, offset / 2, width() - offset, height() - offset);painter->drawImage(rect, img);}else {//按照比例自动居中绘制img = img.scaled(width() - offset, height() - offset, Qt::KeepAspectRatio);int x = rect().center().x() - img.width() / 2;int y = rect().center().y() - img.height() / 2;QPoint point(x, y);painter->drawImage(point, img);}painter->restore();
}void OneImageWindow::initFlowPanel()
{//顶部工具栏,默认隐藏,鼠标移入显示移除隐藏flowPanel = new QWidget(this);flowPanel->setObjectName("flowPanel");flowPanel->setVisible(false);//用布局顶住,左侧弹簧QHBoxLayout *layout = new QHBoxLayout;layout->setSpacing(2);layout->setContentsMargins(0, 0, 0, 0);layout->addStretch();flowPanel->setLayout(layout);//按钮集合名称,如果需要新增按钮则在这里增加即可QList<QString> btns;btns << "btnFlowVideo" << "btnFlowSnap" << "btnFlowSound" << "btnFlowAlarm" << "btnFlowClose";//有多种办法来设置图片,qt内置的图标+自定义的图标+图形字体//既可以设置图标形式,也可以直接图形字体设置文本
#if 0QList<QIcon> icons;icons << QApplication::style()->standardIcon(QStyle::SP_ComputerIcon);icons << QApplication::style()->standardIcon(QStyle::SP_FileIcon);icons << QApplication::style()->standardIcon(QStyle::SP_DirIcon);icons << QApplication::style()->standardIcon(QStyle::SP_DialogOkButton);icons << QApplication::style()->standardIcon(QStyle::SP_DialogCancelButton);
#elseQList<int> icons;icons << 0xe68d << 0xe672 << 0xe674 << 0xea36 << 0xe74c;//判断图形字体是否存在,不存在则加入QFont iconFont;QFontDatabase fontDb;if (!fontDb.families().contains("iconfont")) {int fontId = fontDb.addApplicationFont(":/font/iconfont.ttf");QStringList fontName = fontDb.applicationFontFamilies(fontId);if (fontName.count() == 0) {qDebug() << "load iconfont.ttf error";}}if (fontDb.families().contains("iconfont")) {iconFont = QFont("iconfont");iconFont.setPixelSize(17);
#if (QT_VERSION >= QT_VERSION_CHECK(4,8,0))iconFont.setHintingPreference(QFont::PreferNoHinting);
#endif}
#endif//循环添加顶部按钮for (int i = 0; i < btns.count(); ++i) {QPushButton *btn = new QPushButton;//绑定按钮单击事件,用来发出信号通知connect(btn, SIGNAL(clicked(bool)), this, SLOT(btnClicked()));//设置标识,用来区别按钮btn->setObjectName(btns.at(i));//设置固定宽度btn->setFixedWidth(20);//设置拉伸策略使得填充btn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);//设置焦点策略为无焦点,避免单击后焦点跑到按钮上btn->setFocusPolicy(Qt::NoFocus);#if 0//设置图标大小和图标btn->setIconSize(QSize(16, 16));btn->setIcon(icons.at(i));
#elsebtn->setFont(iconFont);//btn->setText((QChar)icons.at(i));btn->setText(btns.at(i));
#endif//将按钮加到布局中layout->addWidget(btn);}
}void OneImageWindow::initFlowStyle()
{//设置样式以便区分,可以自行更改样式,也可以不用样式QStringList qss;QString rgba = QString("rgba(%1,%2,%3,150)").arg(flowBgColor.red()).arg(flowBgColor.green()).arg(flowBgColor.blue());qss.append(QString("#flowPanel{background:%1;border:none;}").arg(rgba));qss.append(QString("QPushButton{border:none;padding:0px;background:rgba(0,0,0,0);}"));qss.append(QString("QPushButton:pressed{color:%1;}").arg(flowPressColor.name()));
}void OneImageWindow::btnClicked()
{QPushButton *btn = (QPushButton *)sender();Q_EMIT btnClicked(btn->objectName());
}QImage OneImageWindow::getImage() const
{return this->image;
}
AttributeListDockWidget
设备属性窗口
头文件
#pragma once
#include <QApplication>
#include <QClipboard>
#include <QDockWidget>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QMenu>
#include <QMenuBar>
#include <QAction>
#include <QToolBar>
#include <QLabel>
#include <QTableWidget>
#include <QLineEdit>
#include <QTableWidgetItem>
#include <QSplitter>
#include <QHeaderView>
#include <QTextBrowser>class AttributeListDockWidget :public QDockWidget
{Q_OBJECT
public:AttributeListDockWidget();~AttributeListDockWidget();private:void Init();void InitSlot();void InitRootTree();private slots:private:QTreeWidget* root_tree;QTreeWidget* child_tree;QLineEdit* retrieval_lineEdit;QTextBrowser* retrieval_text;QTreeWidgetItem* feature_node; // 属性树节点QTreeWidgetItem* common_features_node; // 常用属性节点QTreeWidgetItem* trigger_node; // 触发QTreeWidgetItem* advanced_features_node; // 高级属性
};
源文件
#include "AttributeList.h"AttributeListDockWidget::AttributeListDockWidget()
{Init();InitSlot();
}AttributeListDockWidget::~AttributeListDockWidget()
{
}void AttributeListDockWidget::Init()
{QWidget* main_widget = new QWidget();this->setWidget(main_widget);QHBoxLayout* main_layout = new QHBoxLayout();main_widget->setLayout(main_layout);QVBoxLayout* root_list = new QVBoxLayout();QHBoxLayout* retrieval_layout = new QHBoxLayout();QLabel* retrieval_label = new QLabel(QStringLiteral("检索:"));retrieval_layout->addWidget(retrieval_label);retrieval_lineEdit = new QLineEdit();retrieval_layout->addWidget(retrieval_lineEdit);root_list->addLayout(retrieval_layout);InitRootTree();root_list->addWidget(root_tree);main_layout->addLayout(root_list);QSplitter* retrieval_splitter = new QSplitter(Qt::Vertical, nullptr);child_tree = new QTreeWidget();child_tree->setHeaderHidden(true);retrieval_splitter->addWidget(child_tree);retrieval_text = new QTextBrowser();retrieval_splitter->addWidget(retrieval_text);main_layout->addWidget(retrieval_splitter);
}void AttributeListDockWidget::InitSlot()
{}void AttributeListDockWidget::InitRootTree()
{root_tree = new QTreeWidget();root_tree->resize(350, 700);root_tree->setHeaderHidden(true);feature_node = new QTreeWidgetItem(root_tree);feature_node->setText(0, "Feature Tree");root_tree->addTopLevelItem(feature_node);common_features_node = new QTreeWidgetItem(root_tree);common_features_node->setText(0, "Common Features");root_tree->addTopLevelItem(common_features_node);trigger_node = new QTreeWidgetItem(root_tree);trigger_node->setText(0, "Trigger");root_tree->addTopLevelItem(trigger_node);advanced_features_node = new QTreeWidgetItem(root_tree);advanced_features_node->setText(0, "Advanced Features");root_tree->addTopLevelItem(advanced_features_node);
}