【问题标题】:Resize QGraphicsView doesn't move the widgets调整 QGraphicsView 大小不会移动小部件
【发布时间】:2012-05-28 01:32:59
【问题描述】:

我有一个 QMainWindows,它位于一个 QGraphicsView 内,它占据了所有客户区。在视图中,我渲染了一些 QGraphicsTextItem 项。只要我不调整主窗口的大小,一切正常。如果我这样做,这些项目将保持在原来的位置,并且不会移动到新的正确位置。基本上我会做的是在布局小部件中具有类似的行为,如果需要,它会扩展

更新 1

更新 2

更新 3

使用以下代码,按钮位于客户区的右侧。 944 是从 QGraphicsView 的 Qt Designer 定义的宽度。我对该区域左侧的小部件具有相同的代码,从 10 开始 xPos 并在每次添加新按钮时递增它。如果我调整窗口大小,左侧小部件总是移动到新位置,右侧没有相同的行为。为什么?

this->ui.setupUi(this);

qreal xPos = 944 - 10;

QGraphicsTextItem *myButton1 = new QGraphicsTextItem("my text");

myButton1 ->adjustSize();
myButton1 ->setPos(xPos - myButton1 ->textWidth(), 10);

xPos -= myButton1 ->textWidth();

this->m_graphicsScene->addItem(myButton1);


QGraphicsTextItem *myButton2 = new QGraphicsTextItem("my text 2");

myButton2 ->adjustSize();
myButton2 ->setPos(xPos - myButton2->textWidth(), 10);

xPos -= myButton2 ->textWidth();

this->m_graphicsScene->addItem(myButton2);

【问题讨论】:

  • 目前还不清楚到底应该发生什么。是否应该缩放显示?是否应该发生一些神奇的“重新布局”,即居中的项目需要保持居中但保持其几何形状?
  • 正如您在屏幕截图中看到的,客户区右侧有一些东西。如果我调整窗口大小,事情不会向右移动,而是保持在旧位置。
  • 视图中的其他内容呢?我怀疑您不希望所有内容都移到视图的左侧。请更具描述性。
  • 如果需要的话,我基本上会有一些可以拉伸的布局(比如 QGridLayout)。调整窗口大小时位于客户端左侧区域的东西会转到新位置,但我在右侧区域绘制的东西不会移动到新位置。
  • 很抱歉,这没有任何意义。如果右侧绘制的内容没有移动,您将拥有屏幕截图中的内容(即留在中间)。你现在说的是调整大小?所以需要应用一些缩放?请对你想要发生的事情做一个真实的模型,并请展示你迄今为止为自己解决这个问题所做的尝试。

标签: qt4 qgraphicsview qgraphicsscene


【解决方案1】:

QGraphicsView 没有直接连接到场景内的 QGraphicsItem 对象。它的唯一目的是在视口中可视化场景的一部分,并将用户交互传输到场景。没有布局,但是添加了布局以与 QGraphicsWidget 一起使用(但这是一个特殊的需求案例)。无论如何,这只是与视图的平移有关,而不是场景中项目的位置(彼此完全不相关)

您最可能需要做的是子类 QGraphicsView,并在您的视图中重新实现 resizeEvent:http://qt-project.org/doc/qt-4.8/qgraphicsview.html#resizeEvent
在 resizeEvent 中,您将根据调整大小将视图平移一个量:http://qt-project.org/doc/qt-4.8/qgraphicsview.html#translate

本质上,您是在自定义 QGraphicsView 中创建自己的布局管理器功能。

更新

我明白你的意思,当 sceneRect 大于 QGraphicsView 时,它将使用滚动条,而不是让你的视图以调整大小为中心。理想情况下,如果您正在创建内容不需要滚动的图形场景类型,您应该保留 sceneRect 默认值,或者将其设置为视口的大小。

否则,这里有一个关于如何使用 resizeEvent 的非常基本的示例。这是在 PyQt 中,但我相信你可以翻译:

class Dialog(QtGui.QDialog):

    def __init__(self):
        super(Dialog, self).__init__()
        self.resize(640,480)
        layout = QtGui.QVBoxLayout(self)

        self.scene = QtGui.QGraphicsScene(self)
        self.scene.setSceneRect(-500,-500,1000,1000)
        self.view = GraphicsView(self)
        self.view.setScene(self.scene)
        layout.addWidget(self.view)

        text = self.scene.addText("Foo")

        self.view.updateCenter()


class GraphicsView(QtGui.QGraphicsView):

    def __init__(self, parent=None):
        super(GraphicsView, self).__init__(parent)
        self._center = None

    def resizeEvent(self, event):
        super(GraphicsView, self).resizeEvent(event)
        if self._center:
            self.centerOn(self._center)

    def updateCenter(self):
        center = self.geometry().center()
        self._center = self.mapToScene(center)

当您拨打updateCenter()时,它会保存您感兴趣的场景点。然后,每次您的视图调整大小时,它都会以该场景点为中心。

更新 2:在您的图片发布和更新之后

如果你真的需要在 QGraphicsScene 中使用这种带有布局的正常 QWidget 行为,那么你应该看看 QGraphicsWidgets,它确实支持布局。然后,您可以制作一个大的根“画布”小部件,并在布局内使其他所有内容成为该小部件的子级。然后你只需要担心保持根小部件的大小合适。然后,您将能够使用上面的相同示例来管理根小部件的大小和位置。

有关更多详细信息,请参阅此问题,因为它与想要将 QGraphicsItem 集成到布局中的人的情况相同:
QGraphicsWidget vs. QGraphicsLayoutItem

【讨论】:

  • 能否请您给我写一个小例子,展示如何实现翻译功能?之后我会接受你的回答
  • @Stefano:你使用的是什么版本的 Qt?我其实去打了个例子,意识到视图的默认行为是保持相对位置。也就是说,如果我在场景的中心创建一个文本项,并调整视图的大小,它会随着视图的增长而保持在中心。我认为您需要发布一个非常简短的工作示例来说明问题。
  • 这正是问题所在。我在 Windows 上使用 qt 4.8。例如,我将 QGraphicsTextItem 放置在位置 0、100。之后我调整窗口大小:如果窗口增大,该项目也应该移动并保持相同的位置,但在我的情况下它什么也不做
  • @Stefano:仅当您的 sceneRect 大于您的视图时才会发生此行为。如果您将场景矩形设置为与视图相同的大小(或根本不设置),它将使所有内容居中。
  • 我认为我的问题解释得很糟糕。我不希望小部件保持在中心,我希望当我调整窗口大小时,小部件遵循宽度/高度,因此如果它们在调整大小后位于左上角,则它们必须仍位于左上角。这不会发生,它们停留在固定位置
猜你喜欢
  • 2021-11-05
  • 1970-01-01
  • 2019-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多