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

news2024/11/15 13:37:30

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 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,用于多窗口显示,单窗口子类。
头文件

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

源文件

#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

设备属性窗口
头文件

#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);
}

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

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

相关文章

适应CLIP作为图像去雾的聚合指导

Adapt CLIP as Aggregation Instructor for Image Dehazing 2408.12317 (arxiv.org) 大多数去雾方法都存在感受野有限的问题&#xff0c;并且没有探索视觉-语言模型中蕴含的丰富语义先验&#xff0c;这些模型已在下游任务中被证明是有效的。 本文介绍了CLIPHaze&#xff0c;这…

如何使用ssm实现汽车养护管理系统

TOC ssm038汽车养护管理系统jsp 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xff0c;规范化管理。…

NAND闪存制造商Kioxia申请IPO,预计市值达103亿美元

据《日本经济新闻》报道&#xff0c;全球第三大NAND闪存制造商Kioxia已向东京证券交易所提交了首次公开募股&#xff08;IPO&#xff09;申请&#xff0c;计划于10月上市。根据《金融时报》的消息&#xff0c;Kioxia希望通过此次IPO筹集至少5亿美元的资金&#xff0c;并可能获得…

Circuitjs web 在线电路模拟器应用简介

Circuitjs 是一款 web 在线电路模拟器, 可以在浏览器上方便地模拟各种模拟或数字的电路, 用户无需安装各种软件, 生成的电路也支持在线分享给其它用户. 访问地址 下述地址我部署的一个版本: https://cc.xiaogd.net/ 此版本的特色是界面翻译成中文时尽量保留了英文, 因此在某…

VBA语言専攻T3学员领取资料通知0823

T3学员领取资料通知0823 各位学员∶本周MF系列VBA技术资料增加706-725讲&#xff0c;T3学员看到通知后请免费领取,领取时间8月23日晚上19:00-8月24日上午11:00。本次增加内容&#xff1a; MF706:在同一页面上打印多个范围 MF707:通过合并行打印多个范围 MF708:将多表中的多…

mathtype7永久激活码密钥及2024最新序列号附安装教程

MathType7是一款强大的数学公式编辑器&#xff0c;它可以在各种文档中插入复杂的数学公式和符号。它的特点包括&#xff1a; MathType最新mac官方版本下载如下: https://wm.makeding.com/iclk/?zoneid61764 MathType最新win官方版本下载如下: https://wm.makeding.com/icl…

代谢组数据分析(十八):随机森林构建代谢组诊断模型

本文参考Metabolomic machine learning predictor for diagnosis and prognosis of gastric cancer撰写。 使用随机森林算法和LASSO特征选择构建了一种胃癌(GC)诊断预测模型。参与者(队列1,n=426)通过随机分层抽样分为发现数据集(n=284)和测试集(n=142)。接下来,在发…

社区流浪动物救助系统-计算机毕设Java|springboot实战项目

&#x1f393; 作者&#xff1a;计算机毕设小月哥 | 软件开发专家 &#x1f5a5;️ 简介&#xff1a;8年计算机软件程序开发经验。精通Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等技术栈。 &#x1f6e0;️ 专业服务 &#x1f6e0;️ 需求定制化开发源码提…

Linux下进程间的通信--信号

信号的概念&#xff1a; 在Linux操作系统中&#xff0c;信号是一种软件中断机制&#xff0c;用于通知进程某个事件已经发生。信号是Linux进程间通信&#xff08;IPC&#xff09;的一种简单且快速的方式&#xff0c;它可以用来处理各种异步事件&#xff0c;如用户输入、硬件事件…

DAG计算框架:实现业务编排

文章目录 DAG如何实现DAG计算框架Node的实现Engine的实现Graph的实现具体某个节点如何使用 在工作几年之后&#xff0c;大部分人如果还在继续做着 CRUD的简单重复工作&#xff0c;即使领导不提出对你更高的期望&#xff0c;自身也会感到焦虑吧。学如逆水行舟不进则退&#xff…

解锁Spring Boot、Prometheus与Grafana三合一:打造你的专属自定义指标炫酷大屏!

