首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >PyQt:如何在QGraphicsView中设置滚动条和显示区域大小策略

PyQt:如何在QGraphicsView中设置滚动条和显示区域大小策略
EN

Stack Overflow用户
提问于 2017-09-15 19:17:02
回答 1查看 3.3K关注 0票数 5

我正在尝试创建一个简单的gui来显示设备的某些组件的(内存)布局,但是我很难执行我想要的策略到显示区域。

让我首先展示一下到目前为止的情况(我的代码变得相当大,但我将代码更改/缩小到任何人都能运行它所需的最低限度):

代码语言:javascript
运行
复制
#!/usr/local/bin/python3
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys

class Register(QGraphicsRectItem):

    RegisterSize = 125

    NameColor = QColor(Qt.blue)
    ValueColor = QColor(0, 154, 205)

    def __init__(self, name, value, pos, parent = None):
        super(Register, self).__init__(parent)
        self.setPos(pos)

        self.width = Register.RegisterSize
        self.height = 0

        self.set_register_name(name)
        self.set_register_value(value)

        self.setRect(0, 0, self.width, self.height)

    def set_register_name(self, name):
        self.text_item = QGraphicsTextItem(name, self)
        self.text_item.setDefaultTextColor(Register.NameColor)
        self.height += self.text_item.boundingRect().height()

    def set_register_value(self, value):
        self.value_item = QGraphicsTextItem(str(value), self)
        self.value_item.setDefaultTextColor(Register.ValueColor)
        self.value_item.setPos(self.text_item.boundingRect().bottomLeft())
        self.height += self.value_item.boundingRect().height()

class Title(QGraphicsTextItem):

    TitleFont = 'Times New Roman'
    TitleFontSize = 18
    TitleColor = QColor(Qt.red)

    def __init__(self, title, parent = None):
        super(Title, self).__init__(title, parent)

        self.setFont(QFont(Title.TitleFont, Title.TitleFontSize))
        self.setDefaultTextColor(Title.TitleColor)

class Component(QGraphicsItem):

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

        self.width = Register.RegisterSize * 4
        self.height = 0

        self.add_title()
        self.add_registers()

        self.rect = QRectF(0, 0, self.width, self.height)

    def add_title(self):
        self.title = Title('Component Layout', self)
        self.title.setPos((self.width - self.title.boundingRect().width()) / 2, 0)
        self.height += self.title.boundingRect().height()

    def add_registers(self):
        y_coor = self.height
        x_coor = 0
        for i in range(64):
            register = Register('register {0:d}'.format(i), i, QPointF(x_coor, y_coor), self)
            x_coor = ((i + 1) % 4) * Register.RegisterSize
            if (i + 1) % 4 == 0:
                y_coor += register.rect().height()

        self.height = y_coor

    def boundingRect(self):
        return self.rect.adjusted(-1, -1, 1, 1)

    def paint(self, painter, option, widget):
        pen = QPen(Qt.blue)
        painter.setPen(pen)
        painter.drawRect(self.rect)

class Device(QGraphicsItem):

    LeftMargin = 50
    RightMargin = 50

    TopMargin = 20
    BottomMargin = 20

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

        self.width = Device.LeftMargin + Device.RightMargin
        self.height = Device.TopMargin + Device.BottomMargin

        component = Component(self)
        component.setPos(QPointF(Device.LeftMargin, Device.TopMargin))
        self.width += component.boundingRect().width() 
        self.height += component.boundingRect().height()

        self.rect = QRectF(0, 0, self.width, self.height)

    def paint(self, painter, option, widget):
        pass

    def boundingRect(self):
        return self.rect.adjusted(-1, -1, 1, 1)

class MainForm(QDialog):

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

        self.scene = QGraphicsScene(parent)
        self.view = QGraphicsView(self)


        self.view.setScene(self.scene)
        self.scene.addItem(Device())
        self.resize(700, 900)


