由于mitk.net被人恶意抢注, 中科院分子影像重点实验室的www.mitk.net 改到 www.mitk.net.cn 。

目录:

开始  《DCMTK(MD版)编译和安装+VS2015》

第一章 《DCMTK(MD版)、QT、VS2015编写Dicom序列浏览应用程序-新建项目,配置环境》

第二章 《第二章 基于QT和DCMTK的Dicom 图像浏览器---界面设计》

第三章 《 基于QT和DCMTK的Dicom 图像浏览器---单个Dicom图像读取类》

第四章 《基于QT和DCMTK的Dicom 图像浏览器---检查文件夹下Dicom序列个数》

第五章 《基于QT和DCMTK的Dicom 图像浏览器---Dicom图像序列类》

第六章  《基于QT和DCMTK的Dicom 图像浏览器---Dicom视图类》

第七章  《基于QT和DCMTK的Dicom 图像浏览器---收尾》

一、设计视图类DicomView

1) 在项目上右键->添加->Add Qt Class ,  按照向导添加类 DicomView,如下图

2) DicomView类继承 QGraphicsView,构造标签为QWidget *parent,如下图

3) 编辑DicomView.h  和 cpp

#pragma once
#include <QGraphicsView>#include "SeriesBase.h"class QGraphicsScene;
class QGraphicsPixmapItem;
class QGraphicsWidget;
class DicomView : public QGraphicsView
{Q_OBJECTpublic:enum viewStatus {Browse,Zoom,//缩放Pan, // 移动Magnifier, // 放大镜Drawing,// 画};DicomView(QWidget *parent=0);~DicomView();void setSeries(SeriesBase*series);void resizePixmapItem(); // 窗口改变时void repositionAuxItems(); // 窗口改变时void updateView();void setHighlight(bool yes); // 边框public slots:void setCurFrameItem(int); signals:void windowChanged();// 窗宽位改变信号void clicked(SeriesBase::ViewType);// 点击protected:void mousePressEvent(QMouseEvent *event); // 鼠标按住时触发void mouseMoveEvent(QMouseEvent *event); // 鼠标移动时触发void mouseReleaseEvent(QMouseEvent *event); // 鼠标释放后触发void wheelEvent(QWheelEvent *e); // 滚轮出发void resizeEvent(QResizeEvent *event); // 窗口调整时运行QSize sizeHint() const { return hintSize; }private:QGraphicsScene *scene;// 场景QGraphicsPixmapItem *pixmapItem;//图像项 场景中的图像QGraphicsSimpleTextItem *posValueItem;// 文本项 显示当前鼠标值QGraphicsSimpleTextItem *curFrameItem; //  文本项 显示当前帧QGraphicsWidget *slider;// 控制条SeriesBase *dicoms; // 该视图显示的数据QSize hintSize;double factor;double fixFactor;// xspace/yspace 宽高的比例QPoint prevMousePos; // viewStatus status;
};
#include "DicomView.h"#include <QGraphicsPixmapItem>
#include <QGraphicsWidget>
#include <QGraphicsProxyWidget>
#include <QGraphicsLinearLayout>
#include <QMouseEvent>
#include <qslider.h>DicomView::DicomView(QWidget *parent): QGraphicsView(parent)
{scene = new QGraphicsScene(this);pixmapItem = new QGraphicsPixmapItem;posValueItem = new QGraphicsSimpleTextItem;curFrameItem = new QGraphicsSimpleTextItem;dicoms = 0;status = Browse;setFocusPolicy(Qt::StrongFocus);setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);setContextMenuPolicy(Qt::DefaultContextMenu);setBackgroundBrush(QBrush(Qt::black));setAcceptDrops(true);setFrameShape(QFrame::Box);setFrameShadow(QFrame::Plain);setAlignment(Qt::AlignCenter);setResizeAnchor(QGraphicsView::AnchorViewCenter);setHighlight(false);scene->setSceneRect(-5000, -5000, 10000, 10000);setScene(scene);// 图片切换风格pixmapItem->setTransformationMode(Qt::SmoothTransformation);pixmapItem->setAcceptHoverEvents(true);posValueItem->setBrush(Qt::magenta);curFrameItem->setBrush(Qt::magenta);scene->addItem(pixmapItem);scene->addItem(posValueItem);scene->addItem(curFrameItem);slider = new QGraphicsWidget;QGraphicsLinearLayout *verticalLayout = new QGraphicsLinearLayout;verticalLayout->setOrientation(Qt::Vertical);verticalLayout->setSpacing(0);slider->setLayout(verticalLayout);scene->addItem(slider);
}DicomView::~DicomView()
{
}void DicomView::setSeries(SeriesBase * series)
{if (!series)return;if (!series->isNormal())return;if (dicoms == 0){// 把dicoms->slider 添加到 sliderQGraphicsProxyWidget*pw = scene->addWidget(series->slider);QGraphicsLinearLayout *verticalLayout = (QGraphicsLinearLayout *)slider->layout();verticalLayout->addItem(pw);}this->dicoms = series;dicoms->setDefaultWindow();emit windowChanged();dicoms->gotoFrame(dicoms->getFrameCount() / 2);connect(dicoms->slider, SIGNAL(valueChanged(int)), this, SLOT(setCurFrameItem(int)));double xSpacing = 0, ySpacing = 0;if (dicoms->getPixSpacing(xSpacing, ySpacing)) {if (xSpacing > 0.000001 && ySpacing > 0.000001) {double psX = xSpacing;double psY = ySpacing;fixFactor = psY / psX;}}pixmapItem->setPos(0, 0);pixmapItem->setRotation(0);pixmapItem->resetTransform();updateView();scene->update(scene->sceneRect());
}void DicomView::resizePixmapItem()
{if (!pixmapItem->pixmap().isNull()) {QRectF pixmapRect = pixmapItem->boundingRect();QRectF viewRect = this->rect();//if (!manualZoom) {if (pixmapRect.width()*viewRect.height() < pixmapRect.height()*fixFactor*viewRect.width())factor = viewRect.height() / (pixmapRect.height()*fixFactor);elsefactor = viewRect.width() / pixmapRect.width();//}pixmapItem->setTransform(QTransform(factor, 0, 0, factor*fixFactor, 0, 0));// if (!manualPan)centerOn(pixmapItem);}
}void DicomView::repositionAuxItems()
{QPointF sceneTL = mapToScene(rect().topLeft());QPointF sceneBR = mapToScene(rect().bottomRight());curFrameItem->setPos(sceneBR.x() - 68, sceneTL.y()+18);slider->setPos(sceneBR.x() - 58, sceneTL.y() + 58);QSizeF slider_size(58, sceneBR.y() - sceneTL.y() - 116);slider->resize(slider_size);posValueItem->setPos(sceneTL.x()+ 10, sceneBR.y()- 58);
}void DicomView::updateView()
{QPixmap pixmap;if (dicoms&&dicoms->isNormal()) {dicoms->getPixmap(pixmap);pixmapItem->setPixmap(pixmap);pixmapItem->setTransformOriginPoint(pixmapItem->boundingRect().center());}else {pixmapItem->setPixmap(pixmap);curFrameItem->setText("");posValueItem->setText("");}resizePixmapItem();repositionAuxItems();
}void DicomView::setHighlight(bool yes)
{
}void DicomView::setCurFrameItem(int)
{if (!dicoms || !dicoms->isNormal())return;curFrameItem->setText(tr("%1-%2").arg(dicoms->getCurFrame()).arg(dicoms->getFrameCount()));
}void DicomView::mousePressEvent(QMouseEvent * event)
{if (dicoms&&dicoms->isNormal()){emit clicked(dicoms->getViewType());QPointF sp = mapToScene(event->pos());QPointF ip = pixmapItem->mapFromScene(sp);prevMousePos = event->pos();if (event->button() == Qt::LeftButton) {setDragMode(QGraphicsView::NoDrag);switch (status) {case Browse:if (!(event->modifiers()&Qt::ControlModifier)) {setDragMode(QGraphicsView::RubberBandDrag);setCursor(Qt::ArrowCursor); // 划框}break;}}QGraphicsView::mousePressEvent(event);}
}void DicomView::mouseMoveEvent(QMouseEvent * event)
{if (dicoms&&dicoms->isNormal()) {QPointF sp = mapToScene(event->pos());QPointF ip = pixmapItem->mapFromScene(sp);if (pixmapItem->contains(ip)) {QPoint pos = ip.toPoint();QString s = dicoms->getPixelValue(pos.x(), pos.y());posValueItem->setText(tr("(%1, %2):").arg(pos.x()).arg(pos.y())+ s);}}// 按住右键调整窗宽窗位if (event->buttons()&Qt::RightButton) {// 调整窗宽位setDragMode(QGraphicsView::NoDrag);setCursor(Qt::ArrowCursor);QPoint delta = event->pos() - prevMousePos;dicoms->setWindowDelta(-delta.y() * 16, delta.x() * 16);emit windowChanged();updateView();}QGraphicsView::mouseMoveEvent(event);
}void DicomView::mouseReleaseEvent(QMouseEvent * event)
{if (dicoms&&dicoms->isNormal()) {if (event->button() == Qt::LeftButton) {switch (status) {case Browse:// 划框时结束时调整窗宽窗位if (scene->selectedItems().size() == 0){if (rubberBandRect().isValid()){if (dicoms->getViewType() == SeriesBase::XY){dicoms->setRoiWindow(pixmapItem->mapFromScene(mapToScene(rubberBandRect())).boundingRect());emit windowChanged();updateView();}}}break;}}}QGraphicsView::mouseReleaseEvent(event);
}void DicomView::wheelEvent(QWheelEvent * e)
{QPoint delta = e->angleDelta();if (dicoms == 0 || !dicoms->isNormal()) return;if (delta.y() > 0) dicoms->prevFrame();else if (delta.y() < 0) dicoms->nextFrame();updateView();
}void DicomView::resizeEvent(QResizeEvent * event)
{resizePixmapItem();repositionAuxItems();
}

二、提升UI文件QGraphicsView 为 DicomView

保存提升后的ui,运行调试,就会发现显示框变黑了,提升成功。 

三、实验“选择序列”下拉菜单功能

    ...
class SeriesBase; // 添加
class DicomBrowse : public QMainWindow
{...public slots:...void on_windowChanged();
private:...SeriesBase *xyS;// 添加  xy视图的序列SeriesBase *xzS;// 添加SeriesBase *yzS;// 添加
}
...
#include "SeriesBase.h"  // 添加
#include "XYSeries.h"
#include "XZSeries.h"
#include "YZSeries.h"...
DicomBrowse::DicomBrowse(QWidget *parent): QMainWindow(parent)
{...connect(ui.graphicsView_XY, SIGNAL(windowChanged()), this, SLOT(on_windowChanged()));xyS = new XYSeries(); // 添加xzS = new XZSeries(); yzS = new YZSeries();
}DicomBrowse::~DicomBrowse()
{delete xyS;delete xzS;delete yzS;
}
...
// 点击“选择序列”下拉菜单后执行
void  DicomBrowse::on_comboBox_which_currentIndexChanged(QString seriesUID)
{if (isOpeing)return;isOpeing = true;SeriesBase::readSeriesUid(seriesUID); // 读取序列isOpeing = false;if (!SeriesBase::isNormal())return;ui.textBrowser->clear(); // ui.textBrowser->append(QStringLiteral("共有%1个序列>>").arg(ReadWorker::UID_Files.count()));ui.textBrowser->append(QStringLiteral("当前序列(%1):").arg(seriesUID));int w, h, s;SeriesBase::getSeriesSize(w, h, s);ui.textBrowser->append(QStringLiteral("宽:%1").arg(w));ui.textBrowser->append(QStringLiteral("高:%1").arg(h));ui.textBrowser->append(QStringLiteral("图像数:%1").arg(s));xyS->update(); xzS->update(); yzS->update();ui.graphicsView_XY->setSeries(xyS);
}
...
void DicomBrowse::on_comboBox_currentIndexChanged(int color)
{// 伪彩下拉菜单选择彩色后,设置序列彩色,并更新视图SeriesBase::setColor(color);ui.graphicsView_XY->updateView();
}
...
void DicomBrowse::on_lineEdit_ww_textEdited(QString ww)
{// 窗宽编辑框数字编辑完成后,设置序列窗宽位,并更新视图double ww_d = 0.0, wl = 0.0;SeriesBase::getWindow(wl, ww_d);ww_d = ww.toDouble();SeriesBase::setWindow(wl, ww_d);ui.graphicsView_XY->updateView();
}void DicomBrowse::on_lineEdit_wl_textEdited(QString wl)
{// 窗位编辑框数字编辑完成后,设置序列窗宽位,并更新视图double ww = 0.0, wl_d = 0.0;SeriesBase::getWindow(wl_d, ww);wl_d = wl.toDouble();SeriesBase::setWindow(wl_d, ww);ui.graphicsView_XY->updateView();
}void DicomBrowse::on_windowChanged()
{// 更新窗宽、窗位的编辑框数字double ww = 0.0, wl = 0.0;SeriesBase::getWindow(wl, ww);set_lineEdit_wl_text(wl);set_lineEdit_ww_text(ww);
}// 修改该函数
void DicomBrowse::ReadCheckCompleted()
{...on_comboBox_which_currentIndexChanged(ui.comboBox_which->currentText());
}
...

运行调试,点击“选择Dicom文件夹”后

设置伪彩色

调整窗宽窗位:1)通过按住拖动鼠标右键;2) 修改窗宽窗位值;3) 按住鼠标左键划框(感兴趣区域);

至此,我们实现了XY视图切片浏览。

在收尾部分(下一章),将实现三视图,并提供工程项目的下载链接。

第六章 基于QT和DCMTK的Dicom 图像浏览器---Dicom视图类相关推荐

  1. 【正点原子FPGA连载】第三十六章 基于OV5640的PL以太网视频传输实验-摘自【正点原子】领航者ZYNQ之FPGA开发指南_V2.0

    1)实验平台:正点原子领航者ZYNQ开发板 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手册+视频下 ...

  2. linux 正点原子ov5640_【正点原子FPGA连载】第二十六章基于OV5640的二值化实验-摘自【正点原子】领航者 ZYNQ 之嵌入式开发指南 (amobbs.com 阿莫电子论坛)...

    本帖最后由 正点原子 于 2020-10-26 16:21 编辑 QQ群头像.png (1.78 KB) 2020-10-24 10:50 上传5)关注正点原子公众号,获取最新资料 100846rel ...

  3. 开源SWD脱机烧录器-第三章 基于QT的上位机

    /********************2020.03.02更新********************/ 感谢博友的提醒我忘记上传Qt源码了,这就补上 https://gitee.com/airt ...

  4. 从零开始做3D地图编辑器(六)(基于QT与OGRE)

    五.OGRE基础知识 友善提醒:如果你对OGRE比较了解,请自觉跳过此节. 本节并不打算提供详细的入门教程,只是对OGRE的简单介绍,如果需要OGRE的详细资料,请自行使用网络功能. 1.OGRE是什 ...

  5. 7.QML Qt Quick——基于Qt Quick Controls 2实现图片浏览器

    Qt Quick Controls 2提供了一组UI控件,例如按钮,标签,复选框,滑块等(用之查之即可).用于在Qt Quick中创建用户界面.UI控件很多,这里通过一个图片浏览器的实现来逐步讲解 图 ...

  6. C# 第六章『交互式图形界面』◆第6节:MessageBox类

    一.MessageBox 类 MessageBox 类https://docs.microsoft.com/zh-cn/dotnet/api/system.windows.forms.messageb ...

  7. 基于QT(C++)实现(窗体)平台类对战游戏【100010513】

    1. 设计任务的描述 用面向对象的设计方法来设计一款平台类对战游戏. 内容包括宠物小精灵的加入.用户注册与平台登录.游戏对战的设计. 2. 功能需求说明及分析 2.1 宠物小精灵的加入 设计宠物小精灵 ...

  8. C# 第六章『交互式图形界面』◆第4节:FileDialog类 、OpenFileDialog类、SaveFileDialog类、示例

    一.FileDialog 类 FileDialog 类https://docs.microsoft.com/zh-cn/dotnet/api/system.windows.forms.filedial ...

  9. C# 第六章『交互式图形界面』◆第5节:FolderBrowserDialog类、DialogResult枚举

    一.FolderBrowserDialog 类 FolderBrowserDialog 类https://docs.microsoft.com/zh-cn/dotnet/api/system.wind ...

  10. 《MATLAB智能算法30个案例》:第16章 基于动态粒子群算法的动态环境寻优算法

    <MATLAB智能算法30个案例>:第16章 基于动态粒子群算法的动态环境寻优算法 1. 前言 2. MATLAB 仿真示例 3. 小结 1. 前言 <MATLAB智能算法30个案例 ...

最新文章

  1. [javaweb] servlet的生命周期 (二)
  2. flutter Web打包
  3. c++学习笔记之类和对象的进阶
  4. 实验吧逆向catalyst-system——WP
  5. 牛客题霸 [ 数字在升序数组中出现的次数] C++题解/答案
  6. c语言输出每个数占10列宽,杭州师范大学C语言试题第1套介绍.doc
  7. Random Forest
  8. win10 hao123劫持html文件,Win10 edge浏览器主页被hao123劫持怎么解决?
  9. AD7606-4输出数据异常
  10. Android手机减少微信步数,iPhone微信步数竟然比安卓少很多,原因已明确!
  11. MongoDB索引原理及实践
  12. 云服务器性能不如物理服务器,云服务器性能不如物理服务器
  13. 2021 PostgreSQL 中国技术大会 PPT 下载
  14. Python自带的服务器
  15. mysql查询emoji_mysql怎么搜emoji?
  16. 一篇文章告诉你如何拍摄720度全景图片
  17. python使用Excel文件(增、删、改、查)
  18. 服务器系统盘怎么命名,云服务器系统盘命名
  19. 常见sql语句的语法错误
  20. conda配置清华源 国内源

热门文章

  1. 将PC端固定布局页面改成移动端流体布局。
  2. java连点方法,Re:连点器(示例代码)
  3. 第十一章.软件工程(上)
  4. ftp服务器扫描不了文件内容,ftp服务器扫描不了文件
  5. java ftpclient prompt,一个JAVA FTP客户端制作的收获
  6. vs2005安装和部署项目
  7. 试图速成的RPG Maker MV 学习笔记(二)
  8. Windows桌面软件美化界面:分享著名的VC++ DirectUI/duilib/SOUI/REDM,IMGUI和C#开源界面库
  9. C语言中程序设计题 计算机二级考试
  10. 观天涯kk大神10年帖子有感