1. 集成Prometheus到Spring Boot 需要在Spring Boot应用中集成Prometheus。可以通过micrometer库来实现。micrometer是一个应用程序监控库&#xff0c;它支持多种监控系统&#xff0c;包括Prometheus。 一招制胜&#xff01;Spring Boot、Prometheus和Grafana三剑合璧&#x…

数仓工具使用Docker部署DolphinScheduler 3.2.0 (分布式任务调度系统)-单机模式

Apache DolphinScheduler——开源大数据调度器神器 Apache DolphinScheduler(海豚调度),国人之光&#xff0c;是许多国人雷锋开源在Apache的顶级项目&#xff0c;主要功能就是负责任务的调度处理&#xff0c;Apache DolphinScheduler是一个分布式去中心化&#xff0c;易扩展的可…

C++--map和set

目录 1. 关联式容器 2. 键值对 3. 树形结构的关联式容器 3.1 set 3.2 map 3.3 multiset 3.4 multimap 4.底层结构 4.3红黑树与AVL树的比较 1. 关联式容器 前面我们已经接触过 STL 中的部分容器&#xff0c;比如&#xff1a; vector 、 list 、 deque、 forward_list(…

自建CDN/WAF解决方案--GoEdge

目录 概述 核心功能 典型应用场景 优点 适用对象 安装 使用 域名准备 DNSPOD的API秘钥申请 添加DNS厂商账号 添加集群 添加节点 添加网站 工作原理 概述 GoEdge 是一款高性能的、支持多种功能的反向代理服务器&#xff0c;通常用于流量管理、负载均衡、安全防护等…

layui2.9 树组件默认无法修改节点图标,修改过程记录下

官方文档树组件 data 参数值&#xff0c;未提供icon属性配置 需要修改源码 layui.js, 搜索图片中标记部分 查找到之后&#xff0c;修改为 <i class“‘(i.icon || “layui-icon layui-icon-file”)’”> 如图&#xff1a; 修改完成后&#xff0c;即可在data中添加icon…

Mysql双主双从

双主双从 1.安装Mysql1.1 查看linux版本1.2 下载Mysql安装包1.3 上传并解压1.4 安装Mysql1.5 编辑端口号1.6 Mysql启动命令1.7 更新密码 2.搭建Mysql主从复制2.1 搭建Master主服务器2.1.1 修改mysql配置文件2.1.2 重启Mysql服务2.1.3 创建Slave用户, 并授权2.1.4 查看主服务器当…

RTOS实战项目之实现多任务系统

文章目录 一、RTOS引入二、任务的引入2.1 任务的定义2.2 理解C函数的内部机制2.3 ARM架构2.4 汇编指令2.5 怎么保存函数的现场①要保存什么②保存现场的几种场景 三、FreeRTOS中怎么创建任务四、通过链表深入理解调度机制4.1 优先级与状态4.2 调度方法 五、创建任务—伪造现场5…

Python青少年简明教程:赋值语句

Python青少年简明教程&#xff1a;赋值语句 变量赋值是指将一个值分配给变量的过程。Python 支持多种形式的赋值&#xff08;assignment&#xff09;&#xff0c;包括基本赋值、多重赋值、链式赋值和解包赋值等。 为了深入理解Python赋值语句机制&#xff0c;先了解一下id()函数…

[Meachines] [Easy] Legacy nmap 漏洞扫描脚本深度发现+MS08-067

信息收集 IP AddressOpening Ports10.10.10.4TCP:135,139,445 $ nmap -p- 10.10.10.4 --min-rate 1000 -sC -sV -Pn PORT STATE SERVICE VERSION 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows n…

战略合作篇白皮书:深度革新,赋能企业跃迁

01背景 企业数字化转型已经成为当今商业环境中不可避免的趋势&#xff0c;主要有以下几个原因&#xff1a; 技术发展&#xff1a;随着信息技术的迅猛发展和普及&#xff0c;企业面临着数字化转型的迫切需求。云计算、大数据、人工智能等技术正在改变商业模式和运营方式&#xf…