Qt. Problem z rysowaniem w viewport

Qt. Problem z rysowaniem w viewport
ReallyGrid
  • Rejestracja:około 11 lat
  • Ostatnio:około 2 miesiące
0

Mam swoją klasę GuiBoard:

Kopiuj
#ifndef GUIBOARD_HPP
#define GUIBOARD_HPP

#include <QWidget>
#include <QRect>

class GuiBoard : public QWidget {
public:
    explicit GuiBoard(QWidget* parent = nullptr);

protected:
    void paintEvent(QPaintEvent* event) override;
    void resizeEvent(QResizeEvent* event) override;

private:
    QRect m_viewport;
};

#endif  // GUIBOARD_HPP

oraz do tego plik cpp:

Kopiuj
#include "GuiBoard.hpp"

#include <algorithm>    // min, max
#include <QDebug>
#include <QPainter>
#include <QResizeEvent>

GuiBoard::GuiBoard(QWidget* const parent) : QWidget(parent) {}

void GuiBoard::paintEvent(QPaintEvent* const event) {
    QPainter painter(this);

    painter.setViewport(m_viewport);
    qDebug() << "Current viewport is:" << painter.viewport();

    painter.fillRect(0, 0, painter.viewport().width(), painter.viewport().height(), Qt::red);
    painter.drawLine(0, 0, 50, 50);
}

void GuiBoard::resizeEvent(QResizeEvent* event) {
    const auto& size = event->size();
    qDebug() << "============\nnew size is:" << size;
    const int width = size.width();
    const int height = size.height();

    const int min = std::min(width, height);
    const int max = std::max(width, height);
    const int p = (max - min) / 2;  // top-left

    if(width > height)
        m_viewport.setRect(p, 0, min, min);
    else
        m_viewport.setRect(0, p, min, min);
}

Po zmianie wymiarów okienka, chcę mieć możliwość rysowania zawsze w maksymalnym kwadracie znajdującym się w środku okienka.
Niestety po uruchomieniu chcąc narysować nawet zwykłą skośna linię (pod kątem 45°, linia 17 w pliku cpp) widzę że jest ona spłaszczona, tak jak na poniższym obrazku.
W konsoli pokazuje mi się, że ustawiony viewport jest prawidłowy (maksymalny kwadrat w tym okienku to właśnie 246x246) Ale nawet czerwony prostokąt, który ma być kwadratem, kwadratem nie jest:

Kopiuj
============
new size is: QSize(640x246)
Current viewport is: QRect(197,0 246x246)

A widzę coś takiego:

screenshot-20250304122507.png

Dlaczego tak się dzieje i jak to poprawić?

Edit:
Wygląda jakby jakaś transformacja skalująca była niejawnie wywoływana wraz z ustawieniem viewporta.
Edit2:
Jeśli zmieni się rozmiar okienka na bardziej pionowy, to skalowanie też się zmieni. Linia też będzie przeskalowana ale będzie bardziej nachylona do poziomu niż do pionu. Dziwne zachowanie...
Edit3:
Żadna transformacja skalująca nie jest niejawnie wywoływana jeśli wierzyć wynikowi zwracanemu przez polecenie: qDebug() << painter.transform(); (dodana linia pomiędzy 14/15). Gdyż daje ono wynik w konsoli:
QTransform(type=TxNone, 11=1 12=0 13=0 21=0 22=1 23=0 31=0 32=0 33=1) czyli macierz identycznościowa

edytowany 6x, ostatnio: ReallyGrid
ReallyGrid
  • Rejestracja:około 11 lat
  • Ostatnio:około 2 miesiące
0

Na razie poradziłem sobie w taki prymitywny sposób:

Kopiuj
void GuiBoard::paintEvent(QPaintEvent* const event) {
    QPainter painter(this);
    const auto& topLeft = m_viewport.topLeft();

    painter.fillRect(m_viewport, Qt::red);

    const int x1 = 20;  // hardcoded
    const int y1 = 20;  // hardcoded
    const int x2 = 50;  // hardcoded
    const int y2 = 90;  // hardcoded
    painter.drawLine(QPoint{x1, y1} + topLeft,
                     QPoint{x2, y2} + topLeft);
}

void GuiBoard::mousePressEvent(QMouseEvent* event) {
    qDebug() << event->pos() - m_viewport.topLeft();
}

Działa choć za każdym razem będę musiał przy rysowaniu dodawać lewy-górny punkt, a w nasłuchiwaczu zdarzeń myszki odejmować go. Póki co nie wiem dlaczego dzieje się to co powyżej (to dziwne skalowanie).

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.