Mix|使用VS2017CMake构建Qt工程 仿照MVS(仅用于学习)

MVS下载链接:https://www.hikrobotics.com/cn/machinevision/service/download/?module=0

CMake工程构建参考:CMake|VS2017+CMake3.8搭建Qt项目

文章目录

效果图

只用Qt实现了显示效果,并没有实现具体功能,仅供学习使用,如有侵权请私信我删除。

整体结构

实现代码

最外层CMakeLists.txt

bash 复制代码
# 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搭建

bash 复制代码
# 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
)

主函数

头文件

cpp 复制代码
// 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.

源文件

cpp 复制代码
// 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类,分别为设备列表、图像显示区域、属性窗口区域。

头文件

cpp 复制代码
#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_;
};

源文件

cpp 复制代码
#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类

头文件

cpp 复制代码
#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;
};

源文件

cpp 复制代码
#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

设备列表显示信息结构体构建

cpp 复制代码
#pragma once

struct 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;		// 占用者IP
	GigEDeviceInfo()
	{
		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;			// GUID
	QString 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,用于多窗口显示,单窗口子类。

头文件

cpp 复制代码
#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;
};

源文件

cpp 复制代码
#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

头文件

cpp 复制代码
#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_OBJECT

public:
	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;                 //默认无图像背景图片
};

源文件

cpp 复制代码
#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 0
	QList<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);
#else
	QList<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));
#else
		btn->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

设备属性窗口

头文件

cpp 复制代码
#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;	// 高级属性
};

源文件

cpp 复制代码
#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);
}
相关推荐
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner2 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz7 天前
QML Hello World 入门示例
qt
xcyxiner10 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner11 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner11 天前
DicomViewer (添加模型类)3
qt
xcyxiner12 天前
DicomViewer (目录调整) 2
qt
xcyxiner12 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00614 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术14 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript