示例#1
0
文件: main.py 项目: msimberg/packman
    def init_ui(self):
        '''
        Helper function to initialize UI widgets
        '''
        # set up the frame object
        cw = QtGui.QWidget()
        self.setCentralWidget(cw)
        self.frame_widget = FrameWidget(self.frame.radius)
        self.available_shapes_widget = AvailableShapesWidget()
        self.info_widget = InfoWidget()
        
        self.frame.set_frame_widget(self.frame_widget)
        self.frame.set_available_shapes_widget(self.available_shapes_widget)
        self.frame.set_info_widget(self.info_widget)  

        # Exit action
        exit_action = QtGui.QAction(QtGui.QIcon.fromTheme("exit"),
                                    '&Exit', self)
        exit_action.setShortcut('Ctrl+Q')
        exit_action.setStatusTip('Exit application')
        exit_action.triggered.connect(self.close)
        
        # Create a menubar
        #menubar = self.menuBar()
        #file_menu = menubar.addMenu('&File')
        #file_menu.addAction(exit_action)
        
        # Create a toolbar
        self.toolbar = self.addToolBar('Exit')
        self.toolbar.addAction(exit_action)
        
        # Create a statusbar
        self.statusBar()
        self.statuslabel = QtGui.QLabel("Algorithm is <b>stopped</b>")
        self.statusBar().addPermanentWidget(self.statuslabel)
        self.frame.set_statuslabel(self.statuslabel)
        
        # Button to move shapes back to the right
        reset_button = QtGui.QPushButton('Reset', self)
        reset_button.clicked.connect(self.frame.reset_shapes)
        reset_button.resize(reset_button.sizeHint())
        reset_button.setStatusTip("Move all fitted shapes to the available shapes")
        
        # Button to run algorithm
        run_button = QtGui.QPushButton("Run")
        run_button.clicked.connect(self.run_frame_widget_algorithm)
        run_button.setStatusTip("Run the currently selected algorithm")
        
        # Button to stop algorithm
        stop_button = QtGui.QPushButton("Stop")
        stop_button.clicked.connect(self.frame.request_stop)
        stop_button.setStatusTip("Stop the currently running algorithm")
        
        # Button to generate shapes
        generate_button = QtGui.QPushButton('Generate\nshapes', self)
        generate_button.clicked.connect(self.generate_shapes)
        generate_button.setStatusTip('Generate new shapes')
        
        # Button to shuffle shapes
        shuffle_button = QtGui.QPushButton("Shuffle")
        shuffle_button.clicked.connect(self.frame.shuffle_available_shapes)
        shuffle_button.setStatusTip('Shuffle available shapes')
        
        # Button to clear shapes
        clear_button = QtGui.QPushButton("Clear shapes")
        clear_button.clicked.connect(self.frame.clear_available_shapes)
        clear_button.setStatusTip("Clear all shapes if algorithm is not running")
        
        # Button to sort shapes
        sort_button = QtGui.QPushButton("Sort by size")
        sort_button.clicked.connect(self.sort_available_shapes)
        sort_button.setStatusTip("Sort the available shapes by size")
        
        # Combobox to choose algorithm
        algolabel = QtGui.QLabel()
        algolabel.setText("Algorithm:")

        self.algocombo = QtGui.QComboBox()
        self.algocombo.addItems(self.frame.get_algorithms())
        self.algocombo.setStatusTip("Choose the algorithm for packing")
        
        # Checkboxes, spinboxes and labels for shape generation
        self.rectcheckbox = QtGui.QCheckBox()
        self.rectcheckbox.setText('Generate')
        self.rectcheckbox.setChecked(True)

        self.circcheckbox = QtGui.QCheckBox()
        self.circcheckbox.setText('Generate')
        self.circcheckbox.setChecked(True)

        self.rectspinbox = QtGui.QSpinBox()
        self.rectspinbox.setMinimum(0)
        self.rectspinbox.setMaximum(50)
        self.rectspinbox.setValue(5)

        self.circspinbox = QtGui.QSpinBox()
        self.circspinbox.setMinimum(0)
        self.circspinbox.setMaximum(50)
        self.circspinbox.setValue(5)
        self.circspinbox.accelerated = True

        self.circmaxspinbox = QtGui.QSpinBox()
        self.circmaxspinbox.setMinimum(10)
        self.circmaxspinbox.setMaximum(self.frame.radius * 2)
        self.circmaxspinbox.setValue(self.frame.radius)

        self.circminspinbox = QtGui.QSpinBox()
        self.circminspinbox.setMinimum(10)
        self.circminspinbox.setMaximum(self.frame.radius * 2)
        self.circminspinbox.setValue(10)

        self.circmaxspinbox.valueChanged.connect(self.cminChange)
        self.circminspinbox.valueChanged.connect(self.cmaxChange)
        
        self.rectmaxspinbox = QtGui.QSpinBox()
        self.rectmaxspinbox.setMinimum(10)
        self.rectmaxspinbox.setMaximum(self.frame.radius * 2)
        self.rectmaxspinbox.setValue(self.frame.radius)

        self.rectminspinbox = QtGui.QSpinBox()
        self.rectminspinbox.setMinimum(10)
        self.rectminspinbox.setMaximum(self.frame.radius * 2)
        self.rectminspinbox.setValue(10)

        self.rectmaxspinbox.valueChanged.connect(self.rminChange)
        self.rectminspinbox.valueChanged.connect(self.rmaxChange)

        rectlabel = QtGui.QLabel()
        rectlabel.setText("<b>rectangles</b> with sides from")
        circlabel = QtGui.QLabel()
        circlabel.setText("<b>circles</b> with diameters from")
        tolabel1 = QtGui.QLabel()
        tolabel1.setText("to")
        tolabel2 = QtGui.QLabel()
        tolabel2.setText("to")
        emptylabel = QtGui.QLabel()
        emptylabel.setText("")

        # Grid layout for shape generation
        gengrid = QtGui.QGridLayout()
        gengrid.addWidget(self.rectcheckbox, 0, 0)
        gengrid.addWidget(self.circcheckbox, 1, 0)
        gengrid.addWidget(self.rectspinbox, 0, 1)
        gengrid.addWidget(self.circspinbox, 1, 1)
        gengrid.addWidget(rectlabel, 0, 2)
        gengrid.addWidget(circlabel, 1, 2)
        gengrid.addWidget(self.rectminspinbox, 0, 3)
        gengrid.addWidget(self.circminspinbox, 1, 3)
        gengrid.addWidget(tolabel1, 0, 4)
        gengrid.addWidget(tolabel2, 1, 4)
        gengrid.addWidget(self.rectmaxspinbox, 0, 5)
        gengrid.addWidget(self.circmaxspinbox, 1, 5)
        gengrid.addWidget(generate_button, 0, 6, 2, 1)
        gengrid.addWidget(emptylabel, 0, 7)
        gengrid.setColumnStretch(7, 1)
        
        # HBox for run, stop and reset buttons
        hbox = QtGui.QHBoxLayout()
        hbox.addWidget(run_button)
        hbox.addWidget(stop_button)
        hbox.addWidget(reset_button)
        hbox.addStretch(1)
        
        # HBox for algorithm combobox and label
        hboxalgo = QtGui.QHBoxLayout()
        hboxalgo.addWidget(algolabel)
        hboxalgo.addWidget(self.algocombo)
        hboxalgo.addStretch(1)
        
        # VBox for left pane
        vboxmain = QtGui.QVBoxLayout()
        vboxmain.addWidget(self.frame_widget)
        vboxmain.addWidget(self.info_widget)
        vboxmain.addLayout(hboxalgo)
        vboxmain.addLayout(hbox)
        
        # Checkbox for reverse sorting and HBox for buttons
        self.reversecheck = QtGui.QCheckBox()
        self.reversecheck.setText('Reverse')
        self.reversecheck.setChecked(False)
        self.reversecheck.setStatusTip("Sort in reverse")
        hboxshape = QtGui.QHBoxLayout()
        hboxshape.addWidget(self.reversecheck)
        hboxshape.addWidget(sort_button)
        hboxshape.addWidget(shuffle_button)
        hboxshape.addWidget(clear_button)
        hboxshape.addStretch(1)
        
        # ScrollArea for available_shapes_widget and VBox for right pane
        aswscroll = QtGui.QScrollArea()
        aswscroll.setWidget(self.available_shapes_widget)
        aswscroll.setMinimumWidth(430)
        aswscroll.setWidgetResizable(True)
        vboxright = QtGui.QVBoxLayout()
        vboxright.addWidget(aswscroll)
        vboxright.addLayout(hboxshape)
        vboxright.addLayout(gengrid)
        
        # HBox to split UI in two panes
        hboxmain = QtGui.QHBoxLayout()
        hboxmain.addLayout(vboxmain)
        hboxmain.addLayout(vboxright)
        hboxmain.setStretch(1,1)
        
        # Central widget
        self.centralWidget().setLayout(hboxmain)
        
        # Set window title and show main window first and widgets after that
        # to avoid extra windows popping up
        self.setWindowTitle('Packman')
        self.show()
        self.center()
        self.frame_widget.show()
        self.available_shapes_widget.show()
        self.info_widget.show()
