1. 程式人生 > >matplotlib嵌入pyqt5視窗中顯示numpy資料圖片

matplotlib嵌入pyqt5視窗中顯示numpy資料圖片

碰到一個需要將numpy陣列(圖片)顯示在pyqt5的視窗中,上網查到的一般顯示出來圖片周圍會有大片的空白。以下程式碼是將qt5的視窗適應到圖片。

# !/usr/bin/env python
# -*- utf-8 -*-
import matplotlib
matplotlib.use("Qt5Agg")
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.pyplot as plt

import Voxel
# from PyQt5 import QtCore
from PyQt5.QtWidgets import QWidget, QSizePolicy

import numpy as np


class PltCanvas(FigureCanvas):
    def __init__(self, parent = None, width = 320, height = 240, dpi = 100):
        figure = Figure(figsize=(width, height), dpi=dpi)
        figure.set_tight_layout({'pad':0, 'w_pad': 0, 'h_pad': 0})
        figure.set_constrained_layout_pads(w_pad=0, h_pad=0, wspace=0, hspace=0)
        self.subplot = figure.add_subplot(111)
        self.compute_initial_figure()
        FigureCanvas.__init__(self, figure)
        self.setParent(parent)
        FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)
        self.subplot.imshow = self._imshow(self.subplot.imshow)
        img = np.zeros([height, width])
        self.subplot.imshow(img)

    def _imshow(self, func):
        def wraper(img, **kargs):
            self.subplot.clear()
            if not kargs.has_key('aspect'):
                kargs['aspect'] = 'auto'
            img = func(img, **kargs)
            self.subplot.set_axis_off()
            self.subplot.set_xticks([])
            self.subplot.set_yticks([])
            return img
        return wraper

    def compute_initial_figure(self):
        pass
