123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- import numpy as np
- from PyQt5.QtCore import Qt
- from PyQt5.QtGui import QImage, QPixmap, QPainter, QColor, QPolygon
- from PyQt5.QtCore import QPoint, QSize, QRect
- from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QTextEdit
- from PyQt5.QtWidgets import QHBoxLayout, QVBoxLayout, QLabel, QFrame
- class Window(QMainWindow):
- """
- Simple application window to render the environment into
- """
- def __init__(self):
- super().__init__()
- self.setWindowTitle('MiniGrid Gym Environment')
- # Image label to display the rendering
- self.imgLabel = QLabel()
- self.imgLabel.setFrameStyle(QFrame.Panel | QFrame.Sunken)
- # Text box for the mission
- self.missionBox = QTextEdit()
- self.missionBox.setReadOnly(True)
- self.missionBox.setMinimumSize(400, 100)
- # Center the image
- hbox = QHBoxLayout()
- hbox.addStretch(1)
- hbox.addWidget(self.imgLabel)
- hbox.addStretch(1)
- # Arrange widgets vertically
- vbox = QVBoxLayout()
- vbox.addLayout(hbox)
- vbox.addWidget(self.missionBox)
- # Create a main widget for the window
- mainWidget = QWidget(self)
- self.setCentralWidget(mainWidget)
- mainWidget.setLayout(vbox)
- # Show the application window
- self.show()
- self.setFocus()
- self.closed = False
- # Callback for keyboard events
- self.keyDownCb = None
- def closeEvent(self, event):
- self.closed = True
- def setPixmap(self, pixmap):
- self.imgLabel.setPixmap(pixmap)
- def setText(self, text):
- self.missionBox.setPlainText(text)
- def setKeyDownCb(self, callback):
- self.keyDownCb = callback
- def keyPressEvent(self, e):
- if self.keyDownCb == None:
- return
- keyName = None
- if e.key() == Qt.Key_Left:
- keyName = 'LEFT'
- elif e.key() == Qt.Key_Right:
- keyName = 'RIGHT'
- elif e.key() == Qt.Key_Up:
- keyName = 'UP'
- elif e.key() == Qt.Key_Down:
- keyName = 'DOWN'
- elif e.key() == Qt.Key_Space:
- keyName = 'SPACE'
- elif e.key() == Qt.Key_Return:
- keyName = 'RETURN'
- elif e.key() == Qt.Key_Alt:
- keyName = 'ALT'
- elif e.key() == Qt.Key_Control:
- keyName = 'CTRL'
- elif e.key() == Qt.Key_PageUp:
- keyName = 'PAGE_UP'
- elif e.key() == Qt.Key_PageDown:
- keyName = 'PAGE_DOWN'
- elif e.key() == Qt.Key_Backspace:
- keyName = 'BACKSPACE'
- elif e.key() == Qt.Key_Escape:
- keyName = 'ESCAPE'
- if keyName == None:
- return
- self.keyDownCb(keyName)
- class Renderer:
- def __init__(self, width, height, ownWindow=False):
- self.width = width
- self.height = height
- self.img = QImage(width, height, QImage.Format_RGB888)
- self.painter = QPainter()
- self.window = None
- if ownWindow:
- self.app = QApplication([])
- self.window = Window()
- def close(self):
- """
- Deallocate resources used
- """
- pass
- def beginFrame(self):
- self.painter.begin(self.img)
- self.painter.setRenderHint(QPainter.Antialiasing, False)
- # Clear the background
- self.painter.setBrush(QColor(0, 0, 0))
- self.painter.drawRect(0, 0, self.width - 1, self.height - 1)
- def endFrame(self):
- self.painter.end()
- if self.window:
- if self.window.closed:
- self.window = None
- else:
- self.window.setPixmap(self.getPixmap())
- self.app.processEvents()
- def getPixmap(self):
- return QPixmap.fromImage(self.img)
- def getArray(self):
- """
- Get a numpy array of RGB pixel values.
- The array will have shape (height, width, 3)
- """
- numBytes = self.width * self.height * 3
- buf = self.img.bits().asstring(numBytes)
- output = np.frombuffer(buf, dtype='uint8')
- output = output.reshape((self.height, self.width, 3))
- return output
- def push(self):
- self.painter.save()
- def pop(self):
- self.painter.restore()
- def rotate(self, degrees):
- self.painter.rotate(degrees)
- def translate(self, x, y):
- self.painter.translate(x, y)
- def scale(self, x, y):
- self.painter.scale(x, y)
- def setLineColor(self, r, g, b, a=255):
- self.painter.setPen(QColor(r, g, b, a))
- def setColor(self, r, g, b, a=255):
- self.painter.setBrush(QColor(r, g, b, a))
- def setLineWidth(self, width):
- pen = self.painter.pen()
- pen.setWidthF(width)
- self.painter.setPen(pen)
- def drawLine(self, x0, y0, x1, y1):
- self.painter.drawLine(x0, y0, x1, y1)
- def drawCircle(self, x, y, r):
- center = QPoint(x, y)
- self.painter.drawEllipse(center, r, r)
- def drawPolygon(self, points):
- """Takes a list of points (tuples) as input"""
- points = map(lambda p: QPoint(p[0], p[1]), points)
- self.painter.drawPolygon(QPolygon(points))
- def drawPolyline(self, points):
- """Takes a list of points (tuples) as input"""
- points = map(lambda p: QPoint(p[0], p[1]), points)
- self.painter.drawPolyline(QPolygon(points))
- def fillRect(self, x, y, width, height, r, g, b, a=255):
- self.painter.fillRect(QRect(x, y, width, height), QColor(r, g, b, a))
|