gpt4 book ai didi

c++ - 在滚动区域内定位可调整大小的小部件

转载 作者:太空宇宙 更新时间:2023-11-04 12:38:47 29 4
gpt4 key购买 nike

我有一个滚动区域,其中包含一个可调整大小的小部件。用户能够增加和减少这个内部小部件的整数比例因子(这会改变它的大小)。当用户增加比例时,左上角可见的内部小部件部分保持不变。这会产生放大到 View 左上角的效果。

当内部小部件的大小发生变化时,我需要滚动内部小部件以使其看起来像用户正在放大到 View 的中心。我想在调整大小时将小部件的部分固定在 View 中心。

我画了一些图表来帮助可视化问题。粉色矩形是内部小部件。棕色矩形是通过滚动区域到小部件的 View 。绿点是内部小部件上的固定点。

Before scaling缩放前

After scaling (current undesirable behaviour)缩放后(当前不良行为)

After scaling (desired behaviour)缩放后(期望的行为)

正如您(希望)从这些粗略绘制的图表中看到的那样。简单地增加滚动区域内的小部件的大小会导致放大到左上角或 View 。我必须做更多的事情来放大 View 的中心。此外,内部小部件可以比滚动区域小得多。我只想移动大于滚动区域的内部小部件。

这是不良行为的一个最小示例。按 Z(在单击内部小部件以更改焦点后)将放大 View 的左上角。我想放大 View 的中心。

#include <QtGui/qpainter.h>
#include <QtWidgets/qscrollbar.h>
#include <QtWidgets/qscrollarea.h>
#include <QtWidgets/qmainwindow.h>
#include <QtWidgets/qapplication.h>

class InnerWidget final : public QWidget {
public:
explicit InnerWidget(QScrollArea *parent)
: QWidget{parent}, parent{parent} {
updateSize();
setFocusPolicy(Qt::StrongFocus);
}

private:
QScrollArea *parent;
int scale = 1;

void updateSize() {
setFixedSize(256 * scale, 256 * scale);
}

void paintEvent(QPaintEvent *) override {
QPainter painter{this};
const QColor green = {0, 255, 0};
painter.fillRect(0, 0, width(), height(), {255, 255, 255});
painter.fillRect(32 * scale, 32 * scale, 16 * scale, 16 * scale, green);
painter.fillRect(128 * scale, 128 * scale, 16 * scale, 16 * scale, green);
}

void keyPressEvent(QKeyEvent *event) override {
if (event->isAutoRepeat()) return;
QScrollBar *hbar = parent->horizontalScrollBar();
QScrollBar *vbar = parent->verticalScrollBar();
if (event->key() == Qt::Key_Z) {
// need to call bar->setValue and bar->value here
scale = std::min(scale + 1, 64);
updateSize();
} else if (event->key() == Qt::Key_X) {
// here too
scale = std::max(scale - 1, 1);
updateSize();
}
}
};

int main(int argc, char **argv) {
QApplication app{argc, argv};
QMainWindow window;
QScrollArea scrollArea{&window};
InnerWidget inner{&scrollArea};
window.setBaseSize(512, 512);
window.setCentralWidget(&scrollArea);
scrollArea.setAlignment(Qt::AlignCenter);
scrollArea.setWidget(&inner);
window.show();
return app.exec();
}

要重现该问题,请放大几次,然后将其中一个矩形定位在窗口的中央。缩放会将矩形移向右下角。我想要缩放以将矩形保持在中心。

这似乎是一个简单的问题,但我似乎无法理解数学。我已尝试对滚动值进行各种计算,但似乎没有一个符合我的要求。

最佳答案

我弄乱了一段时间的数字,然后我弄明白了。这是完全有效的解决方案。

#include <QtGui/qpainter.h>
#include <QtWidgets/qscrollbar.h>
#include <QtWidgets/qmainwindow.h>
#include <QtWidgets/qscrollarea.h>
#include <QtWidgets/qapplication.h>

class InnerWidget final : public QWidget {
public:
explicit InnerWidget(QScrollArea *parent)
: QWidget{parent}, parent{parent}, scale{1} {
updateSize();
setFocusPolicy(Qt::StrongFocus);
}

private:
QScrollArea *parent;
int scale;

void updateSize() {
setFixedSize(256 * scale, 256 * scale);
}

void paintEvent(QPaintEvent *) override {
QPainter painter{this};
const QColor green = {0, 255, 0};
painter.fillRect(0, 0, width(), height(), {255, 255, 255});
painter.fillRect(32 * scale, 32 * scale, 16 * scale, 16 * scale, green);
painter.fillRect(128 * scale, 128 * scale, 16 * scale, 16 * scale, green);
}

void adjustScroll(const int oldScale) {
if (scale == oldScale) return;
QScrollBar *hbar = parent->horizontalScrollBar();
QScrollBar *vbar = parent->verticalScrollBar();
if (width() >= parent->width()) {
const int halfWidth = parent->width() / 2;
hbar->setValue((hbar->value() + halfWidth) * scale / oldScale - halfWidth);
}
if (height() >= parent->height()) {
const int halfHeight = parent->height() / 2;
vbar->setValue((vbar->value() + halfHeight) * scale / oldScale - halfHeight);
}
}

void keyPressEvent(QKeyEvent *event) override {
if (event->isAutoRepeat()) return;
const int oldScale = scale;
if (event->key() == Qt::Key_Z) {
scale = std::min(scale + 1, 64);
updateSize();
adjustScroll(oldScale);
} else if (event->key() == Qt::Key_X) {
scale = std::max(scale - 1, 1);
updateSize();
adjustScroll(oldScale);
}
}
};

int main(int argc, char **argv) {
QApplication app{argc, argv};
QMainWindow window;
QScrollArea scrollArea{&window};
InnerWidget inner{&scrollArea};
window.setBaseSize(512, 512);
window.setCentralWidget(&scrollArea);
scrollArea.setAlignment(Qt::AlignCenter);
scrollArea.setWidget(&inner);
window.show();
return app.exec();
}

关于c++ - 在滚动区域内定位可调整大小的小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55309055/

29 4 0
京ICP证000000号
广告合作:1813099741@qq.com 6ren.com
Xem sitemap của VNExpress