class FloatingWindow(QWidget):
    def __init__(self):
        super(FloatingWindow, self).__init__(None, Qt.FramelessWindowHint)
        self._padding = 5
        self.initTitleLabel()
        #self.setWindowTitle = self._setTitleText(self.setWindowTitle)
        self.setWindowTitle("Floating Window")
        self.initLayout()
        #self.setMinimumWidth(250)
        self.setMouseTracking(True)
        self.initDrag()

    def initDrag(self):
        self._move_drag = False
        self._corner_drag = False
        self._bottom_drag = False
        self._right_drag = False

    def initTitleLabel(self):
        self._title_lable = QLabel(self)
        self._title_lable.setMouseTracking(True)
        self._title_lable.setIndent(10)
        self._title_lable.move(0, 0)

    def initLayout(self):
        self._main_layout = QVBoxLayout()
        self._main_layout.setSpacing(0)
        self._main_layout.addWidget(QLabel(), Qt.AlignLeft)
        self._main_layout.addStretch()
        self.setLayout(self._main_layout)
        self._canvas = canvas.ToFFrameCanvas(self)
        self._main_layout.addWidget(self._canvas)
        self._main_layout.setContentsMargins(0, 0, 0, 0)

    def addLayout(self, layout):
        self._main_layout.addLayout(layout)

    def _setTitleText(self, func):
        def wrapper(*args):
            self._title_lable.setText(*args)
            return func(*args)

        return wrapper

    def setTitleAlignment(self, align):
        self._title_lable.setAlignment(align | Qt.AlignVCenter)

    def setCloseButton(self, flag):
        if flag == True:
            self._close_btn = QPushButton(b'\xef\x81\xb2'.decode('utf-8'), self)
            #self._close_btn.setObjectName('CloseButton')
            #self._close_btn.setToolTip('close window')
            self._close_btn.setMouseTracking(True)
            self._close_btn.setFixedHeight(self._title_lable.height())
            self._close_btn.clicked.connect(self.close)

    def setMinMaxButton(self, flag):
        if flag == True:
            self._min_btn = QPushButton(b'\xef\x80\xb0'.decode('utf-8'), self)
            #self._min_btn.setObjectName("MinMaxButton")
            #self._min_btn.setToolTip("minimize")
            self._min_btn.setMouseTracking(True)
            self._min_btn.setFixedHeight(self._title_lable.height())
            self._min_btn.clicked.connect(self.showMinimized)

            self._max_btn = QPushButton(b'\xef\x80\xb1'.decode('utf-8'), self)
            self._max_btn.setObjectName("MinMaxButton")
            self._max_btn.setToolTip("maximize")
            self._max_btn.setMouseTracking(True)
            #self._max_btn.setFixedHeight(self._title_lable.height())
            self._max_btn.clicked.connect(self._changeNormalButton)

    def _changeNormalButton(self):
        try:
            self.showMaximized()
            self._max_btn.setText(b'\xef\x80\xb2'.decode('utf-8'))
            self._max_btn.setToolTip("resume")
            self._max_btn.disconnect()
            self._max_btn.clicked.connect(self._changeMaxButton)
        except:
            pass

    def resizeEvent(self, QResizeEvent):
        #self._title_lable.setFixedWidth(self.width())
        try:
            self._close_btn.move(self.width() - self._close_btn.width(), 0)
        except:
            pass
        try:
            self._min_btn.move(self.width() - (self._close_btn.width() + 1) * 3 + 1, 0)
        except:
            pass
        try:
            self._max_btn.move(self.width() - (self._close_btn.width() + 1) * 2 + 1, 0)
        except:
            pass

        self._right_rect = [QPoint(self.width() - self._padding, 1),
                            QPoint(self.width() + 1, self.height() + 1)]
        self._bottom_rect = [QPoint(1, self.height() - self._padding),
                             QPoint(self.width(), self.height() + 1)]
        self._corner_rect = [QPoint(self.width() - self._padding, self.height() - self._padding),
                             QPoint(self.width() + 1, self.height() + 1)]

    def _pointInArea(self, p, area):
        return (p.x() > area[0].x()) and (p.x() < area[1].x()) and (p.y() > area[0].y()) and (p.y() < area[1].y())

    def mousePressEvent(self, event):
        if event.button() != Qt.LeftButton:
            return
        if self._pointInArea(event.pos(), self._corner_rect):
            self._corner_drag = True
            event.accept()
        elif self._pointInArea(event.pos(), self._right_rect):
            self._right_drag = True
            event.accept()
        elif self._pointInArea(event.pos(), self._bottom_rect):
            self._bottom_drag = True
        elif event.pos().y() < self._title_lable.height():
            self._move_drag = True
            self._move_drag_pos = event.globalPos() - self.pos()
            event.accept()

    def mouseMoveEvent(self, event):
        if self._pointInArea(event.pos(), self._corner_rect):
            self.setCursor(Qt.SizeFDiagCursor)
        elif self._pointInArea(event.pos(), self._bottom_rect):
            self.setCursor(Qt.SizeVerCursor)
        elif self._pointInArea(event.pos(), self._right_rect):
            self.setCursor(Qt.SizeHorCursor)
        else:
            self.setCursor(Qt.ArrowCursor)

        if self._right_drag:
            self.resize(event.pos().x(), self.height())
            event.accept()
        elif self._bottom_drag:
            self.resize(self.width(), event.pos().y())
            event.accept()
        elif self._corner_drag:
            self.resize(event.pos().x(), event.pos().y())
            event.accept()
        elif self._move_drag:
            self.move(event.globalPos() - self._move_drag_pos)
            event.accept()

    def mouseReleaseEvent(self, event):
        self._move_drag = False
        self._corner_drag = False
        self._bottom_drag = False
        self._right_drag = False


if __name__ == '__main__':
    from PyQt5.QtWidgets import  QApplication
    import sys
    app = QApplication(sys.argv)
    win = FloatingWindow()
    win.setCloseButton(True)
    win.setMinMaxButton(True)
    win.show()
    sys.exit(app.exec_())

程式碼參考了: