我想使用QGraphicsPixmapItem.setScale
缩放图像。然而,在高放大率水平下,即当仅有几个像素填满窗口时,缩放开始非常不稳定。我在PyQt 4.8.7和5.6.0中,在Windows 10以及Ubuntu 16.10上观察到相同的现象。编辑:在最近的PyQt 5.10上测试,结果相同。编辑:在普通的C ++ Qt中测试,见下文。
这是一个缩放因子由鼠标滚轮控制的例子。
import numpy as np
try:
from PyQt5.QtCore import Qt, QRectF
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QGraphicsScene, QGraphicsView, QMainWindow
qt_ver = 5
except:
from PyQt4.QtCore import Qt, QRectF
from PyQt4.QtGui import QImage, QPixmap
from PyQt4.QtGui import QApplication, QGraphicsScene, QGraphicsView, QMainWindow
qt_ver = 4
app = QApplication([])
class MyGraphicsView(QGraphicsView):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.scene = QGraphicsScene(QRectF())
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setScene(self.scene)
im = np.random.randint(255, size=(100, 100, 3), dtype=np.uint8)
qim = QImage(im, 100, 100, QImage.Format_RGB888)
pix = QPixmap.fromImage(qim)
self.pixi = self.scene.addPixmap(pix)
self.pixi.setOffset(-50, -50)
self.zoom = 0
def wheelEvent(self, event):
if qt_ver == 5:
delta = event.angleDelta().y()
else:
delta = event.delta()
if delta > 0:
self.zoom += 1
elif delta < 0:
self.zoom -= 1
self.pixi.setScale(np.exp(self.zoom * 0.1))
window = QMainWindow()
window.setGeometry(100, 100, 900, 900)
view = MyGraphicsView(window)
window.setCentralWidget(view)
window.show()
app.exec()
看起来缩放正在遭遇舍入问题。我做错了吗?
C ++中的行为相同,这不是PyQt / python问题。我想知道这是否可能是由于float32
精度差导致的离散效应?这可能很难解决。
# include <cstdint>
# include <cmath>
# include <random>
# include <vector>
# include <QApplication>
# include <QGraphicsPixmapItem>
# include <QGraphicsView>
# include <QImage>
# include <QMainWindow>
# include <QPixmap>
# include <QWheelEvent>
# include <QWidget>
class MyGraphicsView
: public QGraphicsView
{
private:
int _zoom = 0;
std::vector<std::uint8_t> _im_data;
QGraphicsScene * _scene = nullptr;
QPixmap _pix;
QGraphicsPixmapItem * _pixi = nullptr;
public:
MyGraphicsView(QWidget * parent)
: QGraphicsView(parent)
{
_scene = new QGraphicsScene(QRectF(), this);
this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
this->setScene(_scene);
_im_data.resize(100 * 100 * 3);
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_int_distribution<> distr(0, std::numeric_limits<std::uint8_t>::max());
for (auto & e: _im_data) e = std::uint8_t(distr(mt));
auto im = QImage(_im_data.data(), 100, 100, QImage::Format_RGB888);
_pix = QPixmap::fromImage(std::move(im));
_pixi = _scene->addPixmap(_pix);
_pixi->setOffset(-50, -50);
}
void wheelEvent(QWheelEvent *event) override
{
auto delta = event->angleDelta().y();
if (delta > 0)
++_zoom;
else if (delta < 0)
--_zoom;
_pixi->setScale(std::exp(_zoom * 0.1));
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
auto window = new QMainWindow();
window->setGeometry(100, 100, 900, 900);
auto view = new MyGraphicsView(window);
window->setCentralWidget(view);
window->show();
return a.exec();
}
修改
可能是一个错误。我提交了QTBUG-66310。