一直以来以为setGeometry可以设置控件宽高,某一天发现一个代码
# -*- coding: utf-8 -*-
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.Qt import QPixmap, QPoint, Qt, QPainter
from PyQt5.QtWidgets import QWidget
class ImageBox(QWidget):
def __init__(self):
super(ImageBox, self).__init__()
self.setGeometry(QtCore.QRect(0, 0, 800, 600))
#self.setFixedSize(800,600)
self.img = None
self.scaled_img = QPixmap()
self.scaled_img.fill(Qt.white)
self.start_pos = None
self.end_pos = None
self.left_click = False
self.wheel_flag = False
self.setMouseTracking(True)
self.scale = 1
self.old_scale = 1
self.point = QPoint(0, 0)
self.x = -1
self.y = -1
self.new_height = -1
self.new_width = -1
# self.set_image(r'E:\pao.jpg')
self.setStyleSheet('background:green')
def init_ui(self):
self.setWindowTitle("ImageBox")
def set_image(self, img_path):
self.img = QPixmap(img_path)
width, height = self.img.width(), self.img.height()
if height / width > self.height() / self.width():
new_height = self.height()
new_width = width * self.height() / height
else:
new_height = height * self.width() / width
new_width = self.width()
self.point = QPoint(int((self.width() - new_width) * 0.5), int((self.height() - new_height) * 0.5))
self.img = self.img.scaled(new_width, new_height, Qt.KeepAspectRatio)
self.scaled_img = self.img
self.new_height = new_height
self.new_width = new_width
self.scale = 1
def paintEvent(self, e):
if self.scaled_img:
painter = QPainter()
painter.begin(self)
painter.scale(self.scale, self.scale)
if self.wheel_flag: # 定点缩放
self.wheel_flag = False
# 判断当前鼠标pos在不在图上
this_left_x = self.point.x() * self.old_scale
this_left_y = self.point.y() * self.old_scale
this_scale_width = self.new_width * self.old_scale
this_scale_height = self.new_height * self.old_scale
# 鼠标点在图上,以鼠标点为中心动作
gap_x = self.x - this_left_x
gap_y = self.y - this_left_y
if 0 < gap_x < this_scale_width and 0 < gap_y < this_scale_height:
new_left_x = int(self.x / self.scale - gap_x / self.old_scale)
new_left_y = int(self.y / self.scale - gap_y / self.old_scale)
self.point = QPoint(new_left_x, new_left_y)
# 鼠标点不在图上,固定左上角进行缩放
else:
true_left_x = int(self.point.x() * self.old_scale / self.scale)
true_left_y = int(self.point.y() * self.old_scale / self.scale)
self.point = QPoint(true_left_x, true_left_y)
painter.drawPixmap(self.point, self.scaled_img) # 此函数中还会用scale对point进行处理
painter.end()
def wheelEvent(self, event):
angle = event.angleDelta() / 8 # 返回QPoint对象,为滚轮转过的数值,单位为1/8度
angleY = angle.y()
self.old_scale = self.scale
self.x, self.y = event.x(), event.y()
self.wheel_flag = True
# 获取当前鼠标相对于view的位置
if angleY > 0:
self.scale *= 1.08
else: # 滚轮下滚
self.scale *= 0.92
if self.scale < 0.3:
self.scale = 0.3
self.adjustSize()
self.update()
def mouseMoveEvent(self, e):
print('鼠标移动:', e.pos())
print('控件宽高:w={},h={}'.format(self.width(), self.height()))
if self.left_click:
self.end_pos = e.pos() - self.start_pos # 当前位置-起始位置=差值
self.point = self.point + self.end_pos / self.scale # 左上角的距离变化
self.start_pos = e.pos()
self.repaint()
def mousePressEvent(self, e):
if e.button() == Qt.LeftButton:
self.left_click = True
self.start_pos = e.pos()
def mouseReleaseEvent(self, e):
if e.button() == Qt.LeftButton:
self.left_click = False
class Ui_Form(QWidget):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(800, 600)
# 创建QScrollArea容器
self.scrollArea = QtWidgets.QScrollArea(Form)
self.scrollArea.setGeometry(QtCore.QRect(0, 0, 800, 600))
self.scrollArea.setStyleSheet('background:black')
self.scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
# self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea")
# 创建QWidget容器
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setStyleSheet("background:red")
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 800, 600))
self.scrollAreaWidgetContents.setMinimumSize(QtCore.QSize(100, 100))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
# 在QWidget容器容器上创建一个QGridLayout网格布局
self.gridLayout = QtWidgets.QGridLayout(self.scrollAreaWidgetContents)
self.gridLayout.setObjectName("gridLayout")
# 创建一个图片容器
self.box = ImageBox()
# 将图片容器放到网格布局
self.gridLayout.addWidget(self.box, 0, 0, 1, 1)
# 将QWidget容器放到scrollArea
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
#print('self.scrollAreaWidgetContents width={},height={}'.format(self.scrollAreaWidgetContents.width(),self.scrollAreaWidgetContents.height()))
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_Form()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
你可以运行看看,发现imagebox宽高一直是778x578宽高都是少了22像素,这个让我百思不得其解,反复调试都没发现问题,难道哪里把尺寸改过,后来发现一直没什么问题,但是这个不可控的控件尺寸很明显会影响开发,比如我就要800x600怎么办,后来在代码加了一句就可以了
self.setFixedSize(800,600)
然后控件尺寸就变成800x600但是为什么setGeometry却不行了,从字面理解setGeometry就是设置控件位置和显示尺寸,但是不是设置真实控件尺寸。因此需要用设置控件尺寸函数去设置才应该合理,但是为什么不设置固定尺寸,为啥是778x578呢,这个我一直没弄明白,而且至今也没弄明白为什么会是这个值,也许将成为永久的未解之谜了。