<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
實現圖片瀏覽器用到了前面幾乎所有的知識,包括視窗部件、佈局、事件、物件模型與容器類、圖形檢視、模型/檢視程式設計以及多執行緒等。大致流程為:首先定義一個圖片類,該類包含圖片的路徑、檔名、檔案id以及獲取這些變數的函數。然後定義了一個圖片陣列類,主要包含新增影象以及獲取所有影象以及新加入影象的函數。最後通過將圖片名字加入到介面左側QDockWidget部件中的QTreeView中,通過執行緒將圖片的預覽加入介面下側的視窗部件中。最後通過雙擊可檢視完整圖片,以及通過滾輪和滑鼠等事件來對圖片進行一些操作。
#ifndef UTILS_H #define UTILS_H #include<QString> #include<string> //string to QString inline QString str2qstr(const std::string& str) { return QString::fromLocal8Bit(str.data()); } //QString to string inline std::string qstr2str(const QString& qstr) { QByteArray cdata = qstr.toLocal8Bit(); return std::string(cdata); } #endif // UTILS_H
#ifndef IMAGE_H #define IMAGE_H #include<string> #include<vector> using std::vector; using std::string; class Image { public: Image() = default; ~Image() = default; Image(const string& _path,const unsigned& _id):path_(_path),id_(_id){ //從路徑中獲取影象名稱 auto pos = path_.find_last_of('\') +1; if(pos == 0) { pos = path_.find_last_of('/')+1; } name_ = path_.substr(pos,path_.length() - pos); pos = name_.find_last_of('.'); name_ = name_.substr(0,pos); } //設定相機所屬的id void set_cam_id(const unsigned& _id){ cam_id_ = _id; } //獲取路徑 const string& get_path(){ return path_; } //獲取檔名 const string& get_name(){ return name_; } const unsigned &get_id(){ return id_; } //獲取相機id const unsigned& get_cam_id(){ return cam_id_; } private: string path_; string name_; unsigned id_; unsigned cam_id_; }; #endif // IMAGE_H
#ifndef IMAGE_GROUP_H #define IMAGE_GROUP_H #include"image.h" class image_group { public: image_group(); ~image_group(); public: bool addImages(const vector<string>& img_paths); const vector<Image>& GetAllImages(); const vector<Image>& GetNewAddingImages(); private: //所有圖片陣列 vector<Image> all_images_; //新加入的圖片陣列 vector<Image> new_images_; }; #endif // IMAGE_GROUP_H
#include "image_group.h" image_group::image_group() { } image_group::~image_group() { } bool image_group::addImages(const vector<std::string> &img_paths) { new_images_.clear(); for(auto& path: img_paths) { all_images_.emplace_back(path,all_images_.size()); new_images_.emplace_back(path,all_images_.size()); } return true; } const vector<Image> &image_group::GetAllImages() { return all_images_; } const vector<Image> &image_group::GetNewAddingImages() { return new_images_; }
#ifndef QIMGVIEWWIDGET_H #define QIMGVIEWWIDGET_H #include <QWidget> #include<QImage> //用於顯示2D影象的視窗部件 class QImgViewWidget : public QWidget { Q_OBJECT public: explicit QImgViewWidget(QWidget *parent = nullptr); ~QImgViewWidget() = default; //從檔案路徑載入圖片 void SetImage(const QString& img_path); void ResetTransform(); private: //用來展示的image資訊 QImage img_display_; //原始pixmap資訊 QPixmap pix_ori_; //用來展示的pixmap資訊 QPixmap pix_display_; //圖片路徑 QString img_path_; //滑鼠滾輪控制的縮放比例 float zoom_scale_; //由滑鼠移動控制的移動 QPoint move_step_; bool move_start_; bool is_moving_; QPoint mouse_point_; protected: void paintEvent(QPaintEvent* event)override; void wheelEvent(QWheelEvent* event)override; void mousePressEvent(QMouseEvent* event)override; void mouseReleaseEvent(QMouseEvent* event)override; void mouseMoveEvent(QMouseEvent* event)override; void resizeEvent(QResizeEvent* event)override; }; #endif // QIMGVIEWWIDGET_H
#include "qimgviewwidget.h" #include <QPainter> #include <QWheelEvent> QImgViewWidget::QImgViewWidget(QWidget *parent) : QWidget(parent) { zoom_scale_ = 1.0f; move_start_ = false; is_moving_ = false; } void QImgViewWidget::SetImage(const QString &img_path) { ResetTransform(); QSize view_size = size(); //通過QImage載入影象 img_path_ = img_path; img_display_.load(img_path_); pix_ori_ = QPixmap::fromImage(img_display_); pix_display_ = pix_ori_.scaled(zoom_scale_ *size(),Qt::KeepAspectRatio); } void QImgViewWidget::ResetTransform() { //重新設定縮放比例和移動位置 zoom_scale_ = 1.0f; move_step_ = QPoint(0,0); } void QImgViewWidget::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.drawPixmap(move_step_.x()+(width()-pix_display_.width())/2,move_step_.y()+(height()- pix_display_.height()) / 2,pix_display_); } void QImgViewWidget::wheelEvent(QWheelEvent *event) { //隨滾輪縮放 if(event->delta()>0) { zoom_scale_ *= 1.1; } else { zoom_scale_ *=0.9; } pix_display_ = pix_ori_.scaled(zoom_scale_ * size(),Qt::KeepAspectRatio); update(); } void QImgViewWidget::mousePressEvent(QMouseEvent *event) { if(event->button() == Qt::LeftButton) { if(!move_start_) { move_start_ = true; is_moving_ = false; mouse_point_ = event->globalPos(); } } } void QImgViewWidget::mouseReleaseEvent(QMouseEvent *event) { if(event->button() ==Qt::LeftButton) { if(move_start_) { move_start_ = false; is_moving_ = false; } } } void QImgViewWidget::mouseMoveEvent(QMouseEvent *event) { if(move_start_) { const QPoint mos_pt = event->globalPos(); move_step_ +=mos_pt - mouse_point_; is_moving_ = true; mouse_point_ = mos_pt; repaint(); } } void QImgViewWidget::resizeEvent(QResizeEvent *event) { pix_display_ = pix_ori_.scaled(zoom_scale_ *size(),Qt::KeepAspectRatio); update(); }
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include"image_group.h" #include<QThread> namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = Q_NULLPTR); // ~MainWindow(); image_group* get_image_group(){ return &image_group_; } Ui::MainWindow* get_ui(){ return ui; } void InitTreeView(); void InitPrewView(); void InitDockView(); void InitTabView(); void InitLayout(); void updateTreeView(); void updatePreView(); private slots: void OnActionAddImages(); void OnActiondoubleClickedTreeImage(const QModelIndex& index); protected: void paintEvent(QPaintEvent* event)override; void resizeEvent(QResizeEvent* event)override; private: Ui::MainWindow *ui; image_group image_group_; }; class QUpdatePreviewThread :public QThread { Q_OBJECT public: QUpdatePreviewThread(MainWindow* mainwindow); signals: void SingalAddPreview(const QPixmap& pixmap,const int& img_id); private slots: void SlotAddPreview(const QPixmap& pixmap,const int& img_id); protected: void run() override; private: MainWindow* mainwindow_; }; #endif // MAINWINDOW_H
mainwindow.cpp
#include"utils.h" #include "mainwindow.h" #include "ui_mainwindow.h" #include<QStandardItemModel> #include<QFileDialog> #include<QMessageBox> #include<QResizeEvent> #include<QListWidgetItem> #include<QImageReader> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); setWindowState(Qt::WindowMaximized); //初始化Ui InitDockView(); InitTreeView(); InitTabView(); InitPrewView(); InitLayout(); connect(ui->action_addimages,&QAction::triggered,this,&MainWindow::OnActionAddImages); connect(ui->tree_images,&QTreeView::doubleClicked,this,&MainWindow::OnActiondoubleClickedTreeImage); connect(ui->list_previews,&QTreeView::doubleClicked,this,&MainWindow::OnActiondoubleClickedTreeImage); } void MainWindow::InitTreeView() { //初始化tree view auto tree_imgs = ui->tree_images; auto* model = new QStandardItemModel(tree_imgs); tree_imgs->setModel(model); model->setHorizontalHeaderLabels(QStringList()<<QStringLiteral("images")); tree_imgs->setEditTriggers(QAbstractItemView::NoEditTriggers); } void MainWindow::InitPrewView() { //初始化preview view auto list_preview = ui->list_previews; list_preview->setIconSize(QSize(100,100)); list_preview->setResizeMode(QListView::Adjust); list_preview->setViewMode(QListView::IconMode); list_preview->setMovement(QListView::Static); list_preview->setSpacing(10); } void MainWindow::InitDockView() { //初始化dockView auto dp_workspace = (QDockWidget*)ui->dock_workspace; dp_workspace->setWindowTitle("Wokspace"); addDockWidget(Qt::LeftDockWidgetArea,dp_workspace); } void MainWindow::InitTabView() { //2d/3d部件的樣式表 // auto tab_view = ui->tab_mainview; // tab_view->setStyleSheet("QTabWidget:pane{ border: 1px ;} // QTabBar::tab{width:50px;height:28px; background-color:rgb(36,36,36); color:rgb(200,200,200); margin-right: 2px; margin-bottom:-2px;} // QTabBar::tab:selected{border:1px;border-bottom-color: none; background-color:rgb(50,50,50)} // QTabBar::tab:!selected{border-bottom: 3px;} // "); // tab_view->setCurrentIndex(0); // auto wid_model = ui->widget_model; // wid_model->setStyleSheet("background-color:rgb(80,80,80);"); // auto wid_image = ui->widght_imgview; // wid_image->setStyleSheet(" background-color:rgb(80,80,80);"); // //照片/控制檯部件樣式表 // auto tab_info = ui->tab_info; // tab_info->setStyleSheet("QTabWidget:pane{ border: 1px ;} // QTabBar::tab{width:60px;height:28px; background-color:rgb(36,36,36); color:rgb(200,200,200); margin-right: 2px; margin-bottom:-2px;} // QTabBar::tab:selected{border:1px;border-bottom-color: none; background-color:rgb(50,50,50)} // QTabBar::tab:!selected{border-bottom: 3px;} // "); // auto wid_priviews = ui->widget_previews; // wid_priviews->setStyleSheet(" background-color:rgb(80,80,80);"); // auto wid_console = ui->widget_console; // wid_console->setStyleSheet(" background-color:rgb(80,80,80);"); } void MainWindow::InitLayout() { } void MainWindow::updateTreeView() { //相關操作後更新tree view。例如,載入影象 const auto all_images = image_group_.GetAllImages(); const auto new_images = image_group_.GetNewAddingImages(); if(new_images.empty()) return; const auto num_allimages = all_images.size(); const auto num_images = new_images.size(); auto* tree = ui->tree_images; auto* model = static_cast<QStandardItemModel*>(tree->model()); QString str_title = QString("All Images (%1 Images)").arg(num_allimages); if(model->item(0,0) ==nullptr) { model->setItem(0,0,new QStandardItem(str_title)); } else { auto item = model->item(0,0); item->setText(str_title); } //為tree新增圖片的名字 for(auto image:new_images) { model->item(0,0)->setChild(image.get_id(),0,new QStandardItem(str2qstr(image.get_name()))); } tree->setExpanded(model->index(0,0),true); auto workspace = static_cast<QDockWidget*>(ui->dock_workspace); auto ws_size = workspace->frameSize(); tree->setFixedWidth(ws_size.width()); } void MainWindow::updatePreView() { auto tab_info = ui->tab_info; tab_info->setCurrentIndex(0); //通過執行緒來建立previews QUpdatePreviewThread* thread = new QUpdatePreviewThread(this); thread->start(); } void MainWindow::OnActionAddImages() { QStringList file_paths = QFileDialog::getOpenFileNames(this,tr("Image Path"),"Data\", tr("Image Files(*png *jpg *tif);")); //新增圖片 vector<string> str_paths; for(auto path:file_paths) { str_paths.push_back(qstr2str(path)); } image_group_.addImages(str_paths); //更新tree view updateTreeView(); //更新preview view updatePreView(); } void MainWindow::OnActiondoubleClickedTreeImage(const QModelIndex &index) { QMessageBox msg_box; auto* tree = ui->tree_images; auto* model = static_cast<QStandardItemModel*>(tree->model()); unsigned img_id = index.row(); const auto all_images = image_group_.GetAllImages(); if(img_id>=all_images.size()) { msg_box.setText("data error"); msg_box.exec(); return; } //獲得雙擊的圖片路徑 auto image = all_images[img_id]; auto imgpath = str2qstr(image.get_path()); //repaint auto img_view = ui->widght_imgview; img_view->SetImage(imgpath); img_view->repaint(); } void MainWindow::paintEvent(QPaintEvent* event) { } void MainWindow::resizeEvent(QResizeEvent* event) { //自動調整所有小部件的大小 const QSize size = event->size(); const QRect frame_geometry = ui->central_widget->geometry(); const QSize frame_size = ui->central_widget->size(); const QSize menu_size = ui->menuBar->size(); QSize layout_h1(menu_size.width() * 0.12, frame_size.height()), layout_h2(menu_size.width() * 0.76, frame_size.height()), layout_h3(menu_size.width() * 0.12, frame_size.height()); QSize layout_v1(menu_size.width(), frame_size.height()*0.8), layout_v2(menu_size.width(), frame_size.height()*0.2); // workspace ui->dock_workspace->setMinimumWidth(layout_h1.width()); ui->dock_workspace->setMaximumHeight(frame_size.height()); // main view(model and image) ui->tab_mainview->setFixedSize(layout_h2.width() - 10, layout_v1.height()); QSize tab_bar_sz = ui->tab_mainview->tabBar()->size(); ui->widget_model->setFixedSize(layout_h2.width() - 10, layout_v1.height() - tab_bar_sz.height()); ui->widght_imgview->setFixedSize(layout_h2.width() - 10, layout_v1.height() - tab_bar_sz.height()); ui->widget_gl_model->setFixedSize(layout_h2.width() - 10, layout_v1.height() - tab_bar_sz.height()); // info view(photos and console) QRect view_rt = ui->tab_mainview->frameGeometry(); ui->tab_info->setGeometry(view_rt.x(), view_rt.y() + view_rt.height()+5, layout_h2.width() - 10, layout_v2.height()); auto tab_sz = ui->tab_info->size(); tab_bar_sz = ui->tab_info->tabBar()->size(); ui->list_previews->setGeometry(0, 0, tab_sz.width(), tab_sz.height()- tab_bar_sz.height()); setMinimumSize(500, 500); } QUpdatePreviewThread::QUpdatePreviewThread(MainWindow *mainwindow) { mainwindow_ = mainwindow; connect(this, SIGNAL(SingalAddPreview(const QPixmap&, const int&)), this, SLOT(SlotAddPreview(const QPixmap&, const int&))); } void QUpdatePreviewThread::SlotAddPreview(const QPixmap &pixmap, const int &img_id) { auto ui = mainwindow_->get_ui(); const auto all_images = mainwindow_->get_image_group()->GetAllImages(); if(img_id >=all_images.size()) return; auto list_preview = ui->list_previews; const QSize icon_sz = list_preview->iconSize(); auto image = all_images[img_id]; QListWidgetItem* list_item = new QListWidgetItem(QIcon(pixmap),str2qstr(image.get_name())); list_item->setSizeHint(QSize(icon_sz.width(),icon_sz.height()+10)); list_preview->insertItem(img_id,list_item); list_preview->repaint(); } void QUpdatePreviewThread::run() { if(mainwindow_ ==nullptr || mainwindow_->get_image_group() ==nullptr) { return; } auto ui = mainwindow_->get_ui(); const auto new_images = mainwindow_->get_image_group()->GetNewAddingImages(); if(new_images.empty()) { return; } const auto num_images = new_images.size(); QImageReader reader; for(auto k=0;k<num_images;k++) { auto image = new_images[k]; reader.setFileName(str2qstr(image.get_path())); reader.setAutoTransform(true); const QSize img_size = reader.size(); const QSize icon_sz = ui->list_previews->iconSize(); const QSize size_scale = img_size.scaled(icon_sz,Qt::KeepAspectRatio); reader.setScaledSize(size_scale); auto pixmap = QPixmap::fromImageReader(&reader); emit SingalAddPreview(pixmap,image.get_id()); } }
#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
以上就是Qt實戰之實現圖片瀏覽器的詳細內容,更多關於Qt圖片瀏覽器的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45