Когда виджет нарисован, используются внутренние координаты, но geometry()
- это координаты относительно родителя, поэтому вы не должны использовать его, вместо этого вы должны использовать rect()
.
from PyQt5 import QtCore, QtGui, QtWidgets
class Simulator(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.stdout = QtWidgets.QTextEdit()
self.stderr = QtWidgets.QTextEdit()
self.exec = QtWidgets.QTextEdit()
self.frame = QtWidgets.QFrame()
self.setCentralWidget(self.frame)
self.grid = QtWidgets.QGridLayout(self.frame)
self.map = SimulatedFieldMap()
# -- setting splitters
splitter_r = QtWidgets.QSplitter(QtCore.Qt.Vertical)
splitter_l = QtWidgets.QSplitter(QtCore.Qt.Vertical)
splitter_h = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
splitter_h.addWidget(splitter_l)
splitter_h.addWidget(splitter_r)
# --------------
# -- top left --
frame = QtWidgets.QFrame()
box = QtWidgets.QVBoxLayout(frame)
splitter_l.addWidget(frame)
label = QtWidgets.QLabel('Map')
box.addWidget(label)
box.addWidget(self.map)
# ------
# -- bottom left --
frame = QtWidgets.QFrame()
box = QtWidgets.QVBoxLayout(frame)
box.addWidget(QtWidgets.QLabel('Exec'))
box.addWidget(self.exec)
splitter_l.addWidget(frame)
# -------
# -- top right --
frame = QtWidgets.QFrame()
box = QtWidgets.QVBoxLayout(frame)
splitter_r.addWidget(frame)
box.addWidget(QtWidgets.QLabel('STDOUT'))
box.addWidget(self.stdout)
# -------
# -- bottom right --
frame = QtWidgets.QFrame()
box = QtWidgets.QVBoxLayout(frame)
splitter_r.addWidget(frame)
box.addWidget(QtWidgets.QLabel('STDERR'))
box.addWidget(self.stderr)
# -------
screen = QtWidgets.QDesktopWidget().screenGeometry()
self.grid.addWidget(splitter_h, 0, 0)
splitter_h.setSizes((screen.width() * 0.7, screen.width() * 0.3))
splitter_l.setSizes((screen.height() * 0.7, screen.height() * 0.3))
splitter_r.setSizes((screen.height() * 0.7, screen.height() * 0.3))
class SimulatedFieldMap(QtWidgets.QWidget):
def __init__(self):
super().__init__()
def paintEvent(self, event):
qp = QtGui.QPainter(self)
self.paintMap(qp)
def paintMap(self, qp):
qp.setBrush(QtGui.QColor(200, 162, 200)) # lilac
qp.setPen(QtGui.QColor(200, 162, 200))
qp.drawRect(self.rect())
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle('Fusion')
sim = Simulator()
sim.showMaximized()
sys.exit(app.exec_())
Обновление: Если вы хотите, чтобы оно было размещено в определенной позиции, вы не должны размещать его в макете, но метка должна быть дочерней по отношению к карте и использовать move()
, чтобы установить положение с помощью уважение к карте сверху слева.
# -- top left --
frame = QtWidgets.QFrame()
box = QtWidgets.QVBoxLayout(frame)
box.addWidget(self.map)
splitter_l.addWidget(frame)
label = QtWidgets.QLabel('Map', self.map)
label.move(0, 100)
# ------
Обновление: Проблема вызвана вертикальной размерной политикой QLabel, которая расширяет QSizePolicy::Preferred
, простое решение - изменить ее на QSizePolicy::Maximum
, поэтому правильная высота вычисляется в соответствии с к шрифту.
# -- top left --
frame = QtWidgets.QFrame()
box = QtWidgets.QVBoxLayout(frame)
splitter_l.addWidget(frame)
label = QtWidgets.QLabel('Map')
sp = label.sizePolicy()
sp.setVerticalPolicy(QtWidgets.QSizePolicy.Maximum)
label.setSizePolicy(sp)
box.addWidget(label)
box.addWidget(self.map)
# ------