效果
主要功能及逻辑介绍
- 界面上导入俩类八张图片,其控件皆为QLabel,导入的图片可以缩放,拖动,还原。导入的方式分为双击选择文件导入,和直接拖拽导入等。
- 总的布局结构为:一个水平布局中插入俩个组,每个组中插入一个网格布局,网格布局中设置各种控件
- 要实现QLabel的缩放与拖拽等功能,需要重写QLabel,重写paintEventd,mouseMoveEvent等函数。重写后想要鼠标悬停显示字体,还需重写event,设置对应得ToolTip。
- 要得到双击弹窗选择路径,需要重写事件过滤器eventFilter
- 拖拽进入QLabel可以选择使用事件过滤器进行处理,也可以选择重写dropEvent与eventFilter函数来实现,注意要先设置好允许拖拽
.h代码(代码需要修正)
#include <QComboBox>
#include <QFileDialog>
#include <QGroupBox>
#include <QPainter>
#include <QToolTip>
#define LABLE_WIDTH 150
#define LABLE_HEIGHT 150
class MyWidget;
class MyLable;
class IamgeSourceWidget : public QWidget
{
friend class MyWidget;
public:
IamgeSourceWidget(QWidget *parnt = nullptr);
void inIt();
/// @brief 选择资源图片文件
/// @param plabel
/// @param isPNG 是否为PNG
void switchFileImage(QLabel *plabel, bool isPNG = false);
/// @brief 设置label参数
/// @param pLabel
void setLabelParam(QLabel *pLabel);
/// @brief 加载已有图片
/// @param var
void setInitLabelImage(const QVariant &var, QLabel *label);
protected:
/// @brief label事件过滤器
/// @param obj
/// @param event
/// @return
virtual bool eventFilter(QObject *obj, QEvent *event) override;
private:
//***PNG控件组***//
MyLable *pngNormalLabel;
MyLable *pngDisableLabel;
MyLable *pngWarningLabel;
MyLable *pngErrorLabel;
QGroupBox *pngGroupBox;
//***SVG控件组***//
MyLable *svgNormalLabel;
MyLable *svgDisableLabel;
MyLable *svgWarningLabel;
MyLable *svgErrorLabel;
QGroupBox *svgGroupBox;
QList<QString> picNames; // PNG名称
QList<QString> svgNames; // SVG名称
MyWidget *myWidget; // 二级弹窗界面
}
class MyWidget : public QWidget
{
public:
MyWidget(IamgeSourceWidget *image, QLabel *label, QWidget *parnt = 0);
public slots:
void onSoureButton();
void onDrawButton();
private:
QLineEdit *edit;
QPushButton *soureButton;
QPushButton *drawButton;
QLabel *mLabel;
IamgeSourceWidget *mImage;
};
class MyLable : public QLabel
{
public:
MyLable(QString str, QWidget *parnt = nullptr);
protected:
void paintEvent(QPaintEvent *) override;
void mouseMoveEvent(QMouseEvent *ev) override;
void mousePressEvent(QMouseEvent *ev) override;
void mouseReleaseEvent(QMouseEvent *ev) override;
void wheelEvent(QWheelEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
void changeWheelValue(QPoint event, int value);
bool event(QEvent *e) override;
private:
double m_scaleValue; // 图片缩放倍数
QPointF m_drawPoint; // 绘图起点
QPointF m_mousePoint; // 鼠标当前位置点
QRect m_rectPixmap; // 被绘图片的矩形范围
bool m_isMousePress; // 鼠标是否按下
const double SCALE_MAX_VALUE; // 最大放大到原来的10倍
const double SCALE_MIN_VALUE; // 最小缩小到原来的0.5倍
QString strs;
};
.cpp代码(代码需要修正)
#include "WizardIamgeSourceWidget.h"
IamgeSourceWidget::IamgeSourceWidget( QWidget *parnt) : QWidget(parnt)
{
picNames << tr("正常状态图片") << tr("禁用状态图片") << tr("警告状态图片") << tr("错误状态图片");
svgNames << tr("0°图片") << tr("90°图片") << tr("180°图片") << tr("270°图片");
inIt();
}
void IamgeSourceWidget::inIt()
{
this->isElec = isElec;
pngGroupBox = new QGroupBox(tr("PNG图片"));
QGridLayout *pnglayout = new QGridLayout(this);
pngNormalLabel = new QLabel(picNames.at(0), this);
setInitLabelImage(picA.value(Kcc::BlockDefinition::A_NORMAL_PIC), pngNormalLabel);
setLabelParam(pngNormalLabel);
pngDisableLabel = new MyLable(picNames.at(1));
setInitLabelImage(picA.value(Kcc::BlockDefinition::A_NORMAL_PIC), pngDisableLabel);
setLabelParam(pngDisableLabel);
pngWarningLabel = new MyLable(picNames.at(2));
setInitLabelImage(picA.value(Kcc::BlockDefinition::A_WARNING_PIC), pngWarningLabel);
setLabelParam(pngWarningLabel);
pngErrorLabel = new MyLable(picNames.at(3));
setInitLabelImage(picA.value(Kcc::BlockDefinition::A_ERROR_PIC), pngErrorLabel);
setLabelParam(pngErrorLabel);
pnglayout->addWidget(pngNormalLabel, 0, 0, 1, 1);
pnglayout->addWidget(pngDisableLabel, 0, 1, 1, 1);
pnglayout->addWidget(pngWarningLabel, 1, 0, 1, 1);
pnglayout->addWidget(pngErrorLabel, 1, 1, 1, 1);
pngGroupBox->setLayout(pnglayout);
svgGroupBox = new QGroupBox(tr("SVG图片"));
QGridLayout *svglayout = new QGridLayout(this);
svgNormalLabel = new MyLable(svgNames.at(0));
setInitLabelImage(picB.value(Kcc::BlockDefinition::B_NORMAL_PIC), svgNormalLabel);
setLabelParam(svgNormalLabel);
svgDisableLabel = new MyLable(svgNames.at(1));
setInitLabelImage(picB.value(Kcc::BlockDefinition::B_DISABLE_PIC), svgDisableLabel);
setLabelParam(svgDisableLabel);
svgWarningLabel = new MyLable(svgNames.at(2));
setInitLabelImage(picB.value(Kcc::BlockDefinition::B_WARNING_PIC), svgWarningLabel);
setLabelParam(svgWarningLabel);
svgErrorLabel = new MyLable(svgNames.at(3));
setInitLabelImage(picB.value(Kcc::BlockDefinition::B_ERROR_PIC), svgErrorLabel);
setLabelParam(svgErrorLabel);
svglayout->addWidget(svgNormalLabel, 0, 0, 1, 1);
svglayout->addWidget(svgDisableLabel, 0, 1, 1, 1);
svglayout->addWidget(svgWarningLabel, 1, 0, 1, 1);
svglayout->addWidget(svgErrorLabel, 1, 1, 1, 1);
svgGroupBox->setLayout(svglayout);
QVBoxLayout *vlayout = new QVBoxLayout;
QHBoxLayout *hlayout = new QHBoxLayout;
QLabel *messable = new QLabel(tr("提示:双击选择图片,图片可以拖动,还原或缩放进行预览"));
hlayout->addWidget(pngGroupBox);
hlayout->addWidget(svgGroupBox);
vlayout->addLayout(hlayout);
vlayout->addWidget(messable);
setLayout(vlayout);
setAcceptDrops(true);
}
void IamgeSourceWidget::setInitLabelImage(const QVariant &var, QLabel *label)
{
QImage image = qvariant_cast<QImage>(var);
if (!var.isNull()) {
label->setPixmap(QPixmap::fromImage(image));
label->show();
}
}
bool IamgeSourceWidget::eventFilter(QObject *obj, QEvent *event)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
if (obj == pngNormalLabel) {
if (event->type() == QEvent::MouseButtonDblClick) {
if (mouseEvent->button() == Qt::LeftButton) {
switchFileImage(pngNormalLabel, true);
}
}
// if ((event->type() == QEvent::DragEnter)) {
// QDragEnterEvent *dee = dynamic_cast<QDragEnterEvent *>(event);
// dee->acceptProposedAction();
// return true;
// } else if (event->type() == QEvent::Drop) {
// // [[3]]: 当放操作发生后, 取得拖放的数据
// QDropEvent *de = dynamic_cast<QDropEvent *>(event);
// QList<QUrl> urls = de->mimeData()->urls();
// if (urls.isEmpty()) {
// return true;
// }
// QString path = urls.first().toLocalFile();
// // [[4]]: 在label上显示拖放的图片
// QImage image(path); // QImage对I/O优化过, QPixmap对显示优化
// if (!image.isNull()) {
// image = image.scaled(pngNormalLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
// pngNormalLabel->setPixmap(QPixmap::fromImage(image));
// }
// return true;
// }
} else if (obj == pngDisableLabel && event->type() == QEvent::MouseButtonDblClick) {
if (mouseEvent->button() == Qt::LeftButton) {
switchFileImage(pngDisableLabel, true);
}
} else if (obj == pngWarningLabel && event->type() == QEvent::MouseButtonDblClick) {
if (mouseEvent->button() == Qt::LeftButton) {
switchFileImage(pngWarningLabel, true);
}
} else if (obj == pngErrorLabel && event->type() == QEvent::MouseButtonDblClick) {
if (mouseEvent->button() == Qt::LeftButton) {
switchFileImage(pngErrorLabel, true);
}
} else if (obj == svgNormalLabel && event->type() == QEvent::MouseButtonDblClick) {
if (mouseEvent->button() == Qt::LeftButton) {
if (isElec) {
switchFileImage(svgNormalLabel);
}
}
} else if (obj == svgDisableLabel && event->type() == QEvent::MouseButtonDblClick) {
if (mouseEvent->button() == Qt::LeftButton) {
if (isElec) {
switchFileImage(svgDisableLabel);
}
}
} else if (obj == svgWarningLabel && event->type() == QEvent::MouseButtonDblClick) {
if (mouseEvent->button() == Qt::LeftButton) {
if (isElec) {
switchFileImage(svgWarningLabel);
}
}
} else if (obj == svgErrorLabel && event->type() == QEvent::MouseButtonDblClick) {
if (mouseEvent->button() == Qt::LeftButton) {
if (isElec) {
switchFileImage(svgErrorLabel);
}
}
}
return false;
}
void IamgeSourceWidget::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasUrls()) {
QList<QUrl> urls = event->mimeData()->urls();
if (urls.first().toLocalFile().endsWith(".png")) {
event->acceptProposedAction();
}
}
}
void IamgeSourceWidget::dropEvent(QDropEvent *event)
{
// 获取该位置下的子控件对象
if (event->isAccepted()) {
if (childAt(event->pos()) == pngNormalLabel) {
foreach (const QUrl &url, event->mimeData()->urls()) {
QString fileName = url.toLocalFile();
if (fileName.endsWith(".png")) {
QPixmap pixmap(fileName);
pngNormalLabel->setPixmap(pixmap);
event->acceptProposedAction();
break;
}
}
}
}
}
void IamgeSourceWidget::setLabelParam(QLabel *pLabel)
{
pLabel->setAcceptDrops(true);
pLabel->setToolTip(pLabel->text());
pLabel->installEventFilter(this);
pLabel->setFixedSize(LABLE_WIDTH, LABLE_HEIGHT);
pLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
pLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
pLabel->setFrameStyle(QFrame::Panel | QFrame::Plain);
}
void IamgeSourceWidget::switchFileImage(QLabel *plabel, bool isPNG)
{
QString static filePath;
if (!isPNG) {
filePath = QFileDialog::getOpenFileName(&QWidget(), plabel->text(), filePath, "SVG(*.svg)");
if (!filePath.isEmpty()) {
QFile file(filePath);
file.open(QFile::ReadOnly);
QByteArray svgData = file.readAll();
QSvgRenderer renderer(svgData); //绘制SVG图片防止失真
QPixmap pixmap(LABLE_WIDTH - 2, LABLE_HEIGHT - 2);
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
renderer.render(&painter);
plabel->setPixmap(pixmap);
plabel->show();
}
} else {
filePath = QFileDialog::getOpenFileName(&QWidget(), plabel->text(), filePath, "PNG(*.png)");
if (!filePath.isEmpty()) {
QImage image;
QFile file(filePath);
file.open(QFile::ReadOnly);
image.loadFromData(file.readAll());
plabel->setPixmap(QPixmap::fromImage(image));
plabel->show();
}
}
}
MyLable::MyLable(QString str, QWidget *parent)
: QLabel(parent),
m_scaleValue(1.0),
m_mousePoint(0, 0),
m_drawPoint(0, 0),
m_rectPixmap(0, 0, 0, 0),
m_isMousePress(0),
SCALE_MAX_VALUE(10.0),
SCALE_MIN_VALUE(0.5)
{
strs = str;
}
void MyLable::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QPen pen;
pen.setWidth(1);
pen.setColor(Qt::black);
painter.setPen(pen);
const QPixmap *pixmap = this->pixmap();
painter.drawRect(1, 1, LABLE_WIDTH - 2, LABLE_HEIGHT - 2);
if (!pixmap) {
painter.drawText(LABLE_WIDTH / 4, LABLE_HEIGHT / 2, strs);
return;
}
double width = this->width() * m_scaleValue;
double height = this->height() * m_scaleValue;
QPixmap scalePixmap =
this->pixmap()->scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); // 饱满缩放
m_rectPixmap = QRect(m_drawPoint.x(), m_drawPoint.y(), width, height); // 图片区域
painter.drawPixmap(m_rectPixmap, scalePixmap);
}
void MyLable::mouseMoveEvent(QMouseEvent *event)
{
if (m_isMousePress) {
int x = event->pos().x() - m_mousePoint.x();
int y = event->pos().y() - m_mousePoint.y();
m_mousePoint = event->pos();
m_drawPoint = QPointF(m_drawPoint.x() + x, m_drawPoint.y() + y);
update();
}
}
void MyLable::mousePressEvent(QMouseEvent *event)
{
if (event->type() == QEvent::MouseButtonDblClick) {
if (event->button() == Qt::LeftButton) {
return;
}
}
if (event->button() == Qt::LeftButton) {
m_isMousePress = true;
m_mousePoint = event->pos();
}
}
void MyLable::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::RightButton) {
m_drawPoint = QPointF(0, 0);
m_scaleValue = 1.0;
update();
}
if (event->button() == Qt::LeftButton)
m_isMousePress = false;
}
void MyLable::wheelEvent(QWheelEvent *event)
{
changeWheelValue(event->pos(), event->delta());
event->accept();
}
void MyLable::resizeEvent(QResizeEvent *event)
{
m_drawPoint = QPointF(0, 0);
m_scaleValue = 1.0;
update();
}
void MyLable::changeWheelValue(QPoint event, int numSteps)
{
double oldScale = m_scaleValue;
if (numSteps > 0) {
m_scaleValue *= 1.1;
} else {
m_scaleValue *= 0.9;
}
if (m_scaleValue > (SCALE_MAX_VALUE)) {
m_scaleValue = SCALE_MAX_VALUE;
}
if (m_scaleValue < (SCALE_MIN_VALUE)) {
m_scaleValue = SCALE_MIN_VALUE;
}
if (m_rectPixmap.contains(event)) {
double x = m_drawPoint.x()
- (event.x() - m_drawPoint.x()) / m_rectPixmap.width() * (this->width() * (m_scaleValue - oldScale));
double y = m_drawPoint.y()
- (event.y() - m_drawPoint.y()) / m_rectPixmap.height() * (this->height() * (m_scaleValue - oldScale));
m_drawPoint = QPointF(x, y);
} else {
double x = m_drawPoint.x() - (this->width() * (m_scaleValue - oldScale)) / 2;
double y = m_drawPoint.y() - (this->height() * (m_scaleValue - oldScale)) / 2;
m_drawPoint = QPointF(x, y);
}
update();
}
bool MyLable::event(QEvent *e)
{
if (e->type() == QEvent::ToolTip) {
QToolTip::showText(mapToGlobal(QPoint(0, 0)), strs);
return true;
}
return QLabel::event(e);
}