def run_app():
    app = QApplication(sys.argv)
    form = MainForm()
    form.show()
    app.exec_()

if __name__ == '__main__':
    run_app()

当启动此代码时,将显示以下内容:

我不介意垂直滚动条,因为我打算向设备中添加更多组件,而且它们都不适合,困扰我的是水平滚动条

为什么在我没有明确询问的情况下就出现了?

这并不是说QGraphicsView窗口中没有显示内容的空间。

此外,我注意到水平(和垂直)滚动条没有出现,当只有组件被添加到时,QGraphicsView

代码语言:javascript
运行
复制
self.scene.addItem(Component()) # << previously was self.scene.addItem(Device())

现在不出现滚动条:

另外,当我更改以下行时:

代码语言:javascript
运行
复制
LeftMargin = 0  # previously was 50
RightMargin = 0  # previously was 50

TopMargin = 0 # previously was 20
BottomMargin = 0 # previously was 20

滚动条不出现。(我可能越过了一些边界,加上了这些边距?)

我知道我可以使用QGraphicsView.setHorizontalScrollBarPolicy()控制滚动条策略,使水平滚动条始终关闭,但这带来了另一个问题:当无法向右滚动时,垂直滚动条将从显示中“窃取”一些像素,从而生成Device.RightMargin != Device.LeftMargin。另外,我很好奇水平/垂直滚动条出现的大小边界是什么。

因此,这是我要执行的政策:

  • 我希望显示的区域始终有一个X像素的最小高度(不管Device()的高度如何),而垂直滚动条只有在的高度通过这些X像素边界(我将通过所有Component()的高度之和确定Device()的高度)时才会显示为
  • 我希望QGraphicsView永远不要显示水平滚动条(宽度Device()的宽度是固定的,并且与Component()s的数量无关)。
  • 当需要垂直滚动条时,我不希望它占用显示区域的像素。
  • 我想知道滚动条将出现的边界(以像素为单位)(当我没有指定滚动条策略时)。

编辑

玩了一会儿之后,我想了想:

  • 出现不需要的水平滚动条只是因为垂直滚动条出现并占用了一些显示空间。
  • 根据文档,水平滚动条的默认策略是Qt::ScrollBarAsNeeded,这意味着:“当内容太大时显示滚动条,而不是其他内容。”但它没有说明什么被认为“太大”。 当我玩边距(Device.TopMargin/Device.BottomMargin)时,我发现当Device.boundingRect().height()越过786像素边界时,垂直滚动条就会出现(因此也会出现水平滚动条)。 我不知道这个号码是从哪里来的,也不知道怎么控制它。
EN

回答 1

Stack Overflow用户

发布于 2017-09-22 12:46:22

我相信你在找setFixedWidth()setFixedHeight()

代码语言:javascript
运行
复制
class MainForm(QDialog):

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

        self.scene = QGraphicsScene(parent)
        self.view = QGraphicsView(self)

        self.view.setScene(self.scene)
        self.scene.addItem(Device())
        self.resize(700, 900)
        self.view.setFixedWidth(650)   # <-
        self.view.setFixedHeight(500)  # <- these two lines will set Device dimensions 
        self.setFixedWidth(700)        # <- this will fix window width

当您将固定宽度设置为view时,它必须大于其内容(左边距+ Device +右边距),否则将显示水平滚动条。这就是为什么在边距为零时没有得到水平滚动条的原因。

通常,当当前视图无法显示内容时,滚动条将出现。

垂直滚动条将占用一些空间,从窗口,我相信你没有控制,所以你应该为它预留一些地方,也。垂直滚动条的行为取决于您的windows系统,例如,在Mac上,它在不需要的情况下盘旋并消失,因此它根本不占用空间。

我建议在QT设计器中进行布局。我发现直观地做它要容易得多,立即对它进行测试,并且只在生成的代码中引入一些小的更改。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46246196

复制
相关文章

相似问题

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