2017-09-15 1 views
3

장치의 일부 구성 요소의 (메모리) 레이아웃을 표시하는 간단한 GUI를 만들려고하고 있지만 실제로 힘든 시간을 적용하고 있습니다. 내가 표시된 영역에 원하는 정책.
은 내가 먼저 내가 지금까지 무엇을 보여 드리죠 (내 코드는 매우 큰되었지만, 누군가가 그것을 실행할 수 있도록 내가 아래로 최소한의 요구로 변경/코드를 좁혀) :PyQt : QGraphicsView에서 스크롤 막대 및 표시 영역 크기 정책을 설정하는 방법

#!/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() 

이 코드, 내가 장치에 더 많은 구성 요소를 추가하려는 때문에

enter image description here

내가, 수직 스크롤 상관 없어, 그들은 맞지 모든 것, 어떤 날 귀찮게하면 입니다 : 시작 때 다음을 표시합니다 가로 스크롤바.
명시 적으로 묻지 않고 왜 나타나나요?
QGraphicsView이 내용을 표시 할 여유가없는 것은 아닙니다.

또한, 나는 수평 (수직) 스크롤 막대가 표시되지 않는 것으로 나타났습니다, 는 구성 요소가을 추가하는 경우에만 QGraphicsView :

self.scene.addItem(Component()) # << previously was self.scene.addItem(Device()) 

이제 스크롤 막대가 표시되지 않습니다
enter image description here

또한, 대신 다음 줄을 변경하십시오.

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()의 높이) :

    그래서,이게 내가 시행 할 정책이다 Device() 높이가 경계 (폭 0 나는를 QGraphicsView 수평 스크롤 막대를 표시하지 않을 할

  • (나는 모든 Component()의 높이를 합산하여 Device()의 높이를 결정합니다)이 X의 픽셀을 통과하는 경우에만 표시의 너비는 고정되어 있으며 Component() 수와 별개입니다.

  • 수직 스크롤바가 필요할 때마다 디스플레이 영역에서 픽셀을 차지하지 않기를 바랍니다.
  • (스크롤바 정책을 지정하지 않은 경우) 스크롤바가 나타나는 경계 (픽셀 단위)를 알고 싶습니다.

편집는 : 수직 하나가 나타나고 디스플레이 공간의 일부를 훔치는 때문에

  • 원치 않는 가로 스크롤 막대 만 나타납니다
    그것으로 조금 연주 후, 나는 무언가를 생각.

  • 가로 스크롤 막대의 기본 정책은 Qt::ScrollBarAsNeeded입니다. 즉 "콘텐츠가 너무 크면 그렇지 않을 때 스크롤 막대를 표시합니다." "너무 큼"으로 간주됩니다.
    여백 (Device.TopMargin/Device.BottomMargin)을 가지고 놀았을 때 Device.boundingRect().height()이 786 픽셀 경계를 넘었을 때 수직 스크롤 막대가 나타났습니다 (결과적으로 가로 스크롤 막대).
    이 번호는 어디에서 왔는지 또는 제어하는 ​​방법을 알 수 없었습니다.

+0

786은 900-100 (제목 표시 줄) - 2 * 7 (창 테두리)에서 비롯 될 수 있습니다. 귀하의 요구 사항을 만족시켜야합니다. "수평 스크롤바가 필요할 때마다, 나는 그것이 디스플레이 영역에서 픽셀을 차지하기를 원하지 않습니다." "_vertical_ 스크롤바가있을 때마다 ..."(수평 막대의 존재 여부는 이전 글 머리 기호에 의해 제외되었습니다. 포인트)? 기본적으로, 필요한 경우 창 너비를 늘리기 위해 모든 다시 그리기시 세로 스크롤 막대가 있는지 확인하는 것으로 끝납니다. 비대칭 좌우 여백을 사용하고 수직 스크롤바를 항상 표시되게하는 것이 더 쉬울 수도 있습니다 ... –

+0

예, 고맙습니다. 오타입니다 (수직이 아닌 가로). 계산에 관한 정보 - 어떻게 측정 값을 알고 있습니까? (제목 표시 줄, 창 테두리, 등 ...) –

+0

추측하지만, 꽤 특정 제목 표시 줄 높이 및 창 테두리는 너의 900 픽셀 창 높이에서 누락 된 114 픽셀을 추가합니다 –

답변

3

나는 당신이 그 내용 (왼쪽 여백 + Device + 오른쪽 여백)보다 커야합니다 view에 고정 폭을 설정할 때, setFixedWidth()

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 

setFixedHeight()에 대한 그렇지 않으면 수평 스크롤을 찾고 생각 막대가 표시됩니다. 그래서 여백이 0 일 때 가로 스크롤 막대가 표시되지 않습니다.

일반적으로 스크롤 막대는 현재보기에서 내용을 표시 할 수 없을 때 나타납니다.

수직 스크롤 막대는 창 안쪽에서 약간의 공간을 차지할 것이며, 나는 당신이 그것을 제어 할 수 없다고 믿습니다. 그래서 당신은 그것을위한 어떤 장소도 예약해야합니다. 수직 스크롤 막대의 동작은 Windows 시스템에 따라 다릅니다. Mac에서는 불필요한 곳을 가리키며 사라 지므로 공간이 전혀 필요하지 않습니다.

QT 디자이너에서 레이아웃을 수행하는 것이 좋습니다. 나는 그것을 시각적으로하고, 즉시 테스트하고, 생성 된 코드에 작은 변화만을 도입하는 것이 훨씬 더 쉽다는 것을 알게되었다.

+0

감사. QSize (self.sceneRect(). width() + 16, self.sceneRect(). height())를 반환하기 위해'sizeHint()'를 재정의했다. 가로 크기 정책을 '고정'으로 설정합니다.(16 이하의 숫자는 어떤 이유로 수직 스크롤 막대를 만들었습니다.) 코드에서 이러한 '마술 숫자'를 사용하는 것을 싫어하지만 16은 정확히 수직 스크롤 막대 (14) + 1의 너비입니다. 픽셀 마진을 각 측면에서가집니다. –

+0

@ so.very.tired. 수직 스크롤 바, 또는 수평 스크롤 바의 높이의 폭을 얻으려면, 시도해보십시오.'qApp.style() pixelMetric (QStyle.PM_ScrollBarExtent)'. – ekhumoro

관련 문제