我有一个简单的绘图应用程序,但是当我调整窗口大小时,图像被删除了,我想保留它。我尝试使用image.scaled(当前大小),但它不起作用。
qDebug() << "Resized.";
CurrentSize = event->size();
QImage newImage(CurrentSize, QImage::Format_RGB32);
Image = newImage;
Image.fill(Qt::white);
IsDrawing = false;
this->update();
答案 0 :(得分:2)
我假设你提供的代码在一个方法中,在这种情况下,在堆栈上创建newImage,并在退出方法时超出范围(并调用析构函数)。
在堆上创建它(new QImage
)将阻止这种情况,但是您需要管理对象的生命周期。 Qt的parent
通常对此有所帮助。
答案 1 :(得分:0)
我不知道&#34;简单&#34;你的简单油漆应用程序是,但我觉得你过度复杂化了一些东西。
假设我们对绘制画布小部件有以下要求:
下面给出了一个正确且没有无偿悲观的实现。请注意以下事项:
图像是窗口小部件的用户属性。它可以设置,读取和跟踪。它很简单,例如将imageChanged
连接到标签setPixmap
,并有一个重复的画布显示。
paintEvent
强制执行前提条件&#34;正确大小的图像可以画出&#34;致电newImage
。
要更改QImage
的尺寸,您必须创建新图像,使用QPainter::drawImage
复制内容,然后将旧图像与新图像交换。
由于绘画工具的简单性,没有必要明确跟踪绘画/非绘画状态。
即使按下鼠标左键,也可以随时安全地清除图像。
小部件在被禁用时会忽略用户互动。
setImage(std::move(someImage))
是对不再需要someImage
时的优化:它会保存副本。
相关的setter也是插槽 - 这使得小部件可以通过信号插槽连接与其他对象更加组合。
调整大小后没有必要明确安排更新:Qt已经这样做了。
不允许使用活动画家换出图像。
如果小部件的绘画正在进行中,则更改指示助手不会安排更新。这将是一次冗余更新。
画布始终完全自我绘制,并具有左上角对齐的内容。这些事实应在小部件的属性中表示,作为性能优化。
检查QImage::size()
处理空图像 - 它们的大小也为空。
明显缺乏手动内存管理并非偶然,而是设计:代码中的任何地方都没有new
或delete
。在这种情况下,编译器可以为您完成所有操作。更喜欢将成员变量保持为值。例如。 QImage
应按价值持有。它是一个价值类,没有必要通过new
明确地分配它。事实上,这样做是过早的悲观。
自包含代码示例应该很小,最小,并且在一个文件中。在提问时你应该创建这样一个例子。
// https://github.com/KubaO/stackoverflown/tree/master/questions/painting-app-48520925
#include <QtWidgets>
class PaintCanvas : public QWidget {
Q_OBJECT
Q_PROPERTY(QImage image READ image WRITE setImage NOTIFY imageChanged USER true)
Q_PROPERTY(bool neverShrink READ neverShrink WRITE setNeverShrink)
bool m_neverShrink = true;
QImage m_image;
QPoint m_lastPos;
QPen m_pen{{Qt::red}, 3.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin};
void indicateChange() {
emit imageChanged(m_image);
if (!this->paintingActive()) update();
}
void newImage() {
auto newSize = m_neverShrink ? size().expandedTo(m_image.size()) : size();
if (newSize == m_image.size())
return;
QImage new_image{newSize, QImage::Format_ARGB32_Premultiplied};
new_image.fill(Qt::white);
QPainter p{&new_image};
p.drawImage(0, 0, m_image);
p.end();
m_image.swap(new_image);
indicateChange();
}
void paintEvent(QPaintEvent *) override {
QPainter p{this};
newImage(); // ensure that there's something to paint
p.drawImage(0, 0, m_image);
}
void mousePressEvent(QMouseEvent *event) override {
if (isEnabled() && event->buttons() & Qt::RightButton)
clear();
if (! isEnabled() || ! (event->buttons() & Qt::LeftButton))
return;
m_lastPos = event->pos();
QPainter p{&m_image};
p.setPen(m_pen);
p.drawLine(m_lastPos, m_lastPos+QPoint{1,1});
indicateChange();
}
void mouseMoveEvent(QMouseEvent *event) override {
if (! isEnabled() || ! (event->buttons() & Qt::LeftButton))
return;
QPainter p{&m_image};
p.setPen(m_pen);
p.drawLine(m_lastPos, event->pos());
m_lastPos = event->pos();
indicateChange();
}
public:
PaintCanvas(QWidget * parent = {}) : QWidget(parent) {
setAttribute(Qt::WA_OpaquePaintEvent);
setAttribute(Qt::WA_StaticContents);
}
Q_SIGNAL void imageChanged(const QImage &);
QImage image() const { return m_image; }
Q_SLOT void setImage(const QImage & image) {
m_image = image;
indicateChange();
}
void setImage(QImage && image) {
m_image.swap(image);
indicateChange();
}
bool neverShrink() const { return m_neverShrink; }
void setNeverShrink(bool n) { m_neverShrink = n; }
Q_SLOT void clear() {
m_image = {};
newImage();
}
};
int main(int argc, char ** argv)
{
QApplication app(argc, argv);
PaintCanvas canvas;
canvas.show();
return app.exec();
}
#include "main.moc"