pyqt设计的图片查看软件

本文介绍了Qt编程中如何读取和显示图片,以及如何在Label控件上操作图片。同时,讲解了Qt窗口的大小和位置调整,图片大小变化的处理方法,特别是ListWidget的使用,包括添加、删除条目,设置自定义样式,以及添加右键菜单。此外,还展示了如何实现Label上图片的移动效果。内容深入浅出,适合Qt初学者和进阶者参考。
摘要由CSDN通过智能技术生成

  1. 读取图片文件
  2. 显示图片在label上
  3. Qt窗口大小和位置
  4. 图片大小变化问题
  5. Listwidge使用方法
  6. 添加图片条目
  7. 添加右键菜单
  8. label上图片的移动
  9. 最终效果

读取图片文件

打开文件有以下3种:
1.单个文件打开 QFileDialog.getOpenFileName()
2.多个文件打开 QFileDialog.getOpenFileNames()
3.文件夹选取 QFileDialog.getExistingDirectory()
4.文件保存 QFileDialog.getSaveFileName()

 directory1 = QFileDialog.getExistingDirectory(self,
                  "选取文件夹",
                  "./")   #起始路径
fileName1, filetype = QFileDialog.getOpenFileName(self,
                  "选取文件",
                  "./",
                  "All Files (*);;Text Files (*.txt)")  #设置文件扩展名过滤,注意用双分号间隔
files, ok1 = QFileDialog.getOpenFileNames(self,
                  "多文件选择",
                  "./",
                  "All Files (*);;Text Files (*.txt)")
fileName2, ok2 = QFileDialog.getSaveFileName(self,
           "文件保存",
           "./",
           "All Files (*);;Text Files (*.txt)")

在这里插入图片描述

显示图片在label上

 # 很重要:可以使图片大小随label大小自动变化
self.label.setScaledContents(True) 
# imgName为图片路径
# scaled()可以自定义宽和高
jpg=QtGui.QPixmap(imgName).scaled(self.label.width(),self.label.height())
# 在label上显示图片
self.label.setPixmap(jpg)

Qt窗口大小和位置

# geometry()获取某个控件的坐标和宽高
self.w = self.geometry().width()
self.h = self.geometry().height()
self.x = self.geometry().x()
self.y = self.geometry().y() 
# x, y, w, h = self.geometry()
self.wl = self.label.width()
self.hl = self.label.height()   
# frameGeometry:
返回窗口相对于父窗口的几何形状的大小,包括窗口的框架,当窗口是顶级窗口时,返回的实际上是屏幕的大小;
# frameSize:
返回窗口的几何形状的大小,包括窗口的框架,当窗口是顶级窗口时,返回的实际上是屏幕的大小;
# availableGeometry: 
返回屏幕的可用几何图形大小,是screenGeometry ()的子矩形,具体取决于不同平台不同,例如,macOS上的DOCK和菜单栏不包括在内,上的任务栏也不包括;
# screenGeometry: 
返回包含窗口屏幕的几何图形大小。
QDesktopWidget提供了详细的位置信息,其能够自动返回窗口在用户窗口的位置和应用程序窗口的位置

在这里插入图片描述

相关函数解释范围
frameGeometry()几何尺寸**(位置+大小)**对于窗口,包含窗口装饰器
x()、y()、pos()只包含位置信息(左上角坐标)对于窗口,包含窗口装饰器
move()()几何尺寸只移动位置对于窗口,包含窗口装饰器
geometry()几何尺寸**(位置+大小)**不包含窗口装饰器
width()、height()、rect()、size()只包含大小信息不包含窗口装饰器
setGeometry()改变位置和大小不包含窗口装饰器
resize()只改变大小不包含窗口装饰器

图片大小变化问题

图片放大缩小通过改变label来实现(绑定按钮或滚轮事件控制放缩)

#  放大(放大时如果不限制大小会覆盖窗口其他控件,解决办法是将label放在另一个控件容器里,图片显示在label上,如 groupBox容器等)
self.label.setGeometry(self.label.x() - 10, self.label.y() - 10, self.label.width() + 30, self.label.height() + 20)
# 缩小
 self.label.setGeometry(self.label.x() + 10, self.label.y() + 10,  self.label.width() - 30, self.label.height() - 20)

Listwidge使用方法

QListWidget 是一个方便的类,它提供一个与 QListView 提供的列表视图类似的列表视图,但是具有一个用于添加和删除项目的经典的基于项目的接口。QListWidget 使用一个内部模型来管理列表中的每个 QListWidgetItem

对于更灵活的列表视图小部件,可以使用带有标准模型的 QListView 类。QListWidget 是一个方便的类,它提供一个与 QListView 提供的列表视图类似的列表视图,但是具有一个用于添加和删除项目的经典的基于项目的接口。QListWidget 使用一个内部模型来管理列表中的每个 QListWidgetItem

