文章目录
- 读取图片文件
- 显示图片在label上
- Qt窗口大小和位置
- 图片大小变化问题
- Listwidge使用方法
- 添加图片条目
- 添加右键菜单
- label上图片的移动
- 最终效果
读取图片文件
打开文件有以下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
类。
函数#
函数名 | 描述 | 传参 | 返回数据 |
---|---|---|---|
addItem(item or label) | 在列表尾部中添加 QListWidgetItem 对象或字符串 | QListWidgetItem or str | |
addItems(labels) | 在列表尾部中添加 str 列表中的每条目 | [str] | |
openPersistentEditor(item) | 开始编辑 | QListWidgetItem | |
closePersistentEditor(item) | 结束编辑 | QListWidgetItem | |
count() | 列表条目数量 | 空 | int |
currentItem() | 返回当前选中的条目 item | 空 | QListWidgetItem |
currentRow() | 返回当前选中的条目 row | 空 | int |
editItem(item) | 如果条目是可编辑的,则开始编辑该条目 | QListWidgetItem | |
findItems(text, flags) | 文本匹配返回匹配到的条目 | text , flags | [QListWidgetItem] |
indexFromItem(item) | 返回 QModelIndex 对象 | QListWidgetItem | QModelIndex |
insertItem(row, item or label) | 在列表位置插入 QListWidgetItem 对象或字符串 | int ,QListWidgetItem or str | |
insertItems(row, labels) | 在列表位置插入字符串 str 列表中的每条目 | int ,[str] | |
isItemHidden(item) | 官方不推荐使用 | ||
isItemSelected(item) | 官方不推荐使用 | ||
isPersistentEditorOpen(item) | 判断是否开启了编辑模式 | QListWidgetItem | bool |
isSortingEnabled() | 判断是否开启了排序模式 | bool | |
item(row) | 通过列表行找到 QListWidgetItem 对象 | int | QListWidgetItem |
itemAt(p) | 返回坐标处的 item | (int,int) or QPoint | QListWidgetItem |
itemFromIndex(index) | 返回 QListWidgetItem 对象 | QModelIndex | QListWidgetItem |
itemWidget(item) | 返回 item 中的 Widget 对象,如果没有返回 None | QListWidgetItem | Widget 对象 |
items(data) | - | - | - |
removeItemWidget(item) | 移除 item 中的 Widget 对象 | QListWidgetItem | |
row(item) | 通过 QListWidgetItem 找到 row | QListWidgetItem | int |
selectedItems() | 返回当前选中的条目 多个 | [QListWidgetItem] | |
setCurrentItem(item) | 设置当前选中的条目 item | QListWidgetItem | |
setCurrentRow(row) | 设置当前选中的条目 row | int | |
setItemHidden(item, hide) | 官方不推荐使用 | ||
setItemSelected(item, select) | 官方不推荐使用 | ||
setItemWidget(item, widget) | 为 item 设置 widget | QListWidgetItem,Widget | |
setSortingEnabled(enable) | 设置排序模式开关 | bool | |
sortItems([order=Qt.AscendingOrder]) | 默认按升序重新排列条目 | ||
takeItem(row) | 移除列表条目 | int | |
visualItemRect(item) | 返回条目在列表的坐标 与 尺寸 | QListWidgetItem | QRect |
虚函数#
函数名 | 描述 |
---|---|
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
-
新建一个QWidget对象
-
在QWidget内添加Layout
-
在Layout内添加要的控件
-
为QWidget设置Layout
-
新建一个QListWidgetItem并调整大小
-
为QListWidgetItem设置QWidget
创建布局
- 使用 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())
最终效果
在制作窗口框架时可以让控件大小随窗口大小可以拉伸
博客里面是一些要用到的主要知识点, 里面还可以添加很多功能,下面图片是设计好的画面.