Qt - изменить размер текста в QGraphicsScene после рисования - PullRequest
0 голосов
/ 30 мая 2018

Я делаю небольшую программу черчения с группой студентов, мы используем Qt QGraphicsScene на QGraphicsView, чтобы позволить пользователю наносить пользовательские точки на определенных позициях (x, y), каждая точка должна иметь текст поверх нее.

Вот функция, ответственная за добавление очков к сцене:

void MainWindow::AddPoint(float x, float y, QString name)
{
    y = y * -1; // To Flip Y-Axis
    float Radius = 1; // Point's (Eclipse) Radius
    QGraphicsItem *Point = p_Scene->addEllipse(x , y , Radius , Radius , QPen(QColor(Qt::red)) , QBrush(QColor(Qt::red))); // Creates a Red Colored Point on the given Coordinates (x , y) 
    /*
    QGraphicsTextItem *Text = p_Scene->addText(name); // Creates a Text
    Text->setDefaultTextColor(QColor(Qt::red)); // Sets Text's Color to Red
    Text->setFont(QFont("Courier New" , 4)); // Sets Text's Font Size
    Text->setPos(x , y - 10); // Set Text's Position (On top of the Point)
    ui->graphicsView->setScene(p_Scene); // Adds Text to the Scene
    */
}

, поэтому реализация будет выглядеть так:

AddPoint(0 , 0 , "P1"); // Point 1
AddPoint(50 , 100 , "P2"); // Point 2
AddPoint(100 , 0 , "P3"); // Point 3 

Это приведет к:

An Example of Plotting

Мы используем:

ui->graphicsView->fitInView(ui->graphicsView->scene()->sceneRect() , Qt::KeepAspectRatio);

, чтобы убедиться, что QGraphicsView показывает только то, что видно (довольно важно).

Таким образом, проблема в том, что если бы нам пришлось увеличить рисунок, скажем, например:

AddPoint(0 , 0 , "P1");
AddPoint(0 , 1000 , "P2"); // y = 1000

Это нарисует очень длинную линию, которая сделает Точки + Текст, которые мы создали, настолько маленькими, чтоэто даже не видно:

Example of Plotting using Large numbers

Итак, нам нужно как-то вычислить SceneRect (я думаю) и выяснить значение радиуса + шрифтразмер, который мы должны использовать для точки и текста, так чтоони остаются одинаковыми, независимо от размера сцены.

РЕДАКТИРОВАТЬ: Это НОВЫЙ код (в соответствии с решением vcloarec):

GraphicsWindow.h (подкласс QGraphicsView):

#ifndef GRAPHICSVIEW_H
#define GRAPHICSVIEW_H

#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QDebug>

class GraphicsView : public QGraphicsView
{
    Q_OBJECT

public:
    explicit GraphicsView(QWidget *parent = 0);
    void AddPoint(float x , float y , QString name = "");
    void resize();

private:
    QGraphicsScene *p_Scene;
    int p_SizeInView;
};

#endif // GRAPHICSVIEW_H

GraphicsWindow.cpp:

#include "GraphicsView.h"

GraphicsView::GraphicsView(QWidget *parent) : QGraphicsView(parent)
{
    p_PointRadius = 0.0;
    p_PointsLastN = 0;
    p_SizeInView = 5;
    p_Scene = new QGraphicsScene(this);

    this->setScene(p_Scene);
}

void GraphicsView::AddPoint(float x, float y, QString name)
{
    y = y * -1;

    QGraphicsItem *_Point = p_Scene->addEllipse(x , y , 1 , 1 , QPen(QColor(Qt::red)) , QBrush(QColor(Qt::red)));

    this->fitInView(scene()->sceneRect() , Qt::KeepAspectRatio);
    resize();
}

void GraphicsView::resize()
{
    qreal scale = p_SizeInView / this->transform().m11();

    for(int i = 0; i < this->scene()->items().count(); i++)
    {
        this->scene()->items().at(i)->setScale(scale);
    }
}

MainWindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->toolBar->addWidget(ui->ZoomUp_Button);
    ui->toolBar->addWidget(ui->ZoomDown_Button);

    setCentralWidget(ui->graphicsView);

    ui->graphicsView->AddPoint(0 , 0);
    ui->graphicsView->AddPoint(1000 , 0);
    ui->graphicsView->AddPoint(1000 , 50);
    ui->graphicsView->AddPoint(0 , 50);
}

MainWindow::~MainWindow()
{
    delete ui;
}

Этот код масштабирует очки в соответствии с фиксированным масштабом, но все равно приводит кПолосы прокрутки, что мы должны решить.Каким-то образом он игнорирует fitInView (), ИЛИ он действительно соответствует ему, но когда размеры точек изменяются, он изменяет размер SceneRect или что-то

Вот результат:

enter image description here

PS: мы создали подкласс QGraphicsView, потому что нам понадобятся MouseEvents и другие вещи позже.

РЕДАКТИРОВАТЬ: Решено с помощью vcloarec : Решением было вставить точки в (-0.5, -0.5) и затем setPose (x, y), который установит Position в x, y, который мы передаем в AddPoint (x, y).Точки теперь сохраняют один и тот же размер независимо от размера Сцены, и на них будут показаны все созданные Точки сразу без полос прокрутки или чего-либо еще.

Спасибо!

1 Ответ

0 голосов
/ 30 мая 2018

Размеры точек и текста определяются в координатах сцены, а не в координате области просмотра (окна).

Если вы хотите, чтобы точки и текст сохраняли свои размеры на дисплее, у вас естьобновить размер в зависимости от «масштаба» вашего окна просмотра.

Редактировать:

Я пробую аналогию:

  • QGraphicsView - это камера
  • QGraphicScene - это реальная жизнь
  • QGraphicsItems - это люди и вещи

Если вы хотите увидеть определенную часть сцены, вы используете QGraphicsView::setSceneRect(const QRectF & rect), чтобы «увеличить» часть, определенную rect.Когда вы «масштабируете» или «масштабируете» с помощью камеры объекты, эти объекты не меняют свой размер в реальной жизни, но на экране размер изменяется.Это то же самое поведение с QGraphicsView.

Если вам нужен фиксированный размер представления вашего объекта, вы должны адаптировать размер вашего объекта в соответствии с масштабом вашей сцены.В вашем примере с addPoint(0 , 0 , "P1"); addPoint(0 , 1000 , "P2") две точки находятся далеко друг от друга, а точки и тексты очень малы по сравнению с этим расстоянием.

Решение вашей проблемы зависит от типа представленияВы хотите (динамический, статический, ...)

Может быть, вы можете использовать матрицу, возвращаемую QTransform QGraphicsView::transform() const и их диагональные элементы, чтобы найти масштаб для использования.

Посмотрите на это:

    class MyView:public QGraphicsView
{
public:
    MyView(QWidget *parent):QGraphicsView(parent),sizeInView(5) {}

    void resize();

protected:
    void wheelEvent(QWheelEvent *event);

private:
    int sizeInView;

};

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    void putPoint();

private:

    Ui::MainWindow *ui;
    QGraphicsScene *scene;
    MyView *view;
};

И

   MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
   ui->setupUi(this);
   view=new MyView(this);
   centralWidget()->setLayout(new QHBoxLayout());
   centralWidget()->layout()->addWidget(view);

   scene=new QGraphicsScene(this);
   view->setScene(scene);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::putPoint()
{
    QGraphicsEllipseItem *point1= new QGraphicsEllipseItem(-0.5,-0.5,1,1);
    point1->setPos(0,0);
    QGraphicsEllipseItem *point2= new QGraphicsEllipseItem(-0.5,-0.5,1,1);
    point2->setPos(0,100);
    QGraphicsEllipseItem *point3= new QGraphicsEllipseItem(-0.5,-0.5,1,1);
    point3->setPos(0,1000);
    QGraphicsEllipseItem *point4= new QGraphicsEllipseItem(-0.5,-0.5,1,1);
    point4->setPos(100,0);
    QGraphicsEllipseItem *point5= new QGraphicsEllipseItem(-0.5,-0.5,1,1);
    point5->setPos(100,100);
    QGraphicsEllipseItem *point6= new QGraphicsEllipseItem(-0.5,-0.5,1,1);
    point6->setPos(100,1000);

    scene->addItem(point1);
    scene->addItem(point2);
    scene->addItem(point3);
    scene->addItem(point4);
    scene->addItem(point5);
    scene->addItem(point6);

    view->fitInView(scene->sceneRect(),Qt::KeepAspectRatio);
    view->resize();
}


void MyView::resize()
{
    qreal scale=sizeInView/transform().m11();
    for (int i=0;i<scene()->items().count();++i)
        scene()->items().at(i)->setScale(scale);
}

void MyView::wheelEvent(QWheelEvent *event)
{
    float fact=1.5;
    if (event->delta()>=120)
    {
        setTransform(transform()*fact);
        resize();
    }

    if (event->delta()<=-120)
    {
       setTransform(transform()/fact);
       resize();
    }
}

Будьте осторожны, точка вставки вашего QGraphicsItem в сцену определяется QGraphicsItem :: setPos.(X, y), который вы используете при создании точки, - это позиция в локальной системе координат, а не в системе координат сцены, и это не центр вашей точки, а прямоугольник верхнего элемента, содержащий эллипс.

Так что, если центр вашей точки не находится в точке вставки, когда вы изменяете размер, точка перемещается ... Вот почему я помещаю точку в (-0,5, -0,5) в локальной координате свысота и ширина равны 1. Затем я помещаю точку с setPos в координату сцены.

Если вы хотите отключить полосу прокрутки:

setHorizontalScrollBarPolicy ( Qt::ScrollBarAlwaysOff )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...