对于更灵活的列表视图小部件,可以使用带有标准模型的 QListView 类。

QListWidget 官方文档 >

函数#

函数名描述传参返回数据
addItem(item or label)在列表尾部中添加 QListWidgetItem 对象或字符串QListWidgetItem or str
addItems(labels)在列表尾部中添加 str 列表中的每条目[str]
openPersistentEditor(item)开始编辑QListWidgetItem
closePersistentEditor(item)结束编辑QListWidgetItem
count()列表条目数量int
currentItem()返回当前选中的条目 itemQListWidgetItem
currentRow()返回当前选中的条目 rowint
editItem(item)如果条目是可编辑的,则开始编辑该条目QListWidgetItem
findItems(text, flags)文本匹配返回匹配到的条目text, flags[QListWidgetItem]
indexFromItem(item)返回 QModelIndex 对象QListWidgetItemQModelIndex
insertItem(row, item or label)在列表位置插入 QListWidgetItem 对象或字符串int,QListWidgetItem or str
insertItems(row, labels)在列表位置插入字符串 str 列表中的每条目int,[str]
isItemHidden(item)官方不推荐使用
isItemSelected(item)官方不推荐使用
isPersistentEditorOpen(item)判断是否开启了编辑模式QListWidgetItembool
isSortingEnabled()判断是否开启了排序模式bool
item(row)通过列表行找到 QListWidgetItem 对象intQListWidgetItem
itemAt(p)返回坐标处的 item(int,int) or QPointQListWidgetItem
itemFromIndex(index)返回 QListWidgetItem 对象QModelIndexQListWidgetItem
itemWidget(item)返回 item 中的 Widget 对象,如果没有返回 NoneQListWidgetItemWidget 对象
items(data)---
removeItemWidget(item)移除 item 中的 Widget 对象QListWidgetItem
row(item)通过 QListWidgetItem 找到 rowQListWidgetItemint
selectedItems()返回当前选中的条目 多个[QListWidgetItem]
setCurrentItem(item)设置当前选中的条目 itemQListWidgetItem
setCurrentRow(row)设置当前选中的条目 rowint
setItemHidden(item, hide)官方不推荐使用
setItemSelected(item, select)官方不推荐使用
setItemWidget(item, widget)item 设置 widgetQListWidgetItem,Widget
setSortingEnabled(enable)设置排序模式开关bool
sortItems([order=Qt.AscendingOrder])默认按升序重新排列条目
takeItem(row)移除列表条目int
visualItemRect(item)返回条目在列表的坐标 与 尺寸QListWidgetItemQRect

虚函数#

函数名描述
dropMimeData(index, data, action)处理由外部拖放操作提供的数据,该操作以给定索引中的给定操作结束。如果模型可以处理数据和动作,则返回 true 否则返回 false
mimeData(items)返回一个对象,该对象包含指定项的序列化描述。用于描述项的格式是从 mimeTypes() 函数获得的
mimeTypes()返回可用于描述 listwidget 项列表的 MIME 类型列表
supportedDropActions()返回此视图支持的拖放操作

#

函数名描述
clear()删除视图中的所有项,警告:所有项目将被永久删除
scrollToItem(item[, hint=EnsureVisible])必要时滚动视图以确保项目可见。hint 指定操作后项的位置。

信号#

信号名触发条件返回数据
currentItemChanged(current, previous)选中行发生了改变当前 QListWidgetItem 对象,之前 QListWidgetItem 对象
currentRowChanged(currentRow)选中行发生了改变当前行 row
currentTextChanged(currentRow)选中行发生了改变当前行 text
itemClicked(item)点击列表中的条目时QListWidgetItem 对象
itemChanged(item)列表中有变化后QListWidgetItem 对象
itemActivated(item)连击列表中的条目时QListWidgetItem 对象
itemDoubleClicked(item)双击列表中的条目时QListWidgetItem 对象
itemEntered(item)拖拽列表中的条目时对应 QListWidgetItem 对象
itemPressed(item)按下列表中的条目时QListWidgetItem 对象
itemSelectionChanged()选中行发生了改变

通过widge自定义设计样式

自定义一个Item

  1. 新建一个QWidget对象

  2. 在QWidget内添加Layout

  3. 在Layout内添加要的控件

  4. 为QWidget设置Layout

  5. 新建一个QListWidgetItem并调整大小

  6. 为QListWidgetItem设置QWidget

创建布局

  1. 使用 Qt designer

确定布局

比如:
在这里插入图片描述
可以看出此布局总体是一个横向布局(QHBoxLayout), 再其右边是一个纵向(QVBoxLayout), 下面的布局又是一个横向布(QHBoxLayout)

 # 总Widget
 wight = QWidget()
 # 布局
 layout_main = QHBoxLayout() # 总体横向布局
 layout_right = QVBoxLayout() # 右边的纵向布局
 layout_right_down = QHBoxLayout() # 右下的横向布局
 layout_right.addLayout(layout_right_down) # 右下布局填充到右边布局中
 layout_main.addLayout(layout_right) # 右边布局填充入总布局
 wight.setLayout(layout_main) # 为Widget设置总布局

添加数据

# 读取属性
 ship_name = data['ship_name']
 ship_photo = data['ship_photo']
 ship_index = data['ship_index']
 ship_type = data['ship_type']
 ship_country = data['ship_country']
 ship_star = data['ship_star']
 # 总Widget
 wight = QWidget()
 # 总体横向布局
 layout_main = QHBoxLayout()
 map_l = QLabel() # 头像显示
 map_l.setFixedSize(40, 25)
 maps = QPixmap(ship_photo).scaled(40, 25)
 map_l.setPixmap(maps)
 # 右边的纵向布局
 layout_right = QVBoxLayout()
 # 右下的的横向布局
 layout_right_down = QHBoxLayout() # 右下的横向布局
 layout_right_down.addWidget(QLabel(ship_type))
 layout_right_down.addWidget(QLabel(ship_country))
 layout_right_down.addWidget(QLabel(str(ship_star) + "星"))
 layout_right_down.addWidget(QLabel(ship_index))
 # 按照从左到右, 从上到下布局添加
 layout_main.addWidget(map_l) # 最左边的头像
 layout_right.addWidget(QLabel(ship_name)) # 右边的纵向布局
 layout_right.addLayout(layout_right_down) # 右下角横向布局
 layout_main.addLayout(layout_right) # 右边的布局
 wight.setLayout(layout_main) # 布局给wight
 return wight # 返回wight

设置QListWidgetItem

for ship_data in YOUR_DATA:
 item = QListWidgetItem() # 创建QListWidgetItem对象
 item.setSizeHint(QSize(200, 50)) # 设置QListWidgetItem大小
 widget = get_item_wight(ship_data) # 调用上面的函数获取对应
 self.listWidget.addItem(item) # 添加item
 self.listWidget.setItemWidget(item, widget) # 为item设置widget

我的widge自定义样式:图片在上,名字在下

   # 总Widget
   wight = QWidget()
   # 总体横向布局
   layout_main = QVBoxLayout()
   """ 第一个label """
   map_top = QLabel(self)  # 头像显示
   map_top.setToolTip(path)
   maps = QPixmap(path).scaled(200, 150)
   map_top.setPixmap(maps)
   # 有时候写成 Qt.AlignCenter会报错
   map_top.setAlignment(QtCore.Qt.AlignCenter)

   """ 第二个label"""
   text_bottom = QLabel(self)
   text_bottom.setAlignment(QtCore.Qt.AlignCenter)
   text_bottom.setText(name)
   # 将 label 控件给布局,控件按照它布局
   layout_main.addWidget(map_top)
   layout_main.addWidget(text_bottom)

   # 将布局给 wight容器
   wight.setLayout(layout_main)

   item = QListWidgetItem()  # 创建QListWidgetItem对象
   item.setSizeHint(QSize(200, 200))  # 设置QListWidgetItem大小
   self.addiems_widge(current_imgpath, n)
   self.listWidget.addItem(item)  # 添加item
   self.listWidget.setItemWidget(item, wight)  # 为item设置widget

添加图片条目

相关方法

   // ui->listWidget->resize(365,400);
    //设置QListWidget的显示模式
    ui->listWidget->setViewMode(QListView::IconMode);
    //设置QListWidget中单元项的图片大小
    ui->listWidget->setIconSize(QSize(278,278));
    //设置QListWidget中单元项的间距
    ui->listWidget->setSpacing(10);
    //设置自动适应布局调整(Adjust适应,Fixed不适应),默认不适应
    ui->listWidget->setResizeMode(QListWidget::Adjust);
    //设置不能移动
    ui->listWidget->setMovement(QListWidget::Static);

	可以通过iconSize()返回工具栏图标的大小,使用setIconSize(QSize)设置工具栏图标的大小。
    xxxx  .  setIconSize(  QSize( 宽, 高 )  )
	
	// 假如 m_list 添加了很多子项 (一个子项由 一个图片和一段文字组成) 
	// 如果设置为
	m_second_list->setViewMode(QListView::IconMode); 
	// 那么m_list 子项就会从左到右横向的排列 图片和文字是上下排列.
	
	// 如果设置为
	m_second_list->setViewMode(QListView::ListMode); 
	// 那么m_list 子项就会从上到下排列 图片和文字是从左到右排列.
	
	// 如果设置为
	m_second_list->setFlow(QListView::LeftToRight);
	// 那么m_list 子项就会从左到右横向的排列 图片和文字也是从左到右排列.
	
	// 如果设置为
	 m_second_list->setFlow(QListView::TopToBottom);
	// 那么m_list 子项就会从上到下排列 图片和文字是从左到右排列.
	
	// 配合使用大家可以试试看效果.
	// 一般可以和 setWrapping(bool) (可以让布局从左至右,从上到下顺序排列);
	 setMovement() 配合一起使用

