首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Qt -绘制后调整QGraphicsScene上的文本大小

Qt -绘制后调整QGraphicsScene上的文本大小
EN

Stack Overflow用户
提问于 2018-05-31 01:22:52
回答 1查看 1.1K关注 0票数 2

我正在和一群学生一起做一个小绘图程序,我们在QGraphicsView上使用Qt的QGraphicsScene让用户在特定的位置(x,y)绘制自定义的点,每个点都必须有一个文本在上面。

以下是负责向场景添加点的函数:

代码语言:javascript
复制
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
    */
}

因此,实现将如下所示:

代码语言:javascript
复制
AddPoint(0 , 0 , "P1"); // Point 1
AddPoint(50 , 100 , "P2"); // Point 2
AddPoint(100 , 0 , "P3"); // Point 3 

这将导致:

我们使用的是:

代码语言:javascript
复制
ui->graphicsView->fitInView(ui->graphicsView->scene()->sceneRect() , Qt::KeepAspectRatio);

确保QGraphicsView只显示可见的内容(非常重要)。

因此,这里的问题是,如果我们要使绘图更大,例如:

代码语言:javascript
复制
AddPoint(0 , 0 , "P1");
AddPoint(0 , 1000 , "P2"); // y = 1000

这将绘制一条很长的线,这将使我们创建的点+文本非常小,甚至看不到它:

因此,我们需要的是以某种方式计算SceneRect (我认为),并找出半径值+字体大小,我们应该使用的点和文本,使它们保持相同的大小,无论场景的大小。

vcloarec编辑:这是新的代码(根据的解决方案):

H (QGraphicsView子类):

代码语言:javascript
复制
#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:

代码语言:javascript
复制
#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:

代码语言:javascript
复制
#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或其他东西的大小

结果如下:

PS :我们将QGraphicsView子类化,因为我们稍后将需要MouseEvents和其他东西。

编辑:由vcloarec解决:解决方案是在(-0.5,-0.5)处插入点,然后在setPose(x,y)处插入点,这会将位置设置为我们传递给AddPoint(x,y)的x,y。无论场景的大小如何,这些点现在都保持相同的大小,并且它将一次显示所有创建的点,而没有任何滚动条或其他任何东西。

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-05-31 04:06:57

文本末端的点的尺寸在场景坐标中定义,而不是在视口(窗口)坐标中定义。

如果您希望点和文本在显示器上保持其尺寸,则必须根据视口的“缩放”来更新尺寸。

编辑:

我试着打个比方:

the life

  • QGraphicsItems
  • QGraphicsView is a camera
  • QGraphicScene is
    • life
    • QGraphicsItems
    • QGraphicScene

如果要查看场景的特定部分,可以使用QGraphicsView::setSceneRect(const QRectF & rect)rect定义的部分上进行“缩放”。当你用相机对物体进行“缩放”或“取消缩放”时,这些物体在现实生活中不会改变它们的大小,但在屏幕上会改变大小。这与QGraphicsView的行为相同。

如果希望对象表示的大小固定,则必须根据场景的比例调整对象的大小。在您的addPoint(0 , 0 , "P1"); addPoint(0 , 1000 , "P2")示例中,这两个点彼此相距很远,与此距离相比,点和文本非常小。

问题的解决方案取决于所需的表示类型(动态、静态...)

也许您可以使用QTransform QGraphicsView::transform() const返回的矩阵及其对角线元素来查找要使用的比例。

看看这个:

代码语言:javascript
复制
    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;
};

代码语言:javascript
复制
   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。

如果要禁用滚动条:

代码语言:javascript
复制
setHorizontalScrollBarPolicy ( Qt::ScrollBarAlwaysOff )
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50610346

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档