J'essaie de créer un interface graphique simple qui affiche la disposition (de la mémoire) de certains composants d'un périphérique, mais j'ai du mal à faire respecter la politique que je veux à la zone affichée.
Permettez-moi d'abord montrer ce que je suis à ce jour (mon code est devenu assez grand, mais je changé/rétrécies le code jusqu'à la minimale requise pour quiconque de pouvoir l'exécuter):PyQt: Comment configurer les barres de défilement et la politique de taille de la zone d'affichage dans 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()
Ce code, lors de son lancement, affiche les éléments suivants:
Je ne me dérange pas la barre de défilement verticale, car je compte ajouter d'autres composants à l'appareil, et ils ne seront pas tous s'adapter, ce qui me dérange est le barre de défilement horizontale.
Pourquoi apparaît-il sans que je demande explicitement?
Ce n'est pas comme s'il n'y avait pas de place dans la fenêtre pour que le QGraphicsView
affiche le contenu.
De plus, je remarque que les horizontales (et verticales) des barres de défilement ne semblent pas, lorsque seul le composant est ajouté au QGraphicsView
:
self.scene.addItem(Component()) # << previously was self.scene.addItem(Device())
Maintenant, les barres de défilement ne semblent pas:
Aussi; lorsque je remplace à la place les lignes suivantes:
LeftMargin = 0 # previously was 50
RightMargin = 0 # previously was 50
TopMargin = 0 # previously was 20
BottomMargin = 0 # previously was 20
Les barres de défilement n'apparaissent pas. (Je ai probablement franchi une limite avec ces marges ajoutées?)
Je sais que je peux contrôler la politique des barres de défilement avec le QGraphicsView.setHorizontalScrollBarPolicy()
pour faire toujours la barre de défilement horizontale, mais cela soulève un autre problème: Quand il n'y a aucun moyen de faire défiler vers la droite, la barre de défilement verticale "vole" certains des pixels de l'affichage, rendant Device.RightMargin != Device.LeftMargin
. Aussi, je suis curieux de savoir quelle est la limite de taille au-dessus de laquelle apparaissent les barres de défilement horizontales/verticales.
Donc, c'est la politique que je veux appliquer:
Je veux que la zone affichée à toujours avoir une hauteur minimale de pixels X (quelle que soit la hauteur de
Device()
), et pour la barre de défilement verticale semble que si la hauteurDevice()
passe ces X pixels limite (je vais déterminer la hauteur deDevice()
en additionnant tous lesComponent()
hauteurs de)Je veux QGraphicsView de ne jamais montrer barre de défilement horizontale (la largeur 0 La largeur deest fixe et indépendante du nombre de
Component()
s).- Chaque fois que la barre de défilement verticale est nécessaire, je ne veux pas qu'elle prenne des pixels de ma zone d'affichage.
- Je veux savoir quelle est la limite (en pixels) au-dessus de laquelle les barres de défilement apparaîtront (quand je ne spécifie pas de politique de barre de défilement).
EDIT:
Après avoir joué avec un peu, je me suis dit quelque chose:
La barre de défilement horizontale non désirée apparaît seulement parce que l'une verticale apparaît et vole une partie de l'espace d'affichage.
Selon le doc, la politique par défaut de la barre de défilement horizontale est
Qt::ScrollBarAsNeeded
, ce qui signifie: «montre une barre de défilement lorsque le contenu est trop volumineux pour tenir et non autrement », mais il ne dit pas ce est considéré comme "trop grand".
Lorsque j'ai joué avec les marges (Device.TopMargin
/Device.BottomMargin
), j'ai découvert que la barre de défilement verticale apparaît (et par conséquent la barre horizontale) lorsqueDevice.boundingRect().height()
franchit la limite des 786 pixels.
Je n'arrivais pas à savoir d'où venait ce numéro ni comment le contrôler.
786 pourrait provenir de 900 - 100 (barre de titre) - 2 * 7 (bordures de fenêtre), juste une supposition cependant. Ne devrait pas votre exigence "Chaque fois que la barre de défilement horizontale est nécessaire, je ne veux pas qu'elle prenne des pixels de ma zone d'affichage" soit "Chaque fois que la barre de défilement_vertical ..." (la présence d'une barre horizontale a été exclue par la puce précédente point)? Fondamentalement, cela revient à vérifier la présence d'une barre de défilement verticale à chaque redessiner afin d'augmenter la largeur de la fenêtre si nécessaire. Il peut être plus facile d'utiliser des marges gauche/droite asymétriques et afficher la barre de défilement verticale _always_ ... –
Oui, merci, c'est une faute de frappe (horizontale au lieu de verticale). En ce qui concerne votre calcul - comment connaissez-vous ces mesures? (barre de titre, bordures de fenêtre, etc ...) –
De simples suppositions, mais je suis à peu près certaine hauteur de la barre de titre et les bordures de la fenêtre ajouter les 114 pixels manquants de vos 900 pixels hauteur de la fenêtre –