插入图片

    # 获取点击的条目
    item = self.listWidget.selectedItems()
    if not item:
        return 0
    # 获取条目对应的行,通过对行的加减确定插入是在上还是下插入
    row = self.listWidget.row(item[0])
    insert_row = row + 1
    # 从文件夹获取要插入的图片
    insert_img_path, _ = QFileDialog.getOpenFileName(self, "打开文件夹", self.fixedpath, "*.jpg;;*.png;;*.gif")
    if not insert_img_path:
        return 0
    # 将插入的图片保存到开始打开的文件夹里
    img = Image.open(insert_img_path)
    switch_img_path = os.path.join(self.filepath, os.path.basename(insert_img_path))
    img.save(switch_img_path)
    # 调用函数自定义条目显示图片格式
    name = os.path.basename(switch_img_path)
    wight, item = self.addiems_widge(switch_img_path, name)
    # 插入图片条目
    self.listWidget.insertItem(insert_row, item)  # 添加item
    self.listWidget.setItemWidget(item, wight)  # 为item设置widget
    # 插入刚开始读的文件路径
    self.imgpath.insert(insert_row, switch_img_path)

添加右键菜单

在初始化时定义
 #  打开右键菜单的策略
 self.listWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
 #  # 绑定事件
 self.listWidget.customContextMenuRequested.connect(self.listwidgeIten_fun)


 # 传入pos用以通过itemAt确认当前点击位置是一个树节点,currentItem用以获取当前点击节点进行相应操作
 item = self.listWidget.currentItem()
 # itemAt(pos)  返回坐标处的item
 item1 = self.listWidget.itemAt(pos)
 if item != None and item1 != None:
     menu = QMenu(self)
     # QAction 创建菜单选项对象
     # addAction 把动作选项对象添加到菜单 menu 上
     actionA = QAction(QIcon(r'C:\Users\xxx\Pictures\图标\删除数据.png'), u'删除图片', self)
     actionB = QAction(QIcon(r'C:\Users\xxx\Pictures\图标\向上插入行.png'), u'向上插入图片', self)
     actionC = QAction(QIcon(r'C:\Users\xxx\Pictures\图标\向下插入行.png'), u'向下插入图片', self)
     # # 设置动作的快捷键
     # actionA.setShortcut('Ctrl+c')
     # actionB.setShortcut('Ctrl+a')
     # actionC.setShortcut('Ctrl+d')
     # 把动作对象添加到菜单
     menu.addAction(actionA)
     menu.addAction(actionB)
     menu.addAction(actionC)
     # 将动作触发时连接到槽函数 button
     actionA.triggered.connect(self.remove_items)
     actionB.triggered.connect(self.above_add_items)
     actionC.triggered.connect(self.below_add_items)
     # 在鼠标位置显示
     menu.exec_(QCursor.pos())

label上图片的移动

  # 鼠标左击右击事件 控制图片移动
    def mousePressEvent(self, event):
        if event.buttons() == QtCore.Qt.LeftButton or event.buttons() == QtCore.Qt.RightButton:
            self.flag = True

    # 鼠标释放事件
    def mouseReleaseEvent(self, event):
        self.flag = False
        self.mouse_mv_y = ""  # 销毁结点指针
        self.mouse_mv_x = ""

    # 鼠标移动事件
    def mouseMoveEvent(self, event):
        if self.flag:  # 鼠标点击,获取鼠标坐标
            self.x1 = event.x()
            self.y1 = event.y()

            if self.mouse_mv_x != "" and self.mouse_mv_y != "":
                self.label_x = self.label_x + (self.x1 - self.mouse_mv_x)
                self.label_y = self.label_y + (self.y1 - self.mouse_mv_y)

            self.mouse_mv_x = self.x1  # 记录拖拽时上一个点的坐标
            self.mouse_mv_y = self.y1
            self.label.setGeometry(self.label_x, self.label_y, self.label.width(), self.label.height())

最终效果

在制作窗口框架时可以让控件大小随窗口大小可以拉伸

在这里插入图片描述

博客里面是一些要用到的主要知识点, 里面还可以添加很多功能,下面图片是设计好的画面.
在这里插入图片描述

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值