toolbar.md

記事に戻る

# -*- coding: utf-8 -*-
from pathlib import Path
from PyQt5 import QtWidgets, QtCore, QtGui

currentFolderPath = Path(__file__).resolve().parent

class ToolBar(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.tab = QtWidgets.QTabWidget(self)
        self.setLayout( QtWidgets.QGridLayout(self) )
        self.layout().setContentsMargins(1, 1, 1, 1)
        self.layout().setHorizontalSpacing(0)
        self.layout().setVerticalSpacing(0)
        self.layout().addWidget(self.tab)
        self.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Maximum)

        self.homeTab, homeTabLayout = self.addTab('Home')
        self.fileMenu = FileMenu(self.homeTab, 'File')
        self.viewMenu = ViewMenu(self.homeTab, 'View')
        homeTabLayout.addWidget(self.fileMenu)
        homeTabLayout.addWidget(self.viewMenu)
        homeTabLayout.addSpacerItem( QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding) )

        self.imageTab, imageTabLayout = self.addTab('Image')
        self.imageMenu = ImageMenu(self.imageTab, 'Rect recognition')
        self.drawMenu = DrawMenu(self.imageTab, 'Draw rect')
        imageTabLayout.addWidget(self.imageMenu)
        imageTabLayout.addWidget(self.drawMenu)
        imageTabLayout.addSpacerItem( QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding) )

        self.ocrTab, ocrTabLayout = self.addTab('OCR')
        self.ocrMenu = OcrMenu(self.ocrTab, 'Execute')
        self.whiteListMenu = WhiteListMenu(self.ocrTab, 'White list characters')
        ocrTabLayout.addWidget(self.ocrMenu)
        ocrTabLayout.addWidget(self.whiteListMenu)
        ocrTabLayout.addSpacerItem( QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding) )

    def addTab(self, title):
        tabWidget = QtWidgets.QWidget(self)
        tabWidget.setLayout( QtWidgets.QHBoxLayout(tabWidget) )
        tabWidget.layout().setContentsMargins(1, 1, 1, 1)
        self.tab.addTab(tabWidget, title)
        return tabWidget, tabWidget.layout()

class MenuGroup(QtWidgets.QGroupBox):
    def __init__(self, parent, title):
        super().__init__(parent)
        self.toggleViewButton = {}
        self.setLayout( QtWidgets.QVBoxLayout(self) )
        self.layout().setContentsMargins(1, 1, 1, 1)
        self.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.MinimumExpanding)

        self.gridWidget = QtWidgets.QWidget(self)
        self.layout().addWidget(self.gridWidget)
        self.layout().addSpacerItem( QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.MinimumExpanding) )
        label = QtWidgets.QLabel(title, self)
        label.setAlignment(QtCore.Qt.AlignHCenter)
        self.layout().addWidget(label)
        self.gridWidgetLayout = QtWidgets.QGridLayout(self.gridWidget)
        self.gridWidgetLayout.setContentsMargins(1, 1, 1, 1)
        self.gridWidgetLayout.setHorizontalSpacing(0)
        self.gridWidgetLayout.setVerticalSpacing(0)

    def addWidget(self, widget, fromRow, fromColumn, rowSpan, columnSpan):
        if widget is None:
            return widget
        widget.setParent(self.gridWidget)
        self.gridWidgetLayout.addWidget(widget, fromRow, fromColumn, rowSpan, columnSpan)
        return widget

    def createButton(self, parent=None, text='', offIconPath=None, onIconPath=None, checkable=False, iconSize=36):
        button = QtWidgets.QToolButton(parent)
        button.setText(text)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap( str(offIconPath) ), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        icon.addPixmap(QtGui.QPixmap(  str(onIconPath) ), QtGui.QIcon.Normal, QtGui.QIcon.On)
        button.setIcon(icon)
        button.setIconSize( QtCore.QSize(iconSize, iconSize) )
        button.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
        button.setAutoRaise(True)
        button.setArrowType(QtCore.Qt.NoArrow)
        button.setCheckable(checkable)
        button.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
        return button

    def createSlider(self, parent, orientation, minimum, maximum, maximumWidth=100):
        slider = QtWidgets.QSlider(orientation)
        slider.setMinimum(minimum)
        slider.setMaximum(maximum)
        slider.setMaximumWidth(maximumWidth)
        return slider
        
    def addToggleViewButton(self, action, fromRow, fromColumn, rowSpan, columnSpan):
        toolButton = QtWidgets.QToolButton(self)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap(str(currentFolderPath / 'icons/task-line.svg')), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        icon.addPixmap(QtGui.QPixmap(str(currentFolderPath / 'icons/task-fill.svg')), QtGui.QIcon.Normal, QtGui.QIcon.On)
        toolButton.setArrowType(QtCore.Qt.NoArrow)
        toolButton.setAutoRaise(True)
        toolButton.setCheckable(True)
        toolButton.setIcon(icon)
        toolButton.setIconSize( QtCore.QSize(24, 24) )
        toolButton.setText( action.text() )
        toolButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
        toolButton.click()
        toolButton.toggled.connect( lambda : action.trigger() )
        toolButton.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
        self.toggleViewButton[toolButton.text()] = toolButton
        self.addWidget(toolButton,  fromRow, fromColumn, rowSpan, columnSpan)

class FileMenu(MenuGroup):
    def __init__(self, parent, title):
        super().__init__(parent, title)
        self.openButton  = self.createButton(self, 'Open', currentFolderPath / 'icons/file-line.svg')
        self.saveButton  = self.createButton(self, 'Save', currentFolderPath / 'icons/save-3-line.svg')
        self.clearButton = self.createButton(self, 'Clear', currentFolderPath / 'icons/delete-bin-line.svg')
        self.addWidget(self.openButton,  0, 0, 1, 1)
        self.addWidget(self.saveButton,  0, 1, 1, 1)
        self.addWidget(self.clearButton, 0, 2, 1, 1)

class ViewMenu(MenuGroup):
    def __init__(self, parent, title):
        super().__init__(parent, title)
        self.rowHeight = SpinBox(self, 'Row height ', 1, 100, 5, 60)
        self.addWidget(self.rowHeight, 0, 1, 1, 1)

class ImageMenu(MenuGroup):
    def __init__(self, parent, title):
        super().__init__(parent, title)
        self.recognizeButton = self.createButton(self, 'Recognize all',  currentFolderPath / 'icons/image-line.svg')
        self.contourAreaMin  = SpinBox(self, 'Rect area min', 1, 999999999, 5000,    80)
        self.contourAreaMax  = SpinBox(self, 'Rect area max', 1, 999999999, 1000000, 80)
        self.dilate          = SpinBox(self, 'Dilate',           1, 999999999, 3,    50)
        self.addWidget(self.recognizeButton, 0, 0, 1, 1)
        self.addWidget(self.contourAreaMin,  0, 1, 1, 1)
        self.addWidget(self.contourAreaMax,  0, 2, 1, 1)
        self.addWidget(self.dilate,          0, 3, 1, 1)

class OcrMenu(MenuGroup):
    def __init__(self, parent, title):
        super().__init__(parent, title)
        self.ocrButton = self.createButton(self, 'OCR',  currentFolderPath / 'icons/search-line.svg')
        self.addWidget(self.ocrButton, 0, 0, 1, 1)

class WhiteListMenu(MenuGroup):
    def __init__(self, parent, title):
        super().__init__(parent, title)
        self.text = QtWidgets.QPlainTextEdit(self)
        self.text.setPlainText(
              ''.join([str(i)    for i in range(10)])
            + ''.join([chr(i+65) for i in range(26)])
            + ''.join([chr(i+97) for i in range(26)])
        )
        self.text.setMaximumSize(240, 36)
        self.addWidget(self.text, 0, 0, 1, 1)

class DrawMenu(MenuGroup):
    def __init__(self, parent, title):
        super().__init__(parent, title)
        self.drawRectButton   = self.createButton(self, 'Draw rect', currentFolderPath / 'icons/edit-box-line.svg', currentFolderPath / 'icons/edit-box-line.svg', True)
        self.deleteRectButton = self.createButton(self, 'Delete rect', currentFolderPath / 'icons/delete-bin-line.svg')
        self.rectPenComboBox = QtWidgets.QComboBox(self)
        self.rectPenComboBox.setMaximumHeight(36)
        self.rectPenComboBox.setMaximumWidth(60)
        self.addWidget(self.drawRectButton,   0, 0, 1, 1)
        self.addWidget(self.rectPenComboBox,  0, 1, 1, 1)
        self.addWidget(self.deleteRectButton, 0, 2, 1, 1)

        self.rectPenComboBox.addItems(['red', 'green', 'blue'])

class SpinBox(QtWidgets.QWidget):
    valueChanged = QtCore.pyqtSignal(int)
    def __init__(self, parent, text, minimum, maximum, value, width=80, layout=QtWidgets.QVBoxLayout):
        super().__init__(parent)
        self.setLayout( layout(self) )
        self.layout().addWidget( QtWidgets.QLabel(text, self) )
        self.spinBox = QtWidgets.QSpinBox(self)
        self.spinBox.setMinimum(minimum)
        self.spinBox.setMaximum(maximum)
        self.spinBox.setMinimumWidth(width)
        self.spinBox.setMaximumWidth(width)
        self.spinBox.setValue(value)
        self.layout().addWidget(self.spinBox)
        self.layout().setContentsMargins(1, 1, 1, 1)
        self.spinBox.valueChanged.connect(lambda value : self.valueChanged.emit(value))

    def value(self):
        return self.spinBox.value()

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    view = ToolBar()
    view.show()
    app.exec()