示例#2
0
文件: main.py 项目: msimberg/packman
class MainWindow(QtGui.QMainWindow):
    '''
    Creates a main window with the required widgets to handle showing shapes
    and running algorithms for fitting shapes. Inherits QtGui.QMainWindow.
    '''
        

    def __init__(self, frame):
        '''
        Initialize an instance and set the frame which handles algorithms and
        fitting to frame, and the radius to radius.

        @param frame: the frame which will handle fitting
        @type  frame: Frame
        '''
        super(MainWindow, self).__init__()
        self.frame = frame
        self.init_ui()
        
    def init_ui(self):
        '''
        Helper function to initialize UI widgets
        '''
        # set up the frame object
        cw = QtGui.QWidget()
        self.setCentralWidget(cw)
        self.frame_widget = FrameWidget(self.frame.radius)
        self.available_shapes_widget = AvailableShapesWidget()
        self.info_widget = InfoWidget()
        
        self.frame.set_frame_widget(self.frame_widget)
        self.frame.set_available_shapes_widget(self.available_shapes_widget)
        self.frame.set_info_widget(self.info_widget)  

        # Exit action
        exit_action = QtGui.QAction(QtGui.QIcon.fromTheme("exit"),
                                    '&Exit', self)
        exit_action.setShortcut('Ctrl+Q')
        exit_action.setStatusTip('Exit application')
        exit_action.triggered.connect(self.close)
        
        # Create a menubar
        #menubar = self.menuBar()
        #file_menu = menubar.addMenu('&File')
        #file_menu.addAction(exit_action)
        
        # Create a toolbar
        self.toolbar = self.addToolBar('Exit')
        self.toolbar.addAction(exit_action)
        
        # Create a statusbar
        self.statusBar()
        self.statuslabel = QtGui.QLabel("Algorithm is <b>stopped</b>")
        self.statusBar().addPermanentWidget(self.statuslabel)
        self.frame.set_statuslabel(self.statuslabel)
        
        # Button to move shapes back to the right
        reset_button = QtGui.QPushButton('Reset', self)
        reset_button.clicked.connect(self.frame.reset_shapes)
        reset_button.resize(reset_button.sizeHint())
        reset_button.setStatusTip("Move all fitted shapes to the available shapes")
        
        # Button to run algorithm
        run_button = QtGui.QPushButton("Run")
        run_button.clicked.connect(self.run_frame_widget_algorithm)
        run_button.setStatusTip("Run the currently selected algorithm")
        
        # Button to stop algorithm
        stop_button = QtGui.QPushButton("Stop")
        stop_button.clicked.connect(self.frame.request_stop)
        stop_button.setStatusTip("Stop the currently running algorithm")
        
        # Button to generate shapes
        generate_button = QtGui.QPushButton('Generate\nshapes', self)
        generate_button.clicked.connect(self.generate_shapes)
        generate_button.setStatusTip('Generate new shapes')
        
        # Button to shuffle shapes
        shuffle_button = QtGui.QPushButton("Shuffle")
        shuffle_button.clicked.connect(self.frame.shuffle_available_shapes)
        shuffle_button.setStatusTip('Shuffle available shapes')
        
        # Button to clear shapes
        clear_button = QtGui.QPushButton("Clear shapes")
        clear_button.clicked.connect(self.frame.clear_available_shapes)
        clear_button.setStatusTip("Clear all shapes if algorithm is not running")
        
        # Button to sort shapes
        sort_button = QtGui.QPushButton("Sort by size")
        sort_button.clicked.connect(self.sort_available_shapes)
        sort_button.setStatusTip("Sort the available shapes by size")
        
        # Combobox to choose algorithm
        algolabel = QtGui.QLabel()
        algolabel.setText("Algorithm:")

        self.algocombo = QtGui.QComboBox()
        self.algocombo.addItems(self.frame.get_algorithms())
        self.algocombo.setStatusTip("Choose the algorithm for packing")
        
        # Checkboxes, spinboxes and labels for shape generation
        self.rectcheckbox = QtGui.QCheckBox()
        self.rectcheckbox.setText('Generate')
        self.rectcheckbox.setChecked(True)

        self.circcheckbox = QtGui.QCheckBox()
        self.circcheckbox.setText('Generate')
        self.circcheckbox.setChecked(True)

        self.rectspinbox = QtGui.QSpinBox()
        self.rectspinbox.setMinimum(0)
        self.rectspinbox.setMaximum(50)
        self.rectspinbox.setValue(5)

        self.circspinbox = QtGui.QSpinBox()
        self.circspinbox.setMinimum(0)
        self.circspinbox.setMaximum(50)
        self.circspinbox.setValue(5)
        self.circspinbox.accelerated = True

        self.circmaxspinbox = QtGui.QSpinBox()
        self.circmaxspinbox.setMinimum(10)
        self.circmaxspinbox.setMaximum(self.frame.radius * 2)
        self.circmaxspinbox.setValue(self.frame.radius)

        self.circminspinbox = QtGui.QSpinBox()
        self.circminspinbox.setMinimum(10)
        self.circminspinbox.setMaximum(self.frame.radius * 2)
        self.circminspinbox.setValue(10)

        self.circmaxspinbox.valueChanged.connect(self.cminChange)
        self.circminspinbox.valueChanged.connect(self.cmaxChange)
        
        self.rectmaxspinbox = QtGui.QSpinBox()
        self.rectmaxspinbox.setMinimum(10)
        self.rectmaxspinbox.setMaximum(self.frame.radius * 2)
        self.rectmaxspinbox.setValue(self.frame.radius)

        self.rectminspinbox = QtGui.QSpinBox()
        self.rectminspinbox.setMinimum(10)
        self.rectminspinbox.setMaximum(self.frame.radius * 2)
        self.rectminspinbox.setValue(10)

        self.rectmaxspinbox.valueChanged.connect(self.rminChange)
        self.rectminspinbox.valueChanged.connect(self.rmaxChange)

        rectlabel = QtGui.QLabel()
        rectlabel.setText("<b>rectangles</b> with sides from")
        circlabel = QtGui.QLabel()
        circlabel.setText("<b>circles</b> with diameters from")
        tolabel1 = QtGui.QLabel()
        tolabel1.setText("to")
        tolabel2 = QtGui.QLabel()
        tolabel2.setText("to")
        emptylabel = QtGui.QLabel()
        emptylabel.setText("")

        # Grid layout for shape generation
        gengrid = QtGui.QGridLayout()
        gengrid.addWidget(self.rectcheckbox, 0, 0)
        gengrid.addWidget(self.circcheckbox, 1, 0)
        gengrid.addWidget(self.rectspinbox, 0, 1)
        gengrid.addWidget(self.circspinbox, 1, 1)
        gengrid.addWidget(rectlabel, 0, 2)
        gengrid.addWidget(circlabel, 1, 2)
        gengrid.addWidget(self.rectminspinbox, 0, 3)
        gengrid.addWidget(self.circminspinbox, 1, 3)
        gengrid.addWidget(tolabel1, 0, 4)
        gengrid.addWidget(tolabel2, 1, 4)
        gengrid.addWidget(self.rectmaxspinbox, 0, 5)
        gengrid.addWidget(self.circmaxspinbox, 1, 5)
        gengrid.addWidget(generate_button, 0, 6, 2, 1)
        gengrid.addWidget(emptylabel, 0, 7)
        gengrid.setColumnStretch(7, 1)
        
        # HBox for run, stop and reset buttons
        hbox = QtGui.QHBoxLayout()
        hbox.addWidget(run_button)
        hbox.addWidget(stop_button)
        hbox.addWidget(reset_button)
        hbox.addStretch(1)
        
        # HBox for algorithm combobox and label
        hboxalgo = QtGui.QHBoxLayout()
        hboxalgo.addWidget(algolabel)
        hboxalgo.addWidget(self.algocombo)
        hboxalgo.addStretch(1)
        
        # VBox for left pane
        vboxmain = QtGui.QVBoxLayout()
        vboxmain.addWidget(self.frame_widget)
        vboxmain.addWidget(self.info_widget)
        vboxmain.addLayout(hboxalgo)
        vboxmain.addLayout(hbox)
        
        # Checkbox for reverse sorting and HBox for buttons
        self.reversecheck = QtGui.QCheckBox()
        self.reversecheck.setText('Reverse')
        self.reversecheck.setChecked(False)
        self.reversecheck.setStatusTip("Sort in reverse")
        hboxshape = QtGui.QHBoxLayout()
        hboxshape.addWidget(self.reversecheck)
        hboxshape.addWidget(sort_button)
        hboxshape.addWidget(shuffle_button)
        hboxshape.addWidget(clear_button)
        hboxshape.addStretch(1)
        
        # ScrollArea for available_shapes_widget and VBox for right pane
        aswscroll = QtGui.QScrollArea()
        aswscroll.setWidget(self.available_shapes_widget)
        aswscroll.setMinimumWidth(430)
        aswscroll.setWidgetResizable(True)
        vboxright = QtGui.QVBoxLayout()
        vboxright.addWidget(aswscroll)
        vboxright.addLayout(hboxshape)
        vboxright.addLayout(gengrid)
        
        # HBox to split UI in two panes
        hboxmain = QtGui.QHBoxLayout()
        hboxmain.addLayout(vboxmain)
        hboxmain.addLayout(vboxright)
        hboxmain.setStretch(1,1)
        
        # Central widget
        self.centralWidget().setLayout(hboxmain)
        
        # Set window title and show main window first and widgets after that
        # to avoid extra windows popping up
        self.setWindowTitle('Packman')
        self.show()
        self.center()
        self.frame_widget.show()
        self.available_shapes_widget.show()
        self.info_widget.show()

    def run_frame_widget_algorithm(self):
        '''
        Call frame.run_algorithm with the appropriate algorithm index and
        change the permanent label in the statusbar to show that an algorithm
        is running'''
        self.frame.run_algorithm(self.algocombo.currentIndex())
        self.statuslabel.setText("Algorithm is <b>running</b>")

    def generate_shapes(self):
        '''
        Call frame.generate_shapes with the appropriate parameters as set by
        the user in the interface.
        '''
        if not self.rectcheckbox.isChecked():
            num_rects = 0
        else:
            num_rects = self.rectspinbox.value()
        if not self.circcheckbox.isChecked():
            num_circs = 0
        else:
            num_circs = self.circspinbox.value()
        self.frame.generate_shapes(num_rects, 
                                   num_circs, 
                                   self.rectminspinbox.value(),
                                   self.rectmaxspinbox.value(), 
                                   self.circminspinbox.value(),
                                   self.circmaxspinbox.value())
    
    def sort_available_shapes(self):
        '''
        Call frame.sort_available_shapes with the appropriate parameter to tell
        if shapes should be sorted descending by size or ascending by size
        '''
        self.frame.sort_available_shapes(not self.reversecheck.isChecked())

    def cminChange(self, cmax):
        '''
        Set value of min circle number spinbox to the value of the max circle
        number spinbox if the latter is smaller than the former.
        '''
        self.circminspinbox.setValue(min(self.circminspinbox.value(),
                                         cmax))

    def cmaxChange(self, cmin):
        '''
        Set value of max circle number spinbox to the value of the min circle
        number spinbox if the latter is greater than the former.
        '''
        self.circmaxspinbox.setValue(max(cmin,
                                         self.circmaxspinbox.value()))

    def rminChange(self, rmax):
        '''
        Set value of min rectangle number spinbox to the value of the max
        circle number spinbox if the latter is smaller than the former.
        '''
        self.rectminspinbox.setValue(min(self.rectminspinbox.value(),
                                         rmax))

    def rmaxChange(self, rmin):
        '''
        Set value of max rectangle number spinbox to the value of the min
        circle number spinbox if the latter is greater than the former.
        '''
        self.rectmaxspinbox.setValue(max(rmin,
                                         self.rectmaxspinbox.value()))
    
    def closeEvent(self, event):
        '''
        Called when trying to close programme. Shows a dialog box asking the
        user to confirm the decision.
        '''
        reply = QtGui.QMessageBox.question(self, 'Message',
            "Are you sure you want to quit?", QtGui.QMessageBox.Yes | 
            QtGui.QMessageBox.No, QtGui.QMessageBox.No)

        if reply == QtGui.QMessageBox.Yes:
            self.frame.request_end()
            event.accept()
        else:
            event.ignore()

    def keyPressEvent(self, e):
        '''
        Called when Escape is pressed to close programme.
        '''
        if e.key() == QtCore.Qt.Key_Escape:
            self.close()
            
    def center(self):
        '''
        Center self on screen.
        '''
        qr = self.frameGeometry()
        cp = QtGui.QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())