Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ set(PROJECT_SOURCES
enterlimiter.h enterlimiter.cpp
math.h math.cpp


)

if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(QBlueprint
MANUAL_FINALIZATION
${PROJECT_SOURCES}
enterlimiter.h enterlimiter.cpp
imagelabel.h imagelabel.cpp
)
# Define target properties for Android with Qt 6 as:
# set_property(TARGET QBlueprint APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
Expand Down
2 changes: 2 additions & 0 deletions imagelabel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#include "imagelabel.h"

108 changes: 108 additions & 0 deletions imagelabel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// 修改后的 ImageLabel.h
#ifndef IMAGELABEL_H
#define IMAGELABEL_H

#include <QLabel>
#include <QDialog>
#include <QVBoxLayout>
#include <QImage>
#include <QPixmap>
#include <QPushButton>
#include <QMouseEvent>
#include <QHBoxLayout>

class ImageLabel : public QLabel {
Q_OBJECT
public:
explicit ImageLabel(QWidget* parent = nullptr)
: QLabel(parent), imageDialog(nullptr) {
setAlignment(Qt::AlignCenter);
createButton();
}

// 设置原始的 QImage,并更新显示
void setImage(const QImage& img) {
originalImage = img; // 保存原始图像
QPixmap pixmap = QPixmap::fromImage(originalImage); // 将 QImage 转换为 QPixmap
this->setPixmap(pixmap.scaled(this->size(), Qt::KeepAspectRatio)); // 显示缩放后的图像
}

protected:
void mousePressEvent(QMouseEvent* event) override {
// 保留默认的 QLabel 行为
QLabel::mousePressEvent(event);
}

private slots:
void toggleImageDialog() {
if (imageDialog && imageDialog->isVisible()) {
// 如果图像对话框已打开,则关闭
imageDialog->close();
imageDialog->deleteLater();
imageDialog = nullptr;
} else {
// 创建并显示放大的图像
imageDialog = new QDialog();
imageDialog->setWindowFlags(Qt::Popup);

QLabel* enlargedLabel = new QLabel(imageDialog);

// 检查 originalImage 是否为空,确保图像已正确传递
if (!originalImage.isNull()) {
enlargedLabel->setPixmap(QPixmap::fromImage(originalImage).scaled(400, 400, Qt::KeepAspectRatio));
} else {
// 提示没有图像
enlargedLabel->setText("No image available");
}

QPushButton* closeButton = new QPushButton("X", imageDialog);
closeButton->setFixedSize(30, 30);

// 设置关闭按钮的点击事件
connect(closeButton, &QPushButton::clicked, [this]() {
if (imageDialog) {
imageDialog->close();
imageDialog->deleteLater();
imageDialog = nullptr;
}
});

QVBoxLayout* layout = new QVBoxLayout(imageDialog);
QHBoxLayout* topLayout = new QHBoxLayout();
topLayout->addWidget(closeButton);
topLayout->addStretch();

layout->addLayout(topLayout);
layout->addWidget(enlargedLabel);
imageDialog->setLayout(layout);

// 设置对话框的位置在主窗口旁边
QPoint globalPos = this->mapToGlobal(this->rect().topLeft());
imageDialog->move(globalPos.x() + this->width(), globalPos.y());

imageDialog->show();
}
}

public:
void setOpenButtonPos(QPointF buttonPos)
{
openButton->move(buttonPos.x(), buttonPos.y());
}
private:
QPushButton* openButton; // 控制打开/关闭的按钮
QDialog* imageDialog; // 用于显示放大图像的对话框
QImage originalImage; // 原始 QImage

void createButton() {
// 在 QLabel 的左上角创建一个按钮
openButton = new QPushButton("O", this);
openButton->setFixedSize(30, 30);
openButton->move(0, 0); // 按钮位于左上角

// 设置按钮的点击事件
connect(openButton, &QPushButton::clicked, this, &ImageLabel::toggleImageDialog);
}
};

#endif // IMAGELABEL_H
138 changes: 106 additions & 32 deletions qblueprintnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,27 +62,27 @@ QBlueprintNode* QBlueprintNode::clone() const
clonedPort->setParentItem(newNode); // 设置父项为新的 QBlueprintNode
newNode->outputPorts.push_back(clonedPort);

// 确保 LineEdit 与 OutputPort 对应
if (i < this->lineEdits.size()) {
QLineEdit* lineEdit = this->lineEdits[i];
// // 确保 LineEdit 与 OutputPort 对应
// if (i < this->lineEdits.size()) {
// QLineEdit* lineEdit = this->lineEdits[i];

// 创建新的 QLineEdit 实例,复制现有的文本内容
QLineEdit* clonedLineEdit = new QLineEdit(lineEdit->text());
clonedLineEdit->setStyleSheet("QLineEdit { border: 1px solid black; border-radius: 0px; padding: 2px; }");
// // 创建新的 QLineEdit 实例,复制现有的文本内容
// QLineEdit* clonedLineEdit = new QLineEdit(lineEdit->text());
// clonedLineEdit->setStyleSheet("QLineEdit { border: 1px solid black; border-radius: 0px; padding: 2px; }");

// 创建新的 QGraphicsProxyWidget 并将克隆的 QLineEdit 嵌入其中
QGraphicsProxyWidget* clonedProxy = new QGraphicsProxyWidget(newNode); // 父项是新的 QBlueprintNode
clonedProxy->setWidget(clonedLineEdit); // 将新的 QLineEdit 嵌入到新的代理控件中
// // 创建新的 QGraphicsProxyWidget 并将克隆的 QLineEdit 嵌入其中
// QGraphicsProxyWidget* clonedProxy = new QGraphicsProxyWidget(newNode); // 父项是新的 QBlueprintNode
// clonedProxy->setWidget(clonedLineEdit); // 将新的 QLineEdit 嵌入到新的代理控件中

QPointF outputPortPos = port->pos();
clonedProxy->setPos(outputPortPos.x() - clonedLineEdit->width() + 210, outputPortPos.y() + 35 + i * 30);
// QPointF outputPortPos = port->pos();
// clonedProxy->setPos(outputPortPos.x() - clonedLineEdit->width() + 210, outputPortPos.y() + 35 + i * 30);

// 设置克隆的 QLineEdit 大小与原始的一致
clonedProxy->resize(QSize(60, 10));
// // 设置克隆的 QLineEdit 大小与原始的一致
// clonedProxy->resize(QSize(60, 10));

// 添加克隆的 QLineEdit 到新的节点的 lineEdits 列表
newNode->lineEdits.push_back(clonedLineEdit);
}
// // 添加克隆的 QLineEdit 到新的节点的 lineEdits 列表
// newNode->lineEdits.push_back(clonedLineEdit);
// }
}
// 设置克隆节点的初始位置
newNode->setPos(this->pos());
Expand Down Expand Up @@ -177,7 +177,13 @@ QRectF QBlueprintNode::boundingRect() const
nodeWidth += maxLabelWidth;
break;
}

case DataType::QIMAGE:
{
int maxLabelWidth = 150;
nodeWidth += maxLabelWidth;
nodeHeight += (outputPorts.size()-1) * 65;
break;
}
default:
break;
}
Expand Down Expand Up @@ -298,9 +304,10 @@ void QBlueprintNode::addButtonToTopLeft()
break;
}
case DataType::QIMAGE:{
QBlueprintPort * port = addOutputPort(getEnumName(dataType));
QBlueprintPort * outputport = addOutputPort(getEnumName(dataType));
QBlueprintPort * inputport = addInputPort(getEnumName(dataType));
imageNodePortSort();
addInputLabel(port);
addOutputLabel(outputport,inputport);
break;
}
default:
Expand Down Expand Up @@ -499,15 +506,44 @@ void QBlueprintNode::customNodePortSort() {


void QBlueprintNode::imageNodePortSort() {
for (size_t i = 0; i < inputPorts.size(); ++i) {
// 将输入端口放在左侧
inputPorts[i]->setPos(5, i * 115 + 35); // 左边距
if(nodeType == Type::INPUT)
{
for (size_t i = 0; i < inputPorts.size(); ++i) {
// 将输入端口放在左侧
inputPorts[i]->setPos(5, i * 115 + 35); // 左边距
}
for (size_t i = 0; i < outputPorts.size(); ++i) {
// 将输出端口放在右侧
outputPorts[i]->setPos(boundingRect().width() - 15, i * 115 + 35); // 右边距
}
}
else
{
int eventPortHeight = 30; // 事件端口所占高度
int baseHeight = eventPortHeight; // 普通端口从这个高度开始排列
// 首先,处理输入端口
for (size_t i = 0; i < inputPorts.size(); ++i) {
if (inputPorts[i]->portType() == QBlueprintPort::EVENT_INPUT) {
// 事件端口固定在顶部位置
inputPorts[i]->setPos(5, 40); // 事件输入端口固定位置
} else {
// 普通输入端口从事件端口之后开始排列
inputPorts[i]->setPos(5, baseHeight + (i-1) * 95 + 35); // 左边距
}
}

for (size_t i = 0; i < outputPorts.size(); ++i) {
// 将输出端口放在右侧
outputPorts[i]->setPos(boundingRect().width() - 15, i * 115 + 35); // 右边距
// 其次,处理输出端口
for (size_t i = 0; i < outputPorts.size(); ++i) {
if (outputPorts[i]->portType() == QBlueprintPort::EVENT_OUTPUT) {
// 事件端口固定在顶部位置
outputPorts[i]->setPos(boundingRect().width() - 15, 40); // 事件输出端口固定位置
} else {
// 普通输出端口从事件端口之后开始排列
outputPorts[i]->setPos(boundingRect().width() - 15, baseHeight + (i-1) * 95 + 35); // 右边距
}
}
}

}


Expand Down Expand Up @@ -738,13 +774,12 @@ void QBlueprintNode::adjustLabelWidth(const QString &text) {

void QBlueprintNode::addInputLabel(QBlueprintPort* port)
{

// 创建 QWidget 作为 QGraphicsProxyWidget 的容器
QWidget* containerWidget = new QWidget();
containerWidget->setFixedSize(150, 110); // 设置容器大小,可以调整为合适的大小

// 创建 QLabel 用于显示图片
QLabel* pLabel = new QLabel(containerWidget); // 直接设置父对象为 containerWidget
ImageLabel* pLabel = new ImageLabel(containerWidget); // 直接设置父对象为 containerWidget
pLabel->setFixedSize(150, 90); // 设置 QLabel 大小
pLabel->setStyleSheet("QLabel { border: 1px solid black; }");
pLabel->setAlignment(Qt::AlignCenter); // 居中显示图片
Expand Down Expand Up @@ -773,6 +808,15 @@ void QBlueprintNode::addInputLabel(QBlueprintPort* port)
if (!filePath.isEmpty()) {
QPixmap pixmap(filePath);
pLabel->setPixmap(pixmap.scaled(pLabel->size(), Qt::KeepAspectRatio)); // 在 QLabel 中显示选中的图片
QImage image(filePath);
pLabel->setImage(image);
// 更新输出端口的 QVariant 数据为 QImage
port->setVarType(QVariant::fromValue(image));

// 将数据发送给所有连接的端口
port->sendDataToConnectedPorts();

qDebug() << "Sending converted data from QImage to connected ports.";
}
});

Expand All @@ -783,8 +827,14 @@ void QBlueprintNode::addInputLabel(QBlueprintPort* port)

void QBlueprintNode::addOutputLabel(QBlueprintPort *outport, QBlueprintPort *inport)
{
// 创建 QLineEdit
QLabel* pLabel = new QLabel("");
QLabel* pLabel = nullptr; // 声明基类指针

// 根据端口数据类型选择合适的 QLabel 类型
if(outport->portDataType() == DataType::QIMAGE) {
pLabel = new ImageLabel(); // 如果是 QIMAGE 类型,创建 ImageLabel 实例
} else {
pLabel = new QLabel("");
}
pLabel->setStyleSheet("QLineEdit { border: 1px solid black; border-radius: 0px; padding: 2px; }");

// 创建 QGraphicsProxyWidget 并将 QLineEdit 添加到该代理
Expand All @@ -799,9 +849,23 @@ void QBlueprintNode::addOutputLabel(QBlueprintPort *outport, QBlueprintPort *inp
QFontMetrics fontMetrics(inport->m_font);
int outputTextWidth = fontMetrics.horizontalAdvance(inport->name());
pMyProxy->setPos(outputPortPos.x() + outputTextWidth + 30, outputPortPos.y() - 3);

if (outport->portDataType() == DataType::QIMAGE){
pMyProxy->resize(QSize(150, 90));
connect(outport, &QBlueprintPort::dataUpdated, [pLabel](const QVariant &data) {
if (data.canConvert<QImage>()) {
QImage image = data.value<QImage>();
if (!image.isNull()) {
// 转换 QImage 为 QPixmap,并按比例缩放到 QLabel 的大小
pLabel->setPixmap(QPixmap::fromImage(image).scaled(pLabel->size(), Qt::KeepAspectRatio));
} else {
pLabel->setText("Invalid Image");
}
}
});
}
// 设置克隆的 QLineEdit 大小与原始的一致
pMyProxy->resize(QSize(100, 20));
else
pMyProxy->resize(QSize(100, 20));

// 添加克隆的 QLineEdit 到新的节点的 lineEdits 列表
outputlabel.push_back(pLabel);
Expand Down Expand Up @@ -845,7 +909,17 @@ void QBlueprintNode::processData(QBlueprintPort* inputPort, const QVariant& data
int index = std::distance(inputPorts.begin(), it) - 1;
if ((index < outputlabel.size()) /*&& isPortConnected(inputPort, outputPorts[index])*/) {
QLabel* label = outputlabel[index];
label->setText(data.toString()); // 更新 QLabel 显示的内容
if (inputPort->portDataType() == DataType::QIMAGE && data.canConvert<QImage>()) {
// 将 QVariant 数据转换为 QImage
QImage image = data.value<QImage>();
ImageLabel* imageLabel = dynamic_cast<ImageLabel*>(label); // 转化为ImageLabel
// 将 QImage 转换为 QPixmap 并设置到 QLabel
imageLabel->setImage(image);
imageLabel->setPixmap(QPixmap::fromImage(image).scaled(label->size(), Qt::KeepAspectRatio));
} else {
// 更新 QLabel 显示的其他数据内容
label->setText(data.toString()); // 更新 QLabel 显示的文本内容
}
}
}
QVariant result;
Expand Down
5 changes: 4 additions & 1 deletion qblueprintnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <algorithm>
#include <QLineEdit>
#include <QLabel>
#include "imagelabel.h"
#include <QPushButton>
#include <QVBoxLayout>
#include <QFileDialog>
Expand Down Expand Up @@ -64,6 +65,7 @@ class QBlueprintNode : public QObject, public QGraphicsItem
bool isPortConnected(QBlueprintPort *inputPort, QBlueprintPort *outputPort);
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;

private:
void setQVariantType(QBlueprintPort* port);
void customNodePortSort();
Expand Down Expand Up @@ -104,7 +106,8 @@ class QBlueprintNode : public QObject, public QGraphicsItem
std::vector<QLineEdit*> lineEdits;
std::vector<QLabel*> inputlabel;
std::vector<QLabel*> outputlabel;

std::vector<ImageLabel*> inputImagelabel;
std::vector<ImageLabel*> outputImagelabel;
void addLineEdit(QBlueprintPort* port);
void addInputLabel(QBlueprintPort* port);
void addOutputLabel(QBlueprintPort* outport, QBlueprintPort* inport);
Expand Down
6 changes: 6 additions & 0 deletions qblueprintport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@ void QBlueprintPort::sendDataToConnectedPorts() {
case DataType::UNSIGNED_INT:
convertedVar = QVariant::fromValue(var.toUInt()); // 转换为 unsigned int 类型
break;
case DataType::QIMAGE:
if (var.canConvert<QImage>()) {
QImage image = var.value<QImage>(); // 获取 QImage 对象
convertedVar = QVariant::fromValue(image); // 将 QImage 转换为 QVariant 并存储
}
break;
// 你可以根据需求添加其他类型转换逻辑...
default:
convertedVar = var; // 如果未匹配到类型,保持原样
Expand Down
Loading