class SubWin(QMainWindow): count = 0 def __init__(self): super().__init__() self.initUI() def initUI(self): self.mdi = QMdiArea() self.setCentralWidget(self.mdi) self.toolBar = QToolBar() self.addToolBar(self.toolBar) self.toolBar.addAction("新建") self.toolBar.addAction("级联") self.toolBar.addAction("平铺") self.toolBar.addAction("关闭全部") self.toolBar.addAction("关闭活动窗口") self.toolBar.addAction("测试") self.toolBar.actionTriggered[QAction].connect(self.windowaction) bar = self.menuBar() file = bar.addMenu("File") # 添加子菜单 file.addAction("新建") file.addAction("级联") file.addAction("平铺") file.triggered[QAction].connect(self.windowaction) self.setWindowTitle("MDI Demo") #self.showFullScreen() #全屏显示 self.showMaximized() #窗口最大化 #self.showNormal() #正常显示 # self.setGeometry(QDesktopWidget().screenGeometry()) def windowaction(self, q): type = q.text() print("Triggered : %s" % type) if type == "新建": # 子窗口增加一个 self.count = self.count + 1 # 实例化多文档界面对象 sub = QMdiSubWindow() # 向sub内部添加控件 sub.setWidget(QTextEdit()) sub.setWindowTitle("subWindow %d" % self.count) self.mdi.addSubWindow(sub) sub.show() #sub.hide() elif type == "级联": self.mdi.cascadeSubWindows() elif type == "平铺": self.mdi.tileSubWindows() elif type == "关闭全部": self.mdi.closeAllSubWindows() elif type == "关闭活动窗口": self.mdi.closeActiveSubWindow() elif type == "测试": lst = self.mdi.subWindowList() print(lst) def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft())
class MainWindow(QMainWindow): """This create the main window of the application""" def __init__(self): super(MainWindow, self).__init__() # remove close & maximize window buttons #self.setWindowFlags(Qt.CustomizeWindowHint|Qt.WindowMinimizeButtonHint) self.setMinimumSize(500, 666) #self.setMaximumSize(1000,666) self.mdiArea = QMdiArea() self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setCentralWidget(self.mdiArea) self.mdiArea.subWindowActivated.connect(self.updateMenus) self.mdiArea.setViewMode(QMdiArea.TabbedView) self.windowMapper = QSignalMapper(self) self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow) self.child = None self.createActions() self.createMenus() self.createStatusBar() self.updateMenus() self.readSettings() self.setWindowTitle("LEKTURE") mytoolbar = QToolBar() #self.toolbar = self.addToolBar() mytoolbar.addAction(self.newAct) mytoolbar.addAction(self.openAct) mytoolbar.addAction(self.saveAct) mytoolbar.addAction(self.saveAsAct) mytoolbar.addSeparator() mytoolbar.addAction(self.outputsAct) mytoolbar.addAction(self.scenarioAct) self.scenarioAct.setVisible(False) mytoolbar.setMovable(False) mytoolbar.setFixedWidth(60) self.addToolBar(Qt.LeftToolBarArea, mytoolbar) def closeEvent(self, scenario): """method called when the main window wants to be closed""" self.mdiArea.closeAllSubWindows() if self.mdiArea.currentSubWindow(): scenario.ignore() else: self.writeSettings() scenario.accept() def newFile(self): """creates a new project""" child = self.createProjekt() child.newFile() child.show() self.child = child def open(self): """open a project""" fileName, _ = QFileDialog.getOpenFileName(self) if fileName: existing = self.findProjekt(fileName) if existing: self.mdiArea.setActiveSubWindow(existing) return child = self.createProjekt() if child.loadFile(fileName): self.statusBar().showMessage("File loaded", 2000) child.show() else: child.close() def save(self): """called when user save a project""" if self.activeProjekt() and self.activeProjekt().save(): self.statusBar().showMessage("File saved", 2000) else: self.statusBar().showMessage("Error when trying to save the file") def saveAs(self): """called when user save AS a project""" if self.activeProjekt() and self.activeProjekt().saveAs(): self.statusBar().showMessage("File saved", 2000) else: self.statusBar().showMessage("Error when trying to save the file") def openFolder(self): """called when user calls 'reveal in finder' function""" if self.activeProjekt() and self.activeProjekt().openFolder(): self.statusBar().showMessage("File revealed in Finder", 2000) def about(self): """called when user wants to know a bit more on the app""" import sys python_version = str(sys.version_info[0]) python_version_temp = sys.version_info[1:5] for item in python_version_temp: python_version = python_version + "." + str(item) QMessageBox.about(self, "About Lekture", "pylekture build " + str(pylekture.__version__ + "\n" + \ "python version " + str(python_version))) def updateMenus(self): """update menus""" hasProjekt = (self.activeProjekt() is not None) self.saveAct.setEnabled(hasProjekt) self.saveAsAct.setEnabled(hasProjekt) self.outputsAct.setEnabled(hasProjekt) self.scenarioAct.setEnabled(hasProjekt) self.openFolderAct.setEnabled(hasProjekt) self.closeAct.setEnabled(hasProjekt) self.closeAllAct.setEnabled(hasProjekt) self.nextAct.setEnabled(hasProjekt) self.previousAct.setEnabled(hasProjekt) self.separatorAct.setVisible(hasProjekt) def updateWindowMenu(self): """unpates menus on the window toolbar""" self.windowMenu.clear() self.windowMenu.addAction(self.closeAct) self.windowMenu.addAction(self.closeAllAct) self.windowMenu.addSeparator() self.windowMenu.addAction(self.nextAct) self.windowMenu.addAction(self.previousAct) self.windowMenu.addAction(self.separatorAct) windows = self.mdiArea.subWindowList() self.separatorAct.setVisible(len(windows) != 0) for i, window in enumerate(windows): child = window.widget() text = "%d %s" % (i + 1, child.userFriendlyCurrentFile()) if i < 9: text = '&' + text action = self.windowMenu.addAction(text) action.setCheckable(True) action.setChecked(child is self.activeProjekt()) action.triggered.connect(self.windowMapper.map) self.windowMapper.setMapping(action, window) def createProjekt(self): """create a new project""" child = Projekt() self.mdiArea.addSubWindow(child) self.child = child return child def createActions(self): """create all actions""" self.newAct = QAction("&New", self, shortcut=QKeySequence.New, statusTip="Create a new file", triggered=self.newFile) self.openAct = QAction("&Open...", self, shortcut=QKeySequence.Open, statusTip="Open an existing file", triggered=self.open) self.saveAct = QAction("&Save", self, shortcut=QKeySequence.Save, statusTip="Save the document to disk", triggered=self.save) self.saveAsAct = QAction("Save &As...", self, shortcut=QKeySequence.SaveAs, statusTip="Save the document under a new name", triggered=self.saveAs) self.openFolderAct = QAction("Open Project Folder", self, statusTip="Reveal Project in Finder", triggered=self.openFolder) self.exitAct = QAction("E&xit", self, shortcut=QKeySequence.Quit, statusTip="Exit the application", triggered=QApplication.instance().closeAllWindows) self.closeAct = QAction("Cl&ose", self, statusTip="Close the active window", triggered=self.mdiArea.closeActiveSubWindow) self.outputsAct = QAction("Outputs", self, statusTip="Open the outputs panel", triggered=self.openOutputsPanel) self.scenarioAct = QAction("Scenario", self, statusTip="Open the scenario panel", triggered=self.openScenarioPanel) self.closeAllAct = QAction("Close &All", self, statusTip="Close all the windows", triggered=self.mdiArea.closeAllSubWindows) self.nextAct = QAction("Ne&xt", self, shortcut=QKeySequence.NextChild, statusTip="Move the focus to the next window", triggered=self.mdiArea.activateNextSubWindow) self.previousAct = QAction("Pre&vious", self, shortcut=QKeySequence.PreviousChild, statusTip="Move the focus to the previous window", triggered=self.mdiArea.activatePreviousSubWindow) self.separatorAct = QAction(self) self.separatorAct.setSeparator(True) self.aboutAct = QAction("&About", self, statusTip="Show the application's About box", triggered=self.about) def createMenus(self): """create all menus""" self.fileMenu = self.menuBar().addMenu("&File") self.fileMenu.addAction(self.newAct) self.fileMenu.addAction(self.openAct) self.fileMenu.addAction(self.saveAct) self.fileMenu.addAction(self.saveAsAct) self.fileMenu.addSeparator() self.fileMenu.addAction(self.openFolderAct) self.fileMenu.addAction(self.exitAct) self.viewMenu = self.menuBar().addMenu("&View") self.viewMenu.addAction(self.outputsAct) self.viewMenu.addAction(self.scenarioAct) self.windowMenu = self.menuBar().addMenu("&Window") self.updateWindowMenu() self.windowMenu.aboutToShow.connect(self.updateWindowMenu) self.menuBar().addSeparator() self.helpMenu = self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.aboutAct) def createStatusBar(self): """create the status bar""" self.statusBar().showMessage("Ready") def readSettings(self): """read the settings""" settings = QSettings('Pixel Stereo', 'lekture') pos = settings.value('pos', QPoint(200, 200)) size = settings.value('size', QSize(1000, 650)) self.move(pos) self.resize(size) def writeSettings(self): """write settings""" settings = QSettings('Pixel Stereo', 'lekture') settings.setValue('pos', self.pos()) settings.setValue('size', self.size()) def activeProjekt(self): """return the active project object""" activeSubWindow = self.mdiArea.activeSubWindow() if activeSubWindow: return activeSubWindow.widget() else: return None def findProjekt(self, fileName): """return the project""" canonicalFilePath = QFileInfo(fileName).canonicalFilePath() for window in self.mdiArea.subWindowList(): if window.widget().currentFile() == canonicalFilePath: return window return None def setActiveSubWindow(self, window): """set the active sub window""" if window: self.mdiArea.setActiveSubWindow(window) def openOutputsPanel(self): """switch to the outputs editor""" if self.child: project = self.activeProjekt() project.scenario_events_group.setVisible(False) project.outputs_group.setVisible(True) self.scenarioAct.setVisible(True) self.outputsAct.setVisible(False) def openScenarioPanel(self): """switch to the scenario editors""" if self.child: project = self.activeProjekt() project.outputs_group.setVisible(False) project.scenario_events_group.setVisible(True) self.scenarioAct.setVisible(False) self.outputsAct.setVisible(True)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.mdiArea = QMdiArea() self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setCentralWidget(self.mdiArea) self.mdiArea.subWindowActivated.connect(self.updateMenus) self.windowMapper = QSignalMapper(self) self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow) self.createActions() self.createMenus() self.createToolBars() self.createStatusBar() self.updateMenus() self.readSettings() self.setWindowTitle("MDI") def closeEvent(self, event): self.mdiArea.closeAllSubWindows() if self.mdiArea.currentSubWindow(): event.ignore() else: self.writeSettings() event.accept() def newFile(self): child = self.createMdiChild() child.newFile() child.show() def open(self): fileName, _ = QFileDialog.getOpenFileName(self) if fileName: existing = self.findMdiChild(fileName) if existing: self.mdiArea.setActiveSubWindow(existing) return child = self.createMdiChild() if child.loadFile(fileName): self.statusBar().showMessage("File loaded", 2000) child.show() else: child.close() def save(self): if self.activeMdiChild() and self.activeMdiChild().save(): self.statusBar().showMessage("File saved", 2000) def saveAs(self): if self.activeMdiChild() and self.activeMdiChild().saveAs(): self.statusBar().showMessage("File saved", 2000) def cut(self): if self.activeMdiChild(): self.activeMdiChild().cut() def copy(self): if self.activeMdiChild(): self.activeMdiChild().copy() def paste(self): if self.activeMdiChild(): self.activeMdiChild().paste() def about(self): QMessageBox.about( self, "About MDI", "The <b>MDI</b> example demonstrates how to write multiple " "document interface applications using Qt.") def updateMenus(self): hasMdiChild = (self.activeMdiChild() is not None) self.saveAct.setEnabled(hasMdiChild) self.saveAsAct.setEnabled(hasMdiChild) self.pasteAct.setEnabled(hasMdiChild) self.closeAct.setEnabled(hasMdiChild) self.closeAllAct.setEnabled(hasMdiChild) self.tileAct.setEnabled(hasMdiChild) self.cascadeAct.setEnabled(hasMdiChild) self.nextAct.setEnabled(hasMdiChild) self.previousAct.setEnabled(hasMdiChild) self.separatorAct.setVisible(hasMdiChild) hasSelection = (self.activeMdiChild() is not None and self.activeMdiChild().textCursor().hasSelection()) self.cutAct.setEnabled(hasSelection) self.copyAct.setEnabled(hasSelection) def updateWindowMenu(self): self.windowMenu.clear() self.windowMenu.addAction(self.closeAct) self.windowMenu.addAction(self.closeAllAct) self.windowMenu.addSeparator() self.windowMenu.addAction(self.tileAct) self.windowMenu.addAction(self.cascadeAct) self.windowMenu.addSeparator() self.windowMenu.addAction(self.nextAct) self.windowMenu.addAction(self.previousAct) self.windowMenu.addAction(self.separatorAct) windows = self.mdiArea.subWindowList() self.separatorAct.setVisible(len(windows) != 0) for i, window in enumerate(windows): child = window.widget() text = "%d %s" % (i + 1, child.userFriendlyCurrentFile()) if i < 9: text = '&' + text action = self.windowMenu.addAction(text) action.setCheckable(True) action.setChecked(child is self.activeMdiChild()) action.triggered.connect(self.windowMapper.map) self.windowMapper.setMapping(action, window) def createMdiChild(self): child = MdiChild() self.mdiArea.addSubWindow(child) child.copyAvailable.connect(self.cutAct.setEnabled) child.copyAvailable.connect(self.copyAct.setEnabled) return child def createActions(self): self.newAct = QAction(QIcon(':/images/new.png'), "&New", self, shortcut=QKeySequence.New, statusTip="Create a new file", triggered=self.newFile) self.openAct = QAction(QIcon(':/images/open.png'), "&Open...", self, shortcut=QKeySequence.Open, statusTip="Open an existing file", triggered=self.open) self.saveAct = QAction(QIcon(':/images/save.png'), "&Save", self, shortcut=QKeySequence.Save, statusTip="Save the document to disk", triggered=self.save) self.saveAsAct = QAction( "Save &As...", self, shortcut=QKeySequence.SaveAs, statusTip="Save the document under a new name", triggered=self.saveAs) self.exitAct = QAction( "E&xit", self, shortcut=QKeySequence.Quit, statusTip="Exit the application", triggered=QApplication.instance().closeAllWindows) self.cutAct = QAction( QIcon(':/images/cut.png'), "Cu&t", self, shortcut=QKeySequence.Cut, statusTip="Cut the current selection's contents to the clipboard", triggered=self.cut) self.suggestAct = QAction( "Suggest", self, shortcut=QKeySequence.Copy, statusTip="Cut the current selection's contents to the clipboard", triggered=self.copy) self.copyAct = QAction( QIcon(':/images/copy.png'), "&Copy", self, shortcut=QKeySequence.Copy, statusTip="Copy the current selection's contents to the clipboard", triggered=self.copy) self.pasteAct = QAction( QIcon(':/images/paste.png'), "&Paste", self, shortcut=QKeySequence.Paste, statusTip= "Paste the clipboard's contents into the current selection", triggered=self.paste) self.closeAct = QAction("Cl&ose", self, statusTip="Close the active window", triggered=self.mdiArea.closeActiveSubWindow) self.closeAllAct = QAction("Close &All", self, statusTip="Close all the windows", triggered=self.mdiArea.closeAllSubWindows) self.tileAct = QAction("&Tile", self, statusTip="Tile the windows", triggered=self.mdiArea.tileSubWindows) self.cascadeAct = QAction("&Cascade", self, statusTip="Cascade the windows", triggered=self.mdiArea.cascadeSubWindows) self.nextAct = QAction("Ne&xt", self, shortcut=QKeySequence.NextChild, statusTip="Move the focus to the next window", triggered=self.mdiArea.activateNextSubWindow) self.previousAct = QAction( "Pre&vious", self, shortcut=QKeySequence.PreviousChild, statusTip="Move the focus to the previous window", triggered=self.mdiArea.activatePreviousSubWindow) self.separatorAct = QAction(self) self.separatorAct.setSeparator(True) self.aboutAct = QAction("&About", self, statusTip="Show the application's About box", triggered=self.about) self.aboutQtAct = QAction("About &Qt", self, statusTip="Show the Qt library's About box", triggered=QApplication.instance().aboutQt) def createMenus(self): self.fileMenu = self.menuBar().addMenu("&File") self.fileMenu.addAction(self.newAct) self.fileMenu.addAction(self.openAct) self.fileMenu.addAction(self.saveAct) self.fileMenu.addAction(self.saveAsAct) self.fileMenu.addSeparator() action = self.fileMenu.addAction("Switch layout direction") action.triggered.connect(self.switchLayoutDirection) self.fileMenu.addAction(self.exitAct) self.editMenu = self.menuBar().addMenu("&Edit") self.editMenu.addAction(self.cutAct) self.editMenu.addAction(self.copyAct) self.editMenu.addAction(self.pasteAct) self.windowMenu = self.menuBar().addMenu("&Window") self.updateWindowMenu() self.windowMenu.aboutToShow.connect(self.updateWindowMenu) self.menuBar().addSeparator() self.helpMenu = self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.aboutAct) self.helpMenu.addAction(self.aboutQtAct) def createToolBars(self): self.fileToolBar = self.addToolBar("File") self.fileToolBar.addAction(self.newAct) self.fileToolBar.addAction(self.openAct) self.fileToolBar.addAction(self.saveAct) self.editToolBar = self.addToolBar("Edit") self.editToolBar.addAction(self.cutAct) self.editToolBar.addAction(self.copyAct) self.editToolBar.addAction(self.pasteAct) def createStatusBar(self): self.statusBar().showMessage("Ready") def readSettings(self): settings = QSettings('Trolltech', 'MDI Example') pos = settings.value('pos', QPoint(200, 200)) size = settings.value('size', QSize(400, 400)) self.move(pos) self.resize(size) def writeSettings(self): settings = QSettings('Trolltech', 'MDI Example') settings.setValue('pos', self.pos()) settings.setValue('size', self.size()) def activeMdiChild(self): activeSubWindow = self.mdiArea.activeSubWindow() if activeSubWindow: return activeSubWindow.widget() return None def findMdiChild(self, fileName): canonicalFilePath = QFileInfo(fileName).canonicalFilePath() for window in self.mdiArea.subWindowList(): if window.widget().currentFile() == canonicalFilePath: return window return None def switchLayoutDirection(self): if self.layoutDirection() == Qt.LeftToRight: QApplication.setLayoutDirection(Qt.RightToLeft) else: QApplication.setLayoutDirection(Qt.LeftToRight) def setActiveSubWindow(self, window): if window: self.mdiArea.setActiveSubWindow(window) def contextMenuEvent(self, event): menu = QMenu(self) menu.addAction(self.cutAct) menu.addAction(self.copyAct) menu.addAction(self.pasteAct) menu.addAction(self.suggestAct) menu.exec_(event.globalPos())
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.mdi = QMdiArea() self.setCentralWidget(self.mdi) fileNewAction = self.createAction("&New", self.fileNew, QKeySequence.New, "filenew", "Create a text file") fileOpenAction = self.createAction("&Open...", self.fileOpen, QKeySequence.Open, "fileopen", "Open an existing text file") fileSaveAction = self.createAction("&Save", self.fileSave, QKeySequence.Save, "filesave", "Save the text") fileSaveAsAction = self.createAction( "Save &As...", self.fileSaveAs, icon="filesaveas", tip="Save the text using a new filename") fileSaveAllAction = self.createAction("Save A&ll", self.fileSaveAll, "filesave", tip="Save all the files") fileQuitAction = self.createAction("&Quit", self.close, "Ctrl+Q", "filequit", "Close the application") editCopyAction = self.createAction("&Copy", self.editCopy, QKeySequence.Copy, "editcopy", "Copy text to the clipboard") editCutAction = self.createAction("Cu&t", self.editCut, QKeySequence.Cut, "editcut", "Cut text to the clipboard") editPasteAction = self.createAction("&Paste", self.editPaste, QKeySequence.Paste, "editpaste", "Paste in the clipboard's text") self.windowNextAction = self.createAction( "&Next", self.mdi.activateNextSubWindow, QKeySequence.NextChild) self.windowPrevAction = self.createAction( "&Previous", self.mdi.activatePreviousSubWindow, QKeySequence.PreviousChild) self.windowCascadeAction = self.createAction( "Casca&de", self.mdi.cascadeSubWindows) self.windowTileAction = self.createAction("&Tile", self.mdi.tileSubWindows) self.windowRestoreAction = self.createAction("&Restore All", self.windowRestoreAll) self.windowMinimizeAction = self.createAction("&Iconize All", self.windowMinimizeAll) #self.windowArrangeIconsAction = self.createAction( # "&Arrange Icons", self.mdi.arrangeIcons) self.windowArrangeIconsAction = self.createAction( "&Arrange Icons", self.windowMinimizeAll) self.windowCloseAction = self.createAction( "&Close", self.mdi.closeActiveSubWindow, QKeySequence.Close) self.windowMapper = QSignalMapper(self) self.windowMapper.mapped[QWidget].connect(self.mdi.setActiveSubWindow) fileMenu = self.menuBar().addMenu("&File") self.addActions( fileMenu, (fileNewAction, fileOpenAction, fileSaveAction, fileSaveAsAction, fileSaveAllAction, None, fileQuitAction)) editMenu = self.menuBar().addMenu("&Edit") self.addActions(editMenu, (editCopyAction, editCutAction, editPasteAction)) self.windowMenu = self.menuBar().addMenu("&Window") self.windowMenu.aboutToShow.connect(self.updateWindowMenu) fileToolbar = self.addToolBar("File") fileToolbar.setObjectName("FileToolbar") self.addActions(fileToolbar, (fileNewAction, fileOpenAction, fileSaveAction)) editToolbar = self.addToolBar("Edit") editToolbar.setObjectName("EditToolbar") self.addActions(editToolbar, (editCopyAction, editCutAction, editPasteAction)) settings = QSettings() if settings.value("MainWindow/Geometry") or settings.value( "MainWindow/State"): self.restoreGeometry( QByteArray(settings.value("MainWindow/Geometry"))) self.restoreState(QByteArray(settings.value("MainWindow/State"))) status = self.statusBar() status.setSizeGripEnabled(False) status.showMessage("Ready", 5000) self.updateWindowMenu() self.setWindowTitle("Text Editor") QTimer.singleShot(0, self.loadFiles) def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()"): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/{0}.png".format(icon))) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: action.triggered.connect(slot) if checkable: action.setCheckable(True) return action def addActions(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def closeEvent(self, event): failures = [] for textEdit in self.mdi.subWindowList(): textEdit = textEdit.widget() if textEdit.isModified(): try: textEdit.save() except IOError as e: failures.append(str(e)) if (failures and QMessageBox.warning( self, "Text Editor -- Save Error", "Failed to save{0}\nQuit anyway?".format( "\n\t".join(failures)), QMessageBox.Yes | QMessageBox.No) == QMessageBox.No): event.ignore() return settings = QSettings() settings.setValue("MainWindow/Geometry", self.saveGeometry()) settings.setValue("MainWindow/State", self.saveState()) files = [] for textEdit in self.mdi.subWindowList(): textEdit = textEdit.widget() if not textEdit.filename.startswith("Unnamed"): files.append(textEdit.filename) settings.setValue("CurrentFiles", files) self.mdi.closeAllSubWindows() def loadFiles(self): if len(sys.argv) > 1: for filename in sys.argv[1:31]: # Load at most 30 files filename = filename if QFileInfo(filename).isFile(): self.loadFile(filename) QApplication.processEvents() else: settings = QSettings() #files = settings.value("CurrentFiles").toStringList() if settings.value("CurrentFiles"): files = settings.value("CurrentFiles") for filename in files: filename = filename if QFile.exists(filename): self.loadFile(filename) QApplication.processEvents() def fileNew(self): textEdit = textedit.TextEdit() self.mdi.addSubWindow(textEdit) textEdit.show() def fileOpen(self): filename, filetype = QFileDialog.getOpenFileName( self, "Text Editor -- Open File") if filename: for textEdit_MSW in self.mdi.subWindowList(): textEdit = textEdit_MSW.widget() if textEdit.filename == filename: self.mdi.setActiveSubWindow(textEdit_MSW) break else: self.loadFile(filename) def loadFile(self, filename): textEdit = textedit.TextEdit(filename) try: textEdit.load() except EnvironmentError as e: QMessageBox.warning(self, "Text Editor -- Load Error", "Failed to load {0}: {1}".format(filename, e)) textEdit.close() del textEdit else: self.mdi.addSubWindow(textEdit) textEdit.show() def fileSave(self): textEdit = self.mdi.activeSubWindow() textEdit = textEdit.widget() if textEdit is None or not isinstance(textEdit, QTextEdit): return True try: textEdit.save() return True except EnvironmentError as e: QMessageBox.warning( self, "Text Editor -- Save Error", "Failed to save {0}: {1}".format(textEdit.filename, e)) return False def fileSaveAs(self): textEdit = self.mdi.activeSubWindow() textEdit = textEdit.widget() if textEdit is None or not isinstance(textEdit, QTextEdit): return filename, filetype = QFileDialog.getSaveFileName( self, "Text Editor -- Save File As", textEdit.filename, "Text files (*.txt *.*)") if filename: textEdit.filename = filename return self.fileSave() return True def fileSaveAll(self): errors = [] for textEdit in self.mdi.subWindowList(): textEdit = textEdit.widget() if textEdit.isModified(): try: textEdit.save() except EnvironmentError as e: errors.append("{0}: {1}".format(textEdit.filename, e)) if errors: QMessageBox.warning( self, "Text Editor -- Save All Error", "Failed to save\n{0}".format("\n".join(errors))) def editCopy(self): textEdit = self.mdi.activeSubWindow() textEdit = textEdit.widget() if textEdit is None or not isinstance(textEdit, QTextEdit): return cursor = textEdit.textCursor() text = cursor.selectedText() if text: clipboard = QApplication.clipboard() clipboard.setText(text) def editCut(self): textEdit = self.mdi.activeSubWindow() textEdit = textEdit.widget() if textEdit is None or not isinstance(textEdit, QTextEdit): return cursor = textEdit.textCursor() text = cursor.selectedText() if text: cursor.removeSelectedText() clipboard = QApplication.clipboard() clipboard.setText(text) def editPaste(self): textEdit = self.mdi.activeSubWindow() textEdit = textEdit.widget() if textEdit is None or not isinstance(textEdit, QTextEdit): return clipboard = QApplication.clipboard() textEdit.insertPlainText(clipboard.text()) def windowRestoreAll(self): for textEdit in self.mdi.subWindowList(): textEdit = textEdit.widget() textEdit.showNormal() def windowMinimizeAll(self): for textEdit in self.mdi.subWindowList(): textEdit = textEdit.widget() textEdit.showMinimized() def updateWindowMenu(self): self.windowMenu.clear() self.addActions( self.windowMenu, (self.windowNextAction, self.windowPrevAction, self.windowCascadeAction, self.windowTileAction, self.windowRestoreAction, self.windowMinimizeAction, self.windowArrangeIconsAction, None, self.windowCloseAction)) textEdits = self.mdi.subWindowList() if not textEdits: return self.windowMenu.addSeparator() i = 1 menu = self.windowMenu for textEdit_MSW in textEdits: textEdit = textEdit_MSW.widget() title = textEdit.windowTitle() if i == 10: self.windowMenu.addSeparator() menu = menu.addMenu("&More") accel = "" if i < 10: accel = "&{0} ".format(i) elif i < 36: accel = "&{0} ".format(chr(i + ord("@") - 9)) action = menu.addAction("{0}{1}".format(accel, title)) self.windowMapper.setMapping(action, textEdit_MSW) action.triggered.connect(self.windowMapper.map) i += 1
class MainWindow(QMainWindow): """This create the main window of the application""" def __init__(self): super(MainWindow, self).__init__() self.ports = serial.listports() self.port = None # remove close & maximize window buttons #self.setWindowFlags(Qt.CustomizeWindowHint|Qt.WindowMinimizeButtonHint) self.setMinimumSize(850, 450) self.mdiArea = QMdiArea() self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setCentralWidget(self.mdiArea) self.mdiArea.subWindowActivated.connect(self.updateMenus) self.mdiArea.setViewMode(QMdiArea.TabbedView) self.windowMapper = QSignalMapper(self) self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow) self.child = None self.createActions() self.createMenus() self.createStatusBar() self.updateMenus() self.readSettings() self.setWindowTitle("VISCAM") mytoolbar = QToolBar() ports_menu = QComboBox() ports_menu.addItem('Output Port') ports_menu.insertSeparator(1) for port in self.ports: ports_menu.addItem(port) self.ports_menu = ports_menu ports_menu.currentTextChanged.connect(self.setActivePort) mytoolbar.addWidget(ports_menu) mytoolbar.addSeparator() mytoolbar.setMovable(False) mytoolbar.setFixedHeight(60) self.addToolBar(Qt.TopToolBarArea, mytoolbar) def closeEvent(self, scenario): self.mdiArea.closeAllSubWindows() if self.mdiArea.currentSubWindow(): scenario.ignore() else: self.writeSettings() scenario.accept() def about(self): QMessageBox.about( self, "About Viscam", "<b>Viscam</b> controls and manage your video camera through VISCA protocol." "This release is an alpha version. Don't use it in production !!") def updateMenus(self): hasCamera = (self.activeCamera() is not None) self.nextAct.setEnabled(hasCamera) self.previousAct.setEnabled(hasCamera) self.separatorAct.setVisible(hasCamera) def updatePortMenu(self): self.PortMenu.clear() for i, port in enumerate(self.ports): text = "%d %s" % (i + 1, port) if i < 9: text = '&' + text action = self.PortMenu.addAction(text) action.setCheckable(True) if port == self.port: action.setChecked(True) action.triggered.connect(self.setActivePort) def updateWindowMenu(self): self.windowMenu.clear() self.windowMenu.addAction(self.nextAct) self.windowMenu.addAction(self.previousAct) self.windowMenu.addAction(self.separatorAct) windows = self.mdiArea.subWindowList() self.separatorAct.setVisible(len(windows) != 0) for i, window in enumerate(windows): child = window.widget() text = "%d %s" % (i + 1, child.userFriendlyCurrentFile()) if i < 9: text = '&' + text action = self.windowMenu.addAction(text) action.setCheckable(True) action.setChecked(child is self.activeCamera()) action.triggered.connect(self.windowMapper.map) self.windowMapper.setMapping(action, window) def createCamera(self): child = Camera(serial) self.mdiArea.addSubWindow(child) child.newFile() self.child = child return child def createActions(self): self.exitAct = QAction( "E&xit", self, shortcut=QKeySequence.Quit, statusTip="Exit the application", triggered=QApplication.instance().closeAllWindows) self.closeAct = QAction("Cl&ose", self, statusTip="Close the active window", triggered=self.mdiArea.closeActiveSubWindow) self.closeAllAct = QAction("Close &All", self, statusTip="Close all the windows", triggered=self.mdiArea.closeAllSubWindows) self.nextAct = QAction("Ne&xt", self, shortcut=QKeySequence.NextChild, statusTip="Move the focus to the next window", triggered=self.mdiArea.activateNextSubWindow) self.previousAct = QAction( "Pre&vious", self, shortcut=QKeySequence.PreviousChild, statusTip="Move the focus to the previous window", triggered=self.mdiArea.activatePreviousSubWindow) self.separatorAct = QAction(self) self.separatorAct.setSeparator(True) self.aboutAct = QAction("&About", self, statusTip="Show the application's About box", triggered=self.about) def createMenus(self): self.fileMenu = self.menuBar().addMenu("&File") self.fileMenu.addAction(self.exitAct) self.PortMenu = self.menuBar().addMenu("&Ports") self.updatePortMenu() self.PortMenu.aboutToShow.connect(self.updatePortMenu) self.windowMenu = self.menuBar().addMenu("&Window") self.updateWindowMenu() self.windowMenu.aboutToShow.connect(self.updateWindowMenu) self.menuBar().addSeparator() self.helpMenu = self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.aboutAct) def createStatusBar(self): self.statusBar().showMessage("Ready") def readSettings(self): settings = QSettings('Pixel Stereo', 'viscam') port = settings.value('port') pos = settings.value('pos', QPoint(200, 200)) size = settings.value('size', QSize(1000, 650)) self.move(pos) self.resize(size) def writeSettings(self): settings = QSettings('Pixel Stereo', 'viscam') settings.setValue('port', self.port) settings.setValue('pos', self.pos()) settings.setValue('size', self.size()) def activeCamera(self): activeSubWindow = self.mdiArea.activeSubWindow() if activeSubWindow: return activeSubWindow.widget() else: return None def findCamera(self, fileName): canonicalFilePath = QFileInfo(fileName).canonicalFilePath() for window in self.mdiArea.subWindowList(): if window.widget().currentFile() == canonicalFilePath: return window return None def setActiveSubWindow(self, window): if window: self.mdiArea.setActiveSubWindow(window) def setActivePort(self): self.port = self.ports_menu.currentText().encode('utf-8') self.updatePortMenu() serial.open(portname=self.port) viscams = _cmd_adress_set(serial) _if_clear(serial) for v in viscams: v = self.createCamera()
class CalculatorWindow(NodeEditorWindow): """Class representing the MainWindow of the application. Instance Attributes: name_company and name_product - used to register the settings """ def initUI(self): """UI is composed with """ # variable for QSettings self.name_company = 'Michelin' self.name_product = 'Calculator NodeEditor' # Load filesheets self.stylesheet_filename = os.path.join(os.path.dirname(__file__), 'qss/nodeeditor.qss') loadStylessheets( os.path.join(os.path.dirname(__file__), 'qss/nodeeditor-dark.qss'), self.stylesheet_filename) self.empty_icon = QIcon(".") if DEBUG: print('Registered Node') pp(CALC_NODES) # Instantiate the MultiDocument Area self.mdiArea = QMdiArea() self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.mdiArea.setViewMode(QMdiArea.TabbedView) self.mdiArea.setTabsClosable(True) self.setCentralWidget(self.mdiArea) # Connect subWindowActivate to updateMenu # Activate the items on the file_menu and the edit_menu self.mdiArea.subWindowActivated.connect(self.updateMenus) # from mdi example... self.windowMapper = QSignalMapper(self) self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow) # instantiate various elements self.createNodesDock() self.createActions() self.createMenus() self.createToolBars() self.createStatusBar() self.updateMenus() self.readSettings() self.setWindowTitle("Calculator NodeEditor Example") def createActions(self): """Instantiate various `QAction` for the main toolbar. File and Edit menu actions are instantiated in the :classs:~`node_editor.node_editor_widget.NodeEditorWidget` Window and Help actions are specific to the :class:~`examples.calc_window.CalcWindow` """ super().createActions() self.actClose = QAction("Cl&ose", self, statusTip="Close the active window", triggered=self.mdiArea.closeActiveSubWindow) self.actCloseAll = QAction("Close &All", self, statusTip="Close all the windows", triggered=self.mdiArea.closeAllSubWindows) self.actTile = QAction("&Tile", self, statusTip="Tile the windows", triggered=self.mdiArea.tileSubWindows) self.actCascade = QAction("&Cascade", self, statusTip="Cascade the windows", triggered=self.mdiArea.cascadeSubWindows) self.actNext = QAction("Ne&xt", self, shortcut=QKeySequence.NextChild, statusTip="Move the focus to the next window", triggered=self.mdiArea.activateNextSubWindow) self.actPrevious = QAction( "Pre&vious", self, shortcut=QKeySequence.PreviousChild, statusTip="Move the focus to the previous window", triggered=self.mdiArea.activatePreviousSubWindow) self.actSeparator = QAction(self) self.actSeparator.setSeparator(True) self.actAbout = QAction("&About", self, statusTip="Show the application's About box", triggered=self.about) def createMenus(self): """Populate File, Edit, Window and Help with `QAction`""" super().createMenus() self.windowMenu = self.menuBar().addMenu("&Window") self.updateWindowMenu() self.windowMenu.aboutToShow.connect(self.updateWindowMenu) self.menuBar().addSeparator() self.helpMenu = self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.actAbout) # Any time the edit menu is about to be shown, update it self.editMenu.aboutToShow.connect(self.updateEditMenu) def onWindowNodesToolbar(self): """Event handling the visibility of the `Nodes Dock`""" if self.nodesDock.isVisible(): self.nodesDock.hide() else: self.nodesDock.show() def createToolBars(self): pass def createNodesDock(self): """Create `Nodes Dock` and populates it with the list of `Nodes` The `Nodes` are automatically detected via the :class:~`examples.calc_drag_listbox.QNEDragListBox` """ self.nodeListWidget = QNEDragListbox() self.nodesDock = QDockWidget("Nodes") self.nodesDock.setWidget(self.nodeListWidget) self.nodesDock.setFloating(False) self.addDockWidget(Qt.RightDockWidgetArea, self.nodesDock) def createStatusBar(self): self.statusBar().showMessage("Ready", ) def updateMenus(self): active = self.getCurrentNodeEditorWidget() hasMdiChild = (active is not None) self.actSave.setEnabled(hasMdiChild) self.actSaveAs.setEnabled(hasMdiChild) self.actClose.setEnabled(hasMdiChild) self.actCloseAll.setEnabled(hasMdiChild) self.actTile.setEnabled(hasMdiChild) self.actCascade.setEnabled(hasMdiChild) self.actNext.setEnabled(hasMdiChild) self.actPrevious.setEnabled(hasMdiChild) self.actSeparator.setVisible(hasMdiChild) self.updateEditMenu() def updateEditMenu(self): if DEBUG: print('updateEditMenu') try: active = self.getCurrentNodeEditorWidget() hasMdiChild = (active is not None) hasSelectedItems = hasMdiChild and active.hasSelectedItems() self.actPaste.setEnabled(hasMdiChild) self.actCut.setEnabled(hasSelectedItems) self.actCopy.setEnabled(hasSelectedItems) self.actDelete.setEnabled(hasSelectedItems) self.actUndo.setEnabled(hasMdiChild and active.canUndo()) self.actRedo.setEnabled(hasMdiChild and active.canRedo()) except Exception as e: dumpException(e) def updateWindowMenu(self): self.windowMenu.clear() toolbar_nodes = self.windowMenu.addAction('Nodes toolbar') toolbar_nodes.setCheckable(True) toolbar_nodes.triggered.connect(self.onWindowNodesToolbar) toolbar_nodes.setChecked(self.nodesDock.isVisible()) self.windowMenu.addSeparator() self.windowMenu.addAction(self.actClose) self.windowMenu.addAction(self.actCloseAll) self.windowMenu.addSeparator() self.windowMenu.addAction(self.actTile) self.windowMenu.addAction(self.actCascade) self.windowMenu.addSeparator() self.windowMenu.addAction(self.actNext) self.windowMenu.addAction(self.actPrevious) self.windowMenu.addAction(self.actSeparator) windows = self.mdiArea.subWindowList() self.actSeparator.setVisible(len(windows) != 0) for i, window in enumerate(windows): child = window.widget() text = "%d %s" % (i + 1, child.getUserFriendlyFilename()) if i < 9: text = '&' + text action = self.windowMenu.addAction(text) action.setCheckable(True) action.setChecked(child is self.getCurrentNodeEditorWidget()) action.triggered.connect(self.windowMapper.map) self.windowMapper.setMapping(action, window) def getCurrentNodeEditorWidget(self) -> NodeEditorWidget: """Return the widget currently holding the scene. For different application, the method can be overridden to return mdiArea, the central widget... Returns ------- NodeEditorWidget Node editor Widget. The widget holding the scene. """ activeSubWindow = self.mdiArea.activeSubWindow() if activeSubWindow: return activeSubWindow.widget() return None def onFileNew(self): try: subwnd = self.createMdiChild() subwnd.widget().fileNew() subwnd.show() except Exception as e: dumpException(e) def onFileOpen(self): """Open OpenFileDialog""" # OpenFile dialog fnames, filter = QFileDialog.getOpenFileNames( self, 'Open graph from file', self.getFileDialogDirectory(), self.getFileDialogFilter()) try: for fname in fnames: if fname: existing = self.findMdiChild(fname) if existing: self.mdiArea.setActiveSubWindow(existing) else: # do not use createMdiChild as a new node editor to call the fileLoad method # Create new subwindow and open file nodeeditor = CalculatorSubWindow() if nodeeditor.fileLoad(fname): self.statusBar().showMessage( f'File {fname} loaded', 5000) nodeeditor.setTitle() subwnd = self.createMdiChild(nodeeditor) subwnd.show() else: nodeeditor.close() except Exception as e: dumpException(e) def about(self): QMessageBox.about( self, "About Calculator NodeEditor Example", "The <b>Calculator NodeEditor</b> example demonstrates how to write multiple " "document interface applications using PyQt5 and NodeEditor.") def closeEvent(self, event: QCloseEvent) -> None: try: self.mdiArea.closeAllSubWindows() if self.mdiArea.currentSubWindow(): event.ignore() else: self.writeSettings() event.accept() # In case of fixing the application closing # import sys # sys.exit(0) except Exception as e: dumpException(e) def createMdiChild(self, child_widget=None): nodeeditor = child_widget if child_widget is not None else CalculatorSubWindow( ) subwnd = self.mdiArea.addSubWindow(nodeeditor, ) subwnd.setWindowIcon(self.empty_icon) # nodeeditor.scene.addItemSelectedListener(self.updateEditMenu) # nodeeditor.scene.addItemsDeselectedListener(self.updateEditMenu) nodeeditor.scene.history.addHistoryModifiedListener( self.updateEditMenu) nodeeditor.addCloseEventListener(self.onSubWndClose) return subwnd def onSubWndClose(self, widget: CalculatorSubWindow, event: QCloseEvent): # close event from the nodeeditor works by asking the active widget # if modification occurs on the active widget, ask to save or not. # Therefore when closing a subwindow, select the corresponding subwindow existing = self.findMdiChild(widget.filename) self.mdiArea.setActiveSubWindow(existing) # Does the active widget need to be saved ? if self.maybeSave(): event.accept() else: event.ignore() def findMdiChild(self, fileName): for window in self.mdiArea.subWindowList(): if window.widget().filename == fileName: return window return None def setActiveSubWindow(self, window): if window: self.mdiArea.setActiveSubWindow(window)
class RDFNavigator(QMainWindow): output_message = pyqtSignal(str) def __init__(self): super(RDFNavigator, self).__init__() self.lastDir = '.' self.settingsManager = RDFNavigatorSettignsManager() self.resourceRefManager = RDFNavigatorResourceReferenceManager() self.childrenFactory = RDFNavigatorChildrenFactory(self) self.mdiArea = QMdiArea() self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setCentralWidget(self.mdiArea) self.mdiArea.subWindowActivated.connect(self.updateMenus) self.windowMapper = QSignalMapper(self) self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow) self.createActions() self.createMenus() self.createToolBars() self.createStatusBar() self.updateMenus() self.createDockWidgets() self.readSettings() self.setWindowTitle("RDF Navigator") self.global_data = {} self.analyzeSystemData() #self.setStyleSheet("""QToolTip { background-color: black; color: white; border: black solid 1px }""") def closeEvent(self, event): self.mdiArea.closeAllSubWindows() if self.mdiArea.currentSubWindow(): event.ignore() else: self.writeSettings() event.accept() def newFile(self, fileType): child = self.createMdiChild(fileType) child.newFile() child.show() def openFileHelper(self, fileName, fileType): if fileName: self.lastDir = os.path.dirname(fileName) existing = self.findMdiChild(fileName) if existing: self.mdiArea.setActiveSubWindow(existing) return child = self.createMdiChild(fileType) child.setManager(self.settingsManager) if child.loadFile(fileName): self.statusBar().showMessage("File loaded", 2000) child.show() else: child.close() def open(self): fileName, _ = QFileDialog.getOpenFileName( self, "Open runntime data format file", self.lastDir, "RDF Files (*.RDF);;XML Files (*.xml)") self.openFileHelper(fileName, RDFNavigatorChildrenTypes.XML) def openProject(self): fileName, _ = QFileDialog.getOpenFileName( self, "Open XML schema project file", self.lastDir, "XML Schema Files (*.xsd);;") self.openFileHelper(fileName, RDFNavigatorChildrenTypes.SCHEMA) child = self.findMdiChild(fileName) if child: schema = RDFNavigatorXmlSchema() schema.validation_message.connect(self.output_message) schema.setSchemaPath(fileName) graph = schema.getSchemaDependencyGraph() self.projectStructureWidget.createProjectTree( fileName, graph, RDFNavigatorChildrenTypes.SCHEMA) self.projectStructureWidget.open_file_request.connect( self.openFileHelper) def openTemplate(self): fileName, _ = QFileDialog.getOpenFileName( self, "Open system data template file", self.lastDir, "XML Template Files (*.xml);;") self.openFileHelper(fileName, RDFNavigatorChildrenTypes.TEMPLATE) child = self.findMdiChild(fileName) if child: schema = RDFNavigatorXmlSchema() schema.validation_message.connect(self.output_message) schema.setSchemaPath(fileName) graph = schema.getTemplateDependencyGraph() self.projectStructureWidget.createProjectTree( fileName, graph, RDFNavigatorChildrenTypes.TEMPLATE) self.projectStructureWidget.createObjectsTree(fileName) self.projectStructureWidget.createFileSystemTree(fileName) self.projectStructureWidget.open_file_request.connect( self.openFileHelper) self.analyzeTemplateData(os.path.dirname(fileName)) def save(self): if self.activeMdiChild() and self.activeMdiChild().save(): self.statusBar().showMessage("File saved", 2000) def saveAs(self): if self.activeMdiChild() and self.activeMdiChild().saveAs(): self.statusBar().showMessage("File saved", 2000) def cut(self): if self.activeMdiChild(): self.activeMdiChild().cut() def copy(self): if self.activeMdiChild(): self.activeMdiChild().copy() def paste(self): if self.activeMdiChild(): self.activeMdiChild().paste() def activateFind(self): child = self.activeMdiChild() find = RDFNavigatorFind(self) find.findAllCurrentClicked.connect(child.findAll) find.findNextClicked.connect(child.findNextWord) find.findCountClicked.connect(child.countWord) if child.hasSelectedText(): text = child.selectedText() find.setFindText(text) find.show() def about(self): QMessageBox.about(self, "About RDF Navigator", "Tool to simplify work with RDF data") def updateMenus(self): hasMdiChild = (self.activeMdiChild() is not None) self.saveAct.setEnabled(hasMdiChild) self.saveAsAct.setEnabled(hasMdiChild) self.pasteAct.setEnabled(hasMdiChild) self.closeAct.setEnabled(hasMdiChild) self.closeAllAct.setEnabled(hasMdiChild) self.tileAct.setEnabled(hasMdiChild) self.cascadeAct.setEnabled(hasMdiChild) self.nextAct.setEnabled(hasMdiChild) self.previousAct.setEnabled(hasMdiChild) self.separatorAct.setVisible(hasMdiChild) hasSelection = (self.activeMdiChild() is not None and self.activeMdiChild().hasSelectedText()) self.cutAct.setEnabled(hasSelection) self.copyAct.setEnabled(hasSelection) def updateWindowMenu(self): self.windowMenu.clear() self.windowMenu.addAction(self.closeAct) self.windowMenu.addAction(self.closeAllAct) self.windowMenu.addSeparator() self.windowMenu.addAction(self.tileAct) self.windowMenu.addAction(self.cascadeAct) self.windowMenu.addSeparator() self.windowMenu.addAction(self.nextAct) self.windowMenu.addAction(self.previousAct) self.windowMenu.addAction(self.separatorAct) windows = self.mdiArea.subWindowList() self.separatorAct.setVisible(len(windows) != 0) for i, window in enumerate(windows): child = window.widget() text = "%d %s" % (i + 1, child.userFriendlyCurrentFile()) if i < 9: text = '&' + text action = self.windowMenu.addAction(text) action.setCheckable(True) action.setChecked(child is self.activeMdiChild()) action.triggered.connect(self.windowMapper.map) self.windowMapper.setMapping(action, window) def createMdiChild(self, childType): child = self.childrenFactory.createObject(childType) self.mdiArea.addSubWindow(child) child.copyAvailable.connect(self.cutAct.setEnabled) child.copyAvailable.connect(self.copyAct.setEnabled) return child def createActions(self): self.newAct = QAction(QIcon(':/images/new.png'), "&New", self, shortcut=QKeySequence.New, statusTip="Create a new file", triggered=self.newFile) self.openFileAct = QAction(QIcon(':/images/open.png'), "&Open file...", self, shortcut=QKeySequence.Open, statusTip="Open an existing file", triggered=self.open) self.openProjectAct = QAction(QIcon(':/images/openProject.png'), "&Open project...", self, shortcut=QKeySequence("Ctrl+Shift+O"), statusTip="Open an existing project", triggered=self.openProject) self.openTemplate = QAction(QIcon(':/images/sdt.png'), "&Open template...", self, shortcut=QKeySequence("Alt+Shift+O"), statusTip="Open an existing template", triggered=self.openTemplate) self.saveAct = QAction(QIcon(':/images/save.png'), "&Save", self, shortcut=QKeySequence.Save, statusTip="Save the document to disk", triggered=self.save) self.saveAsAct = QAction( "Save &As...", self, shortcut=QKeySequence.SaveAs, statusTip="Save the document under a new name", triggered=self.saveAs) self.exitAct = QAction( "E&xit", self, shortcut=QKeySequence.Quit, statusTip="Exit the application", triggered=QApplication.instance().closeAllWindows) self.cutAct = QAction( QIcon(':/images/cut.png'), "Cu&t", self, shortcut=QKeySequence.Cut, statusTip="Cut the current selection's contents to the clipboard", triggered=self.cut) self.copyAct = QAction( QIcon(':/images/copy.png'), "&Copy", self, shortcut=QKeySequence.Copy, statusTip="Copy the current selection's contents to the clipboard", triggered=self.copy) self.pasteAct = QAction( QIcon(':/images/paste.png'), "&Paste", self, shortcut=QKeySequence.Paste, statusTip= "Paste the clipboard's contents into the current selection", triggered=self.paste) self.findAct = QAction(QIcon(':/images/find.png'), "&Find", self, shortcut=QKeySequence.Find, statusTip="Find text", triggered=self.activateFind) self.settingsAct = QAction(QIcon(':/images/settings.png'), "Open settings", self, shortcut=QKeySequence("Ctrl+1"), statusTip="Open Settings", triggered=self.activateSettings) self.showProjectStructAct = QAction( QIcon(':/images/project_structure.png'), "Show structure", self, shortcut=QKeySequence("Alt+1"), statusTip="Show project structure", triggered=self.showProjectStructure) self.showOutputAct = QAction(QIcon(':/images/project_output.png'), "Show output", self, shortcut=QKeySequence("Alt+2"), statusTip="Show output", triggered=self.showOutput) self.showBookmarks = QAction(QIcon(':/images/project_bookmarks.png'), "Show bookmarks", self, shortcut=QKeySequence("Alt+3"), statusTip="Show bookmarks", triggered=self.showBookmarks) self.showAsDiagram = QAction(QIcon(':/images/diagram.png'), "Show as diagram", self, shortcut=QKeySequence("Alt+4"), statusTip="Show document as diagram", triggered=self.showAsDiagram) self.closeAct = QAction("Cl&ose", self, statusTip="Close the active window", triggered=self.mdiArea.closeActiveSubWindow) self.closeAllAct = QAction("Close &All", self, statusTip="Close all the windows", triggered=self.mdiArea.closeAllSubWindows) self.tileAct = QAction("&Tile", self, statusTip="Tile the windows", triggered=self.mdiArea.tileSubWindows) self.cascadeAct = QAction("&Cascade", self, statusTip="Cascade the windows", triggered=self.mdiArea.cascadeSubWindows) self.nextAct = QAction("Ne&xt", self, shortcut=QKeySequence.NextChild, statusTip="Move the focus to the next window", triggered=self.mdiArea.activateNextSubWindow) self.previousAct = QAction( "Pre&vious", self, shortcut=QKeySequence.PreviousChild, statusTip="Move the focus to the previous window", triggered=self.mdiArea.activatePreviousSubWindow) self.separatorAct = QAction(self) self.separatorAct.setSeparator(True) self.aboutAct = QAction("&About", self, statusTip="Show the application's About box", triggered=self.about) self.aboutQtAct = QAction("About &Qt", self, statusTip="Show the Qt library's About box", triggered=QApplication.instance().aboutQt) def createMenus(self): self.fileMenu = self.menuBar().addMenu("&File") self.fileMenu.addAction(self.newAct) self.fileMenu.addAction(self.openFileAct) self.fileMenu.addAction(self.openProjectAct) self.fileMenu.addAction(self.openTemplate) self.fileMenu.addAction(self.saveAct) self.fileMenu.addAction(self.saveAsAct) self.fileMenu.addSeparator() action = self.fileMenu.addAction("Switch layout direction") action.triggered.connect(self.switchLayoutDirection) self.fileMenu.addAction(self.exitAct) self.editMenu = self.menuBar().addMenu("&Edit") self.editMenu.addAction(self.cutAct) self.editMenu.addAction(self.copyAct) self.editMenu.addAction(self.pasteAct) self.editMenu.addAction(self.findAct) self.settingsMenu = self.menuBar().addMenu("Set&tings") self.settingsMenu.addAction(self.settingsAct) self.viewMenu = self.menuBar().addMenu("&View") self.createViewMenu() self.windowMenu = self.menuBar().addMenu("&Window") self.updateWindowMenu() self.windowMenu.aboutToShow.connect(self.updateWindowMenu) self.menuBar().addSeparator() self.helpMenu = self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.aboutAct) self.helpMenu.addAction(self.aboutQtAct) def createToolBars(self): self.fileToolBar = self.addToolBar("File") self.fileToolBar.addAction(self.newAct) self.fileToolBar.addAction(self.openFileAct) self.fileToolBar.addAction(self.openProjectAct) self.fileToolBar.addAction(self.openTemplate) self.fileToolBar.addAction(self.saveAct) self.editToolBar = self.addToolBar("Edit") self.editToolBar.addAction(self.cutAct) self.editToolBar.addAction(self.copyAct) self.editToolBar.addAction(self.pasteAct) def createStatusBar(self): self.statusBar().showMessage("Ready") def createDockWidgets(self): self.projectStructureWidget = RDFNavigatorProjectStructure(self) self.projectStructureDockWidget = QDockWidget("Project structure", self) self.projectStructureDockWidget.setWidget(self.projectStructureWidget) self.addDockWidget(Qt.LeftDockWidgetArea, self.projectStructureDockWidget) self.projectOutputWidget = RDFNavigatorOutput(self) self.projectOutputDockWidget = QDockWidget("Project output", self) self.projectOutputDockWidget.setWidget(self.projectOutputWidget) self.addDockWidget(Qt.BottomDockWidgetArea, self.projectOutputDockWidget) self.output_message.connect(self.projectOutputWidget.write) self.bookmarskWidget = RDFNavigatorBookmarks(self) self.bookmarksDockWidget = QDockWidget("Bookmarks", self) self.bookmarksDockWidget.setWidget(self.bookmarskWidget) self.addDockWidget(Qt.BottomDockWidgetArea, self.bookmarksDockWidget) self.bookmarskWidget.bookmark_ref_requested.connect(self.showBookmark) def readSettings(self): pos = self.settingsManager.getConfig('pos', QPoint(200, 200)) size = self.settingsManager.getConfig('size', QSize(400, 400)) self.lastDir = self.settingsManager.getConfig('lastDir', '') self.move(pos) self.resize(size) def writeSettings(self): self.settingsManager.setConfig('pos', self.pos()) self.settingsManager.setConfig('size', self.size()) self.settingsManager.setConfig('lastDir', self.lastDir) def activeMdiChild(self): activeSubWindow = self.mdiArea.activeSubWindow() if activeSubWindow: return activeSubWindow.widget() return None def findMdiChild(self, fileName): canonicalFilePath = QFileInfo(fileName).canonicalFilePath() for window in self.mdiArea.subWindowList(): if window.widget().currentFile() == canonicalFilePath: return window return None def switchLayoutDirection(self): if self.layoutDirection() == Qt.LeftToRight: QApplication.setLayoutDirection(Qt.RightToLeft) else: QApplication.setLayoutDirection(Qt.LeftToRight) def setActiveSubWindow(self, window): if window: self.mdiArea.setActiveSubWindow(window) def activateSettings(self): settingsDlg = RDFNavigatorSettings(self) settingsDlg.setPluginsPath(self.settingsManager) settingsDlg.setRDFToolsPath(self.settingsManager) settingsDlg.setSchemaPath(self.settingsManager) settingsDlg.setSysDataPath(self.settingsManager) settingsDlg.exec_() settingsDict = settingsDlg.getConfig() map(lambda (x, y): self.settingsManager.setConfig(x, y), settingsDict.items()) def analyzeSystemData(self): self.resourceRefManager.setSysDataPath( self.settingsManager.getConfig('sys_data', '')) self.global_refs_data, self.global_vals_data = self.resourceRefManager.analyzeRefs( ) if self.global_refs_data != {} and self.global_vals_data != {}: self.global_file_refs_data = dict( reduce(lambda x, y: x + y, [[(v, keys) for v in vals] for keys, vals in self.global_refs_data.iteritems() if vals != {}])) def analyzeTemplateData(self, template_path): sysDataPath = self.resourceRefManager.getSysDataPath() self.resourceRefManager.setSysDataPath(template_path) self.template_refs_data, self.template_vals_data = self.resourceRefManager.analyzeRefs( ) if self.template_refs_data != {} and self.template_vals_data != {}: self.template_file_refs_data = dict( reduce(lambda x, y: x + y, [[(v, keys) for v in vals] for keys, vals in self.template_refs_data.iteritems() if vals != {}])) self.resourceRefManager.setSysDataPath(sysDataPath) def showReference(self, obj_name, key_id): child_name = self.template_file_refs_data.get(obj_name) if child_name is None: child_name = self.global_file_refs_data[obj_name] child = self.findMdiChild(child_name) if child is None: self.openFileHelper(child_name, RDFNavigatorChildrenTypes.TEMPLATE) child = self.findMdiChild(child_name) self.mdiArea.setActiveSubWindow(child) line = None try: line = self.template_refs_data[child_name][obj_name][key_id] except KeyError: line = self.global_refs_data[child_name][obj_name][key_id] child.widget().goToLine(line) def showReferenceValue(self, obj_name, key_id): child_name = self.template_file_refs_data.get(obj_name) if child_name is None: child_name = self.global_file_refs_data[obj_name] value = None try: value = self.template_vals_data[child_name][obj_name][key_id] except KeyError: value = self.global_refs_data[child_name][obj_name][key_id] child = self.activeMdiChild() if child is not None: child.displayRefValue(value) def showBookmark(self, filename, line): child = self.findMdiChild(filename) if child is None: self.openFileHelper(filename, RDFNavigatorChildrenTypes.TEMPLATE) child = self.findMdiChild(filename) self.mdiArea.setActiveSubWindow(child) child.widget().goToLine(line) def createViewMenu(self): self.viewMenu.addAction(self.showProjectStructAct) self.viewMenu.addAction(self.showOutputAct) self.viewMenu.addAction(self.showBookmarks) self.viewMenu.addAction(self.showAsDiagram) def showProjectStructure(self): self.projectStructureDockWidget.show() def showOutput(self): self.projectOutputDockWidget.show() def showBookmarks(self): self.bookmarksDockWidget.show() def showAsDiagram(self): from rdfdiagram.rdfdiagramwidget import RdfDiagramWidget rdfdiagram = RdfDiagramWidget(self) self.mdiArea.addSubWindow(rdfdiagram) rdfdiagram.show()
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.mdiArea = QMdiArea() self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setCentralWidget(self.mdiArea) self.mdiArea.subWindowActivated.connect(self.updateMenus) self.windowMapper = QSignalMapper(self) self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow) self.createActions() self.createMenus() self.createStatusBar() self.updateMenus() self.setWindowTitle("MDI") def closeEvent(self, event): self.mdiArea.closeAllSubWindows() if self.mdiArea.currentSubWindow(): event.ignore() else: event.accept() def newFile(self): child = BrowserChaturbate(self.mdiArea) self.mdiArea.addSubWindow(child) child.load("https://www.chaturbate.com/") child.resize(320, 240) child.show() def newCam4(self): child = BrowserCam4(self.mdiArea) self.mdiArea.addSubWindow(child) child.load("https://www.cam4.com") child.resize(320, 240) child.show() def newFreecam(self): child = BrowserMyFreeCams(self.mdiArea) self.mdiArea.addSubWindow(child) #child.load("https://www.myfreecams.com/php/online_models_splash.php?") child.load('https://www.pornhub.com/categories?o=al') child.resize(320, 240) child.show() def updateMenus(self): hasMdiChild = (self.activeMdiChild() is not None) self.closeAct.setEnabled(hasMdiChild) self.closeAllAct.setEnabled(hasMdiChild) self.tileAct.setEnabled(hasMdiChild) self.cascadeAct.setEnabled(hasMdiChild) self.nextAct.setEnabled(hasMdiChild) self.previousAct.setEnabled(hasMdiChild) self.separatorAct.setVisible(hasMdiChild) def updateWindowMenu(self): self.windowMenu.clear() self.windowMenu.addAction(self.closeAct) self.windowMenu.addAction(self.closeAllAct) self.windowMenu.addSeparator() self.windowMenu.addAction(self.tileAct) self.windowMenu.addAction(self.cascadeAct) self.windowMenu.addSeparator() self.windowMenu.addAction(self.nextAct) self.windowMenu.addAction(self.previousAct) self.windowMenu.addAction(self.separatorAct) windows = self.mdiArea.subWindowList() self.separatorAct.setVisible(len(windows) != 0) def createActions(self): self.newAct = QAction("&Chartubate", self, shortcut=QKeySequence.New, statusTip="Browse Chartubate", triggered=self.newFile) self.newActCam4 = QAction("&Cam4", self, shortcut=QKeySequence.New, statusTip="Browse Cam4", triggered=self.newCam4) self.newActFreeCam = QAction("&PornHub", self, shortcut=QKeySequence.New, statusTip="Browse PornHub", triggered=self.newFreecam) self.closeAct = QAction("Cl&ose", self, statusTip="Close the active window", triggered=self.mdiArea.closeActiveSubWindow) self.closeAllAct = QAction("Close &All", self, statusTip="Close all the windows", triggered=self.mdiArea.closeAllSubWindows) self.tileAct = QAction("&Tile", self, statusTip="Tile the windows", triggered=self.mdiArea.tileSubWindows) self.cascadeAct = QAction("&Cascade", self, statusTip="Cascade the windows", triggered=self.mdiArea.cascadeSubWindows) self.nextAct = QAction("Ne&xt", self, shortcut=QKeySequence.NextChild, statusTip="Move the focus to the next window", triggered=self.mdiArea.activateNextSubWindow) self.previousAct = QAction( "Pre&vious", self, shortcut=QKeySequence.PreviousChild, statusTip="Move the focus to the previous window", triggered=self.mdiArea.activatePreviousSubWindow) self.separatorAct = QAction(self) self.separatorAct.setSeparator(True) def createMenus(self): self.fileMenu = self.menuBar().addMenu("&File") self.fileMenu.addAction(self.newAct) self.fileMenu.addAction(self.newActCam4) self.fileMenu.addAction(self.newActFreeCam) self.exitAct = QAction( "E&xit", self, shortcut=QKeySequence.Quit, statusTip="Exit the application", triggered=QApplication.instance().closeAllWindows) self.fileMenu.addSeparator() action = self.fileMenu.addAction("Switch layout direction") action.triggered.connect(self.switchLayoutDirection) self.fileMenu.addAction(self.exitAct) self.windowMenu = self.menuBar().addMenu("&Window") self.updateWindowMenu() self.windowMenu.aboutToShow.connect(self.updateWindowMenu) self.menuBar().addSeparator() def createStatusBar(self): self.statusBar().showMessage("Ready") def activeMdiChild(self): activeSubWindow = self.mdiArea.activeSubWindow() if activeSubWindow: return activeSubWindow.widget() return None def findMdiChild(self, fileName): canonicalFilePath = QFileInfo(fileName).canonicalFilePath() for window in self.mdiArea.subWindowList(): if window.widget().currentFile() == canonicalFilePath: return window return None def switchLayoutDirection(self): if self.layoutDirection() == Qt.LeftToRight: QApplication.setLayoutDirection(Qt.RightToLeft) else: QApplication.setLayoutDirection(Qt.LeftToRight) def setActiveSubWindow(self, window): if window: self.mdiArea.setActiveSubWindow(window)
class Example(QMainWindow): def __init__(self): ''' 一些初始设置 ''' super().__init__() self.InitUI() def InitUI(self): ''' 界面初始设置 ''' self.setWindowTitle('关注微信公众号:学点编程吧--扑克牌模拟') self.mid = QMdiArea() self.setCentralWidget(self.mid) # 新建一个QMdiArea类的对象,并将其设置为主窗口的中央小部件 sendOnecardAct = QAction(QIcon('./res/sendOnecard.ico'), '发1张牌', self) sendOnecardAct.triggered.connect(self.sendOnecard) # 发1张牌命令 sendFivecardsAct = QAction(QIcon('./res/sendFivecard.ico'), '随机5张牌', self) sendFivecardsAct.triggered.connect(self.sendFivecards) # 随机5张牌命令 clearcardAct = QAction(QIcon('./res/clear.ico'), '清除牌', self) clearcardAct.triggered.connect(self.clearCards) # 清除牌命令 foldcardAct = QAction(QIcon('./res/fold.ico'), '收牌', self) foldcardAct.triggered.connect(self.foldCards) # 收牌 toolbar = self.addToolBar('工具栏') toolbar.addAction(sendOnecardAct) toolbar.addAction(sendFivecardsAct) toolbar.addAction(clearcardAct) toolbar.addAction(foldcardAct) #把上面的几个命令放到工具栏上 toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) #文字在图标下面 def sendOnecard(self): ''' 随机一张牌,发出去。 ''' randomflag = self.randomsend(1) subcard = QMdiSubWindow() subcard.setWidget(Card(randomflag)) self.mid.addSubWindow(subcard) subcard.setWindowFlags(Qt.WindowMinimizeButtonHint) # 设置窗口属性,让其只显示最小化按钮。 subcard.resize(150, 200) subcard.show() def sendFivecards(self): ''' 随机5张牌 ''' randomflag = self.randomsend(5) for card in randomflag: # 遍历5张牌,发出去。 subcard = QMdiSubWindow() subcard.setWidget(Card(card)) self.mid.addSubWindow(subcard) subcard.setWindowFlags(Qt.WindowMinimizeButtonHint) # 设置窗口属性,让其只显示最小化按钮。 subcard.resize(150, 200) subcard.show() def clearCards(self): ''' 清除牌 ''' self.mid.closeAllSubWindows() # 所有窗口关闭 def foldCards(self): ''' 收牌 ''' self.mid.cascadeSubWindows() # 所有窗口级联模式排列 def randomsend(self, num): ''' 发送方式: 1、要是发1张牌,从cardlist中随机取一个元素返回就行了。 2、要是随机发5张牌,从cardlist中随机取出一段包含有5个元素的列表。 ''' cardlist = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "a", "j", "joker", "k", "q"] if num == 1: return random.choice(cardlist) elif num == 5: return random.sample(cardlist, 5)
class EditorMainWindow(object): def __init__(self): self.seq = 0 self.widget = loadUi(MAIN_UI_PATH) self.init_mdi() self.init_actions() self.init_instance() self.widget.closeEvent = self.close_handler self.widget.showMaximized() def get_seq(self): self.seq += 1 return self.seq def init_mdi(self): self.mdi = QMdiArea(self.widget) self.mdi.setViewMode(QMdiArea.TabbedView) self.mdi.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.mdi.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.mdi.setTabsMovable(True) self.mdi.setTabsClosable(True) self.mdi.setTabShape(QTabWidget.Rounded) self.widget.setCentralWidget(self.mdi) def init_actions(self): self.widget.actionNew.triggered.connect(self.action_new_handler) self.widget.actionOpen.triggered.connect(self.action_open_handler) self.widget.actionSave.triggered.connect(self.action_save_handler) self.widget.actionSave_As.triggered.connect( self.action_save_as_handler) self.widget.actionClose.triggered.connect(self.action_close_handler) self.widget.actionClose_All.triggered.connect( self.action_close_all_handler) self.widget.actionExport.triggered.connect(self.action_export_handler) self.widget.actionStates.triggered.connect(self.action_states_handler) self.widget.actionEvents.triggered.connect(self.action_events_handler) def close_handler(self, ev): l = self.mdi.subWindowList() if len(l) != 0: self.mdi.closeAllSubWindows() ev.ignore() def init_instance(self): self.instances = [] def remove_instance(self, ins): self.instances.remove(ins) def find_non_existing_name(self): while True: tmp_path = os.path.join( config.src_path, "NewFsm" + str(self.get_seq()) + FSM_FILE_EXT) if not os.path.exists(tmp_path): return tmp_path def action_new_handler(self): tmp_path = self.find_non_existing_name() m = FsmModel() m.default_init() vm = InstanceVM(m, self, tmp_path) vm.set_modified(True) def file_already_open(self, pth): for i in self.instances: pth = os.path.abspath(pth) if pth == i.file_path: return i return None def action_open_handler(self): p = QFileDialog() p.setViewMode(QFileDialog.List) p.setFileMode(QFileDialog.ExistingFiles) p.setDirectory(config.src_path) p.exec() paths = p.selectedFiles() for pth in paths: i = self.file_already_open(pth) if i: self.mdi.setActiveSubWindow(i.sub_window) else: m = FsmModel.load_file(pth) vm = InstanceVM(m, self, pth) def action_save_handler(self): w = self.mdi.activeSubWindow() if w is None: return model = w.instance.model model.dump_file(w.instance.file_path) w.instance.set_modified(False) def action_save_as_handler(self): w = self.mdi.activeSubWindow() if w is None: return p = QFileDialog() p.setViewMode(QFileDialog.List) p.setDirectory(config.src_path) p.exec() paths = p.selectedFiles() if len(paths) == 0: return w.instance.file_path = os.path.abspath(paths[0]) w.instance.update_title() model = w.instance.model model.dump_file(w.instance.file_path) w.instance.set_modified(False) def action_close_handler(self): w = self.mdi.activeSubWindow() if w is None: return w.close() def action_close_all_handler(self): self.mdi.closeAllSubWindows() def action_export_handler(self): fsm_files = os.listdir(config.src_path) for fn in fsm_files: full_name = os.path.join(config.src_path, fn) b, e = os.path.splitext(full_name) if e == FSM_FILE_EXT: f = open(full_name, "rb") basename, e = os.path.splitext(fn) model_object = pickle.load(f) f.close() exporter = FsmModelPythonExporter(model_object) exporter.export( os.path.join(config.export_path, basename + "_fsm.py")) def action_states_handler(self): cur = self.get_current_instance() if cur is None: return model = cur.model w = loadUi(STATE_LIST_DIALOG_PATH) list_vm = MultiColumnListModel(model.state, LIST_DIALOG_COLUMNS, STATE_DIALOG_HEADERS) add_item = functools.partial(model.add_item, StateItem, "state") remove_item = functools.partial(model.remove_item, "state") dialog = StateListPanelVM(list_vm, model.state, add_item, remove_item, w) dialog.run() cur.table_vm.refresh() def action_events_handler(self): cur = self.get_current_instance() if cur is None: return model = cur.model w = loadUi(EVENT_DIALOG_PATH) list_vm = MultiColumnListModel(model.event, LIST_DIALOG_COLUMNS, EVENT_DIALOG_HEADERS) add_item = functools.partial(model.add_item, EventItem, "event") remove_item = functools.partial(model.remove_item, "event") dialog = ListEditPanelVM(list_vm, model.event, add_item, remove_item, w) dialog.run() cur.table_vm.refresh() def get_current_instance(self): current = self.mdi.activeSubWindow() if not current: return None for i in self.instances: if i.sub_window == current: return i assert ( False ) # there is an active sub window but there's no matching instance
class EditorMainWindow(object): def __init__(self): self.seq = 0 self.widget = loadUi(MAIN_UI_PATH) self.init_mdi() self.init_actions() self.init_instance() self.widget.closeEvent = self.close_handler self.widget.showMaximized() def get_seq(self): self.seq += 1 return self.seq def init_mdi(self): self.mdi = QMdiArea(self.widget) self.mdi.setViewMode(QMdiArea.TabbedView) self.mdi.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.mdi.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.mdi.setTabsMovable(True) self.mdi.setTabsClosable(True) self.mdi.setTabShape(QTabWidget.Rounded) self.widget.setCentralWidget(self.mdi) def init_actions(self): self.widget.actionNew.triggered.connect(self.action_new_handler) self.widget.actionOpen.triggered.connect(self.action_open_handler) self.widget.actionSave.triggered.connect(self.action_save_handler) self.widget.actionSave_As.triggered.connect(self.action_save_as_handler) self.widget.actionClose.triggered.connect(self.action_close_handler) self.widget.actionClose_All.triggered.connect(self.action_close_all_handler) self.widget.actionExport.triggered.connect(self.action_export_handler) self.widget.actionStates.triggered.connect(self.action_states_handler) self.widget.actionEvents.triggered.connect(self.action_events_handler) def close_handler(self, ev): l = self.mdi.subWindowList() if len(l) != 0: self.mdi.closeAllSubWindows() ev.ignore() def init_instance(self): self.instances = [] def remove_instance(self, ins): self.instances.remove(ins) def find_non_existing_name(self): while True: tmp_path = os.path.join( config.src_path, "NewFsm" + str(self.get_seq()) + FSM_FILE_EXT) if not os.path.exists(tmp_path): return tmp_path def action_new_handler(self): tmp_path = self.find_non_existing_name() m = FsmModel() m.default_init() vm = InstanceVM(m, self, tmp_path) vm.set_modified(True) def file_already_open(self, pth): for i in self.instances: pth = os.path.abspath(pth) if pth == i.file_path: return i return None def action_open_handler(self): p = QFileDialog() p.setViewMode(QFileDialog.List) p.setFileMode(QFileDialog.ExistingFiles) p.setDirectory(config.src_path) p.exec() paths = p.selectedFiles() for pth in paths: i = self.file_already_open(pth) if i: self.mdi.setActiveSubWindow(i.sub_window) else: m = FsmModel.load_file(pth) vm = InstanceVM(m, self, pth) def action_save_handler(self): w = self.mdi.activeSubWindow() if w is None: return model = w.instance.model model.dump_file(w.instance.file_path) w.instance.set_modified(False) def action_save_as_handler(self): w = self.mdi.activeSubWindow() if w is None: return p = QFileDialog() p.setViewMode(QFileDialog.List) p.setDirectory(config.src_path) p.exec() paths = p.selectedFiles() if len(paths) == 0: return w.instance.file_path = os.path.abspath(paths[0]) w.instance.update_title() model = w.instance.model model.dump_file(w.instance.file_path) w.instance.set_modified(False) def action_close_handler(self): w = self.mdi.activeSubWindow() if w is None: return w.close() def action_close_all_handler(self): self.mdi.closeAllSubWindows() def action_export_handler(self): fsm_files = os.listdir(config.src_path) for fn in fsm_files: full_name = os.path.join(config.src_path, fn) b, e = os.path.splitext(full_name) if e == FSM_FILE_EXT: f = open(full_name, "rb") basename, e = os.path.splitext(fn) model_object = pickle.load(f) f.close() exporter = FsmModelPythonExporter(model_object) exporter.export(os.path.join(config.export_path, basename + "_fsm.py")) def action_states_handler(self): cur = self.get_current_instance() if cur is None: return model = cur.model w = loadUi(STATE_LIST_DIALOG_PATH) list_vm = MultiColumnListModel( model.state, LIST_DIALOG_COLUMNS, STATE_DIALOG_HEADERS) add_item = functools.partial(model.add_item, StateItem, "state") remove_item = functools.partial(model.remove_item, "state") dialog = StateListPanelVM( list_vm, model.state, add_item, remove_item, w) dialog.run() cur.table_vm.refresh() def action_events_handler(self): cur = self.get_current_instance() if cur is None: return model = cur.model w = loadUi(EVENT_DIALOG_PATH) list_vm = MultiColumnListModel( model.event, LIST_DIALOG_COLUMNS, EVENT_DIALOG_HEADERS) add_item = functools.partial(model.add_item, EventItem, "event") remove_item = functools.partial(model.remove_item, "event") dialog = ListEditPanelVM( list_vm, model.event, add_item, remove_item, w) dialog.run() cur.table_vm.refresh() def get_current_instance(self): current = self.mdi.activeSubWindow() if not current: return None for i in self.instances: if i.sub_window == current: return i assert(False) # there is an active sub window but there's no matching instance
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.mdiArea = QMdiArea() self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setCentralWidget(self.mdiArea) self.mdiArea.subWindowActivated.connect(self.updateMenus) self.windowMapper = QSignalMapper(self) self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow) self.createActions() self.createMenus() self.createStatusBar() self.updateMenus() self.clipboard = QApplication.clipboard() self.setWindowTitle("Qt5 Multi Video Player v0.02 - by Luis Santos AKA DJOKER") def closeEvent(self, event): self.mdiArea.closeAllSubWindows() if self.mdiArea.currentSubWindow(): event.ignore() else: event.accept() def newFile(self): child = VideoPlayer(True) self.mdiArea.addSubWindow(child) url = self.clipboard.text() child.Player(url) child.show() def newMute(self): child = VideoPlayer(False) self.mdiArea.addSubWindow(child) url = self.clipboard.text() child.Player(url) child.show() return def updateMenus(self): hasMdiChild = (self.activeMdiChild() is not None) self.closeAct.setEnabled(hasMdiChild) self.closeAllAct.setEnabled(hasMdiChild) self.tileAct.setEnabled(hasMdiChild) self.cascadeAct.setEnabled(hasMdiChild) self.nextAct.setEnabled(hasMdiChild) self.previousAct.setEnabled(hasMdiChild) self.separatorAct.setVisible(hasMdiChild) def updateWindowMenu(self): self.windowMenu.clear() self.windowMenu.addAction(self.closeAct) self.windowMenu.addAction(self.closeAllAct) self.windowMenu.addSeparator() self.windowMenu.addAction(self.tileAct) self.windowMenu.addAction(self.cascadeAct) self.windowMenu.addSeparator() self.windowMenu.addAction(self.nextAct) self.windowMenu.addAction(self.previousAct) self.windowMenu.addAction(self.separatorAct) windows = self.mdiArea.subWindowList() self.separatorAct.setVisible(len(windows) != 0) def createMdiChild(self): child = MdiChild() self.mdiArea.addSubWindow(child) return child def createActions(self): self.newAct = QAction( "&New", self, shortcut=QKeySequence.New, statusTip="Create a new Video Player", triggered=self.newFile) self.newActCam4 = QAction("&VideoMute", self, shortcut=QKeySequence.New, statusTip="Create a new Video Player Mute", triggered=self.newMute) self.closeAct = QAction("Cl&ose", self, statusTip="Close the active window", triggered=self.mdiArea.closeActiveSubWindow) self.closeAllAct = QAction("Close &All", self, statusTip="Close all the windows", triggered=self.mdiArea.closeAllSubWindows) self.tileAct = QAction("&Tile", self, statusTip="Tile the windows", triggered=self.mdiArea.tileSubWindows) self.cascadeAct = QAction("&Cascade", self, statusTip="Cascade the windows", triggered=self.mdiArea.cascadeSubWindows) self.nextAct = QAction("Ne&xt", self, shortcut=QKeySequence.NextChild, statusTip="Move the focus to the next window", triggered=self.mdiArea.activateNextSubWindow) self.previousAct = QAction("Pre&vious", self, shortcut=QKeySequence.PreviousChild, statusTip="Move the focus to the previous window", triggered=self.mdiArea.activatePreviousSubWindow) self.separatorAct = QAction(self) self.separatorAct.setSeparator(True) def createMenus(self): self.fileMenu = self.menuBar().addMenu("&File") self.fileMenu.addAction(self.newAct) self.fileMenu.addAction(self.newActCam4) self.exitAct = QAction("E&xit", self, shortcut=QKeySequence.Quit, statusTip="Exit the application", triggered=QApplication.instance().closeAllWindows) self.fileMenu.addSeparator() action = self.fileMenu.addAction("Switch layout direction") action.triggered.connect(self.switchLayoutDirection) self.fileMenu.addAction(self.exitAct) self.windowMenu = self.menuBar().addMenu("&Window") self.updateWindowMenu() self.windowMenu.aboutToShow.connect(self.updateWindowMenu) self.menuBar().addSeparator() def createStatusBar(self): self.statusBar().showMessage("Ready") def activeMdiChild(self): activeSubWindow = self.mdiArea.activeSubWindow() if activeSubWindow: return activeSubWindow.widget() return None def findMdiChild(self, fileName): canonicalFilePath = QFileInfo(fileName).canonicalFilePath() for window in self.mdiArea.subWindowList(): if window.widget().currentFile() == canonicalFilePath: return window return None def switchLayoutDirection(self): if self.layoutDirection() == Qt.LeftToRight: QApplication.setLayoutDirection(Qt.RightToLeft) else: QApplication.setLayoutDirection(Qt.LeftToRight) def setActiveSubWindow(self, window): if window: self.mdiArea.setActiveSubWindow(window)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.mdiArea = QMdiArea() self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setCentralWidget(self.mdiArea) self.mdiArea.subWindowActivated.connect(self.updateMenus) self.windowMapper = QSignalMapper(self) self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow) self.createActions() self.createMenus() self.createToolBars() self.createStatusBar() self.updateMenus() self.readSettings() self.setWindowTitle("MDI") def closeEvent(self, event): self.mdiArea.closeAllSubWindows() if self.mdiArea.currentSubWindow(): event.ignore() else: self.writeSettings() event.accept() def newFile(self): child = self.createMdiChild() child.newFile() child.show() def open(self): fileName, _ = QFileDialog.getOpenFileName(self) if fileName: existing = self.findMdiChild(fileName) if existing: self.mdiArea.setActiveSubWindow(existing) return child = self.createMdiChild() if child.loadFile(fileName): self.statusBar().showMessage("File loaded", 2000) child.show() else: child.close() def save(self): if self.activeMdiChild() and self.activeMdiChild().save(): self.statusBar().showMessage("File saved", 2000) def saveAs(self): if self.activeMdiChild() and self.activeMdiChild().saveAs(): self.statusBar().showMessage("File saved", 2000) def cut(self): if self.activeMdiChild(): self.activeMdiChild().cut() def copy(self): if self.activeMdiChild(): self.activeMdiChild().copy() def paste(self): if self.activeMdiChild(): self.activeMdiChild().paste() def about(self): QMessageBox.about(self, "About MDI", "The <b>MDI</b> example demonstrates how to write multiple " "document interface applications using Qt.") def updateMenus(self): hasMdiChild = (self.activeMdiChild() is not None) self.saveAct.setEnabled(hasMdiChild) self.saveAsAct.setEnabled(hasMdiChild) self.pasteAct.setEnabled(hasMdiChild) self.closeAct.setEnabled(hasMdiChild) self.closeAllAct.setEnabled(hasMdiChild) self.tileAct.setEnabled(hasMdiChild) self.cascadeAct.setEnabled(hasMdiChild) self.nextAct.setEnabled(hasMdiChild) self.previousAct.setEnabled(hasMdiChild) self.separatorAct.setVisible(hasMdiChild) hasSelection = (self.activeMdiChild() is not None and self.activeMdiChild().textCursor().hasSelection()) self.cutAct.setEnabled(hasSelection) self.copyAct.setEnabled(hasSelection) def updateWindowMenu(self): self.windowMenu.clear() self.windowMenu.addAction(self.closeAct) self.windowMenu.addAction(self.closeAllAct) self.windowMenu.addSeparator() self.windowMenu.addAction(self.tileAct) self.windowMenu.addAction(self.cascadeAct) self.windowMenu.addSeparator() self.windowMenu.addAction(self.nextAct) self.windowMenu.addAction(self.previousAct) self.windowMenu.addAction(self.separatorAct) windows = self.mdiArea.subWindowList() self.separatorAct.setVisible(len(windows) != 0) for i, window in enumerate(windows): child = window.widget() text = "%d %s" % (i + 1, child.userFriendlyCurrentFile()) if i < 9: text = '&' + text action = self.windowMenu.addAction(text) action.setCheckable(True) action.setChecked(child is self.activeMdiChild()) action.triggered.connect(self.windowMapper.map) self.windowMapper.setMapping(action, window) def createMdiChild(self): child = MdiChild() self.mdiArea.addSubWindow(child) child.copyAvailable.connect(self.cutAct.setEnabled) child.copyAvailable.connect(self.copyAct.setEnabled) return child def createActions(self): self.newAct = QAction(QIcon(':/images/new.png'), "&New", self, shortcut=QKeySequence.New, statusTip="Create a new file", triggered=self.newFile) self.openAct = QAction(QIcon(':/images/open.png'), "&Open...", self, shortcut=QKeySequence.Open, statusTip="Open an existing file", triggered=self.open) self.saveAct = QAction(QIcon(':/images/save.png'), "&Save", self, shortcut=QKeySequence.Save, statusTip="Save the document to disk", triggered=self.save) self.saveAsAct = QAction("Save &As...", self, shortcut=QKeySequence.SaveAs, statusTip="Save the document under a new name", triggered=self.saveAs) self.exitAct = QAction("E&xit", self, shortcut=QKeySequence.Quit, statusTip="Exit the application", triggered=QApplication.instance().closeAllWindows) self.cutAct = QAction(QIcon(':/images/cut.png'), "Cu&t", self, shortcut=QKeySequence.Cut, statusTip="Cut the current selection's contents to the clipboard", triggered=self.cut) self.copyAct = QAction(QIcon(':/images/copy.png'), "&Copy", self, shortcut=QKeySequence.Copy, statusTip="Copy the current selection's contents to the clipboard", triggered=self.copy) self.pasteAct = QAction(QIcon(':/images/paste.png'), "&Paste", self, shortcut=QKeySequence.Paste, statusTip="Paste the clipboard's contents into the current selection", triggered=self.paste) self.closeAct = QAction("Cl&ose", self, statusTip="Close the active window", triggered=self.mdiArea.closeActiveSubWindow) self.closeAllAct = QAction("Close &All", self, statusTip="Close all the windows", triggered=self.mdiArea.closeAllSubWindows) self.tileAct = QAction("&Tile", self, statusTip="Tile the windows", triggered=self.mdiArea.tileSubWindows) self.cascadeAct = QAction("&Cascade", self, statusTip="Cascade the windows", triggered=self.mdiArea.cascadeSubWindows) self.nextAct = QAction("Ne&xt", self, shortcut=QKeySequence.NextChild, statusTip="Move the focus to the next window", triggered=self.mdiArea.activateNextSubWindow) self.previousAct = QAction("Pre&vious", self, shortcut=QKeySequence.PreviousChild, statusTip="Move the focus to the previous window", triggered=self.mdiArea.activatePreviousSubWindow) self.separatorAct = QAction(self) self.separatorAct.setSeparator(True) self.aboutAct = QAction("&About", self, statusTip="Show the application's About box", triggered=self.about) self.aboutQtAct = QAction("About &Qt", self, statusTip="Show the Qt library's About box", triggered=QApplication.instance().aboutQt) def createMenus(self): self.fileMenu = self.menuBar().addMenu("&File") self.fileMenu.addAction(self.newAct) self.fileMenu.addAction(self.openAct) self.fileMenu.addAction(self.saveAct) self.fileMenu.addAction(self.saveAsAct) self.fileMenu.addSeparator() action = self.fileMenu.addAction("Switch layout direction") action.triggered.connect(self.switchLayoutDirection) self.fileMenu.addAction(self.exitAct) self.editMenu = self.menuBar().addMenu("&Edit") self.editMenu.addAction(self.cutAct) self.editMenu.addAction(self.copyAct) self.editMenu.addAction(self.pasteAct) self.windowMenu = self.menuBar().addMenu("&Window") self.updateWindowMenu() self.windowMenu.aboutToShow.connect(self.updateWindowMenu) self.menuBar().addSeparator() self.helpMenu = self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.aboutAct) self.helpMenu.addAction(self.aboutQtAct) def createToolBars(self): self.fileToolBar = self.addToolBar("File") self.fileToolBar.addAction(self.newAct) self.fileToolBar.addAction(self.openAct) self.fileToolBar.addAction(self.saveAct) self.editToolBar = self.addToolBar("Edit") self.editToolBar.addAction(self.cutAct) self.editToolBar.addAction(self.copyAct) self.editToolBar.addAction(self.pasteAct) def createStatusBar(self): self.statusBar().showMessage("Ready") def readSettings(self): settings = QSettings('Trolltech', 'MDI Example') pos = settings.value('pos', QPoint(200, 200)) size = settings.value('size', QSize(400, 400)) self.move(pos) self.resize(size) def writeSettings(self): settings = QSettings('Trolltech', 'MDI Example') settings.setValue('pos', self.pos()) settings.setValue('size', self.size()) def activeMdiChild(self): activeSubWindow = self.mdiArea.activeSubWindow() if activeSubWindow: return activeSubWindow.widget() return None def findMdiChild(self, fileName): canonicalFilePath = QFileInfo(fileName).canonicalFilePath() for window in self.mdiArea.subWindowList(): if window.widget().currentFile() == canonicalFilePath: return window return None def switchLayoutDirection(self): if self.layoutDirection() == Qt.LeftToRight: QApplication.setLayoutDirection(Qt.RightToLeft) else: QApplication.setLayoutDirection(Qt.LeftToRight) def setActiveSubWindow(self, window): if window: self.mdiArea.setActiveSubWindow(window)
class DemoMdi(QMainWindow): def __init__(self, parent=None): super(DemoMdi, self).__init__(parent) # 设置窗口标题 self.setWindowTitle( 'MDI with a dockWidget tree and a tab-view mdiArea') # 设置窗口大小 self.resize(800, 640) self.initUi() self.mytimer = QTimer(self) self.mytimer.start(1000) self.mytimer.timeout.connect(self.timerCallback) def initUi(self): self.initMenuBar() self.initToolBar() self.initDockTree() self.initStatusBar() self.mdiArea = QMdiArea(self) self.setCentralWidget(self.mdiArea) # set as tabbedView by default self.mdiArea.setViewMode(QMdiArea.TabbedView) self.mdiArea.setTabShape(QTabWidget.Triangular) self.mdiArea.setTabsClosable(True) self.mdiArea.setTabsMovable(True) # index of document self.newDocIndex = 1 def initDockTree(self): self.dockWind = QDockWidget(self) self.dockWind.setWindowTitle('QProfile Explorer') self.initTree() self.dockWind.setWidget(self.tree) self.dockWind.setFloating(False) # set floating = false self.addDockWidget(Qt.LeftDockWidgetArea, self.dockWind) # set the position at left side # remove all features of DockWidget like Closable, Moveable, Floatable, VerticalTitle etc. self.dockWind.setFeatures(QDockWidget.NoDockWidgetFeatures) def initTree(self): self.tree = QTreeWidget() self.tree.setColumnCount(1) #设置列数 #self.tree.setHeaderLabels(['QProfiler items']) #设置树形控件头部的标题 self.tree.setIndentation(20) # 项目的缩进 self.tree.setHeaderHidden(True) #设置根节点 Perfmon = myQTreeWidgetItem(sin(pi * perfmon_x)) Perfmon.setText(0, 'Perfmon') perfmon_00 = myQTreeWidgetItem(sin(2 * pi * perfmon_x)) perfmon_00.setText(0, 'perfmon_00') Perfmon.addChild(perfmon_00) perfmon_01 = QTreeWidgetItem() perfmon_01.setText(0, 'perfmon_01') Perfmon.addChild(perfmon_01) perfmon_02 = QTreeWidgetItem() perfmon_02.setText(0, 'perfmon_02') Perfmon.addChild(perfmon_02) perfmon_03 = QTreeWidgetItem() perfmon_03.setText(0, 'perfmon_03') Perfmon.addChild(perfmon_03) self.tree.addTopLevelItem(Perfmon) # CPU cpuLoad = QTreeWidgetItem() cpuLoad.setText(0, 'CPU') cpuLoad_1 = QTreeWidgetItem() cpuLoad_1.setText(0, 'core 1') cpuLoad.addChild(cpuLoad_1) cpuLoad_2 = QTreeWidgetItem() cpuLoad_2.setText(0, 'core 2') cpuLoad.addChild(cpuLoad_2) self.tree.addTopLevelItem(cpuLoad) # treeItem signal self.tree.itemClicked[QTreeWidgetItem, int].connect(self.treeItemClicked) def treeItemWindow_open(self, item): title = item.text(0) subWind = QMdiSubWindow(self) subWind.setAttribute(Qt.WA_DeleteOnClose) subWind.setWindowTitle(title) self.newDocIndex += 1 mainWid = QWidget() l = QtWidgets.QVBoxLayout(mainWid) txtWind = QPlainTextEdit(mainWid) txtWind.setPlainText(f"perfmon.x = {item.x}, \n y = {item.y}") figWind = MyCanvas(mainWid, width=5, height=4, dpi=100, treeWidgetItem=item) l.addWidget(figWind) l.addWidget(txtWind) l.setStretch(0, 3) # 设置第一列的伸展比例为 3 l.setStretch(1, 1) # 设置第二列的伸展比例为 1, 这样2列的伸展比为3:1 subWind.setWidget(mainWid) self.mdiArea.addSubWindow(subWind) subWind.show() def treeItemClicked(self, item, column): tab = self.get_treeItem_tab(item.text(column)) if tab is not None: tab.setFocus() else: if item.text(column) == 'Perfmon': self.treeItemWindow_open(item) else: newDoc = QMdiSubWindow(self) newDoc.setAttribute(Qt.WA_DeleteOnClose) newDoc.setWindowTitle(item.text(column)) self.newDocIndex += 1 newDoc.setWidget(QPlainTextEdit( item.text(column) * 10, newDoc)) self.mdiArea.addSubWindow(newDoc) newDoc.show() def get_treeItem_tab(self, title): for wind in self.mdiArea.subWindowList(): if title == wind.windowTitle(): return wind return None def initStatusBar(self): self.statusBar = self.statusBar() self.statusBar.showMessage('Ready to start ...', 0) def initMenuBar(self): menuBar = self.menuBar() style = QApplication.style() #==== 文件 ====# fileMenu = menuBar.addMenu('文件') #新建一个文档 aFileNew = QAction('新建文档', self) aFileNew.setIcon(style.standardIcon(QStyle.SP_FileIcon)) aFileNew.triggered.connect(self.onFileNew) fileMenu.addAction(aFileNew) #打开一个文档 aFileOpen = QAction('打开文档', self) aFileOpen.setIcon(style.standardIcon(QStyle.SP_DialogOpenButton)) aFileOpen.triggered.connect(self.onFileOpen) fileMenu.addAction(aFileOpen) #关闭一个文档 aFileCloseAll = QAction('关闭全部', self) aFileCloseAll.setIcon(style.standardIcon(QStyle.SP_DialogCloseButton)) aFileOpen.triggered.connect(self.onFileCloseAll) fileMenu.addAction(aFileCloseAll) #添加分割线 fileMenu.addSeparator() #退出 aFileExit = QAction('退出', self) aFileExit.triggered.connect(self.close) fileMenu.addAction(aFileExit) #==== 编辑 ====# editMenu = menuBar.addMenu('编辑') #剪切 aEditCut = QAction('剪切', self) aEditCut.setIcon(QIcon(':/ico/cut.png')) aEditCut.triggered.connect(self.onEditCut) editMenu.addAction(aEditCut) #复制 aEditCopy = QAction('复制', self) aEditCopy.setIcon(QIcon(':/ico/copy.png')) aEditCopy.triggered.connect(self.onEditCopy) editMenu.addAction(aEditCopy) #粘贴 aEditPaste = QAction('粘贴', self) aEditPaste.setIcon(QIcon(':/ico/paste.png')) aEditPaste.triggered.connect(self.onEditPaste) editMenu.addAction(aEditPaste) #==== 窗口排列方式 ====# windowMenu = menuBar.addMenu('窗口') #子窗口模式 aWndSubView = QAction('子窗口模式', self) aWndSubView.triggered.connect(lambda: self.onWinowdMode(0)) windowMenu.addAction(aWndSubView) #标签页模式 aWndTab = QAction('标签页模式', self) aWndTab.triggered.connect(lambda: self.onWinowdMode(1)) windowMenu.addAction(aWndTab) windowMenu.addSeparator() #平铺模式 aWndTile = QAction('平铺模式', self) aWndTile.triggered.connect(lambda: self.onWinowdMode(2)) windowMenu.addAction(aWndTile) #窗口级联模式 aWndCascade = QAction('窗口级联模式', self) aWndCascade.triggered.connect(lambda: self.onWinowdMode(3)) windowMenu.addAction(aWndCascade) def initToolBar(self): toolBar = self.addToolBar('ToolBar') style = QApplication.style() min_width = 64 btnFileNew = QToolButton(self) btnFileNew.setText('新建文档') btnFileNew.setMinimumWidth(min_width) btnFileNew.setIcon(style.standardIcon(QStyle.SP_FileIcon)) btnFileNew.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) btnFileNew.clicked.connect(self.onFileNew) toolBar.addWidget(btnFileNew) btnFileOpen = QToolButton(self) btnFileOpen.setText('打开文档') btnFileOpen.setMinimumWidth(min_width) btnFileOpen.setIcon(style.standardIcon(QStyle.SP_DialogOpenButton)) btnFileOpen.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) btnFileOpen.clicked.connect(self.onFileOpen) toolBar.addWidget(btnFileOpen) btnFileCloseAll = QToolButton(self) btnFileCloseAll.setText('关闭全部') btnFileCloseAll.setMinimumWidth(min_width) btnFileCloseAll.setIcon(style.standardIcon( QStyle.SP_DialogCloseButton)) btnFileCloseAll.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) btnFileCloseAll.clicked.connect(self.onFileCloseAll) toolBar.addWidget(btnFileCloseAll) toolBar.addSeparator() btnEditCut = QToolButton(self) btnEditCut.setText('剪切') btnEditCut.setMinimumWidth(64) btnEditCut.setIcon(QIcon(':/ico/cut.png')) btnEditCut.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) btnEditCut.clicked.connect(self.onEditCut) toolBar.addWidget(btnEditCut) btnEditCopy = QToolButton(self) btnEditCopy.setText('复制') btnEditCopy.setMinimumWidth(64) btnEditCopy.setIcon(QIcon(':/ico/copy.png')) btnEditCopy.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) btnEditCopy.clicked.connect(self.onEditCopy) toolBar.addWidget(btnEditCopy) btnEditPaste = QToolButton(self) btnEditPaste.setText('粘贴') btnEditPaste.setMinimumWidth(64) btnEditPaste.setIcon(QIcon(':/ico/paste.png')) btnEditPaste.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) btnEditPaste.clicked.connect(self.onEditPaste) toolBar.addWidget(btnEditPaste) def msgCritical(self, strInfo): dlg = QMessageBox(self) dlg.setIcon(QMessageBox.Critical) dlg.setText(strInfo) dlg.show() def onFileNew(self): newDoc = QMdiSubWindow(self) newDoc.setAttribute(Qt.WA_DeleteOnClose) newDoc.setWindowTitle('新文档 ' + str(self.newDocIndex)) self.newDocIndex += 1 newDoc.setWidget(QPlainTextEdit(newDoc)) self.mdiArea.addSubWindow(newDoc) newDoc.show() def onFileOpen(self): path, _ = QFileDialog.getOpenFileName(self, '打开文件', '', '文本文件 (*.txt, *.prf)') if path: try: with open(path, 'rU') as f: text = f.read() except Exception as e: self.msgCritical(str(e)) else: openDoc = QMdiSubWindow(self) openDoc.setWindowTitle(path) txtEdit = QPlainTextEdit(openDoc) txtEdit.setPlainText(text) openDoc.setWidget(txtEdit) self.mdiArea.addSubWindow(openDoc) openDoc.show() def onFileCloseAll(self): self.mdiArea.closeAllSubWindows() def onEditCut(self): txtEdit = self.mdiArea.activeSubWindow().widget() txtEdit.cut() def onEditCopy(self): txtEdit = self.mdiArea.activeSubWindow().widget() txtEdit.copy() def onEditPaste(self): txtEdit = self.mdiArea.activeSubWindow().widget() txtEdit.paste() def onWinowdMode(self, index): if index == 3: self.mdiArea.cascadeSubWindows() elif index == 2: self.mdiArea.tileSubWindows() elif index == 1: self.mdiArea.setViewMode(QMdiArea.TabbedView) else: self.mdiArea.setViewMode(QMdiArea.SubWindowView) def timerCallback(self): self.statusBar.showMessage( f'Document Index = {self.newDocIndex}, subWind num ={len(self.mdiArea.subWindowList())}', 0)
class Example(QMainWindow): def __init__(self): super().__init__() self.InitUI() def InitUI(self): self.setWindowTitle('扑克牌模拟') self.mid = QMdiArea() self.setCentralWidget(self.mid) sendOnecardAct = QAction(QIcon('./res/sendOnecard.ico'), '发1张牌', self) sendOnecardAct.triggered.connect(self.sendOnecard) sendFivecardsAct = QAction(QIcon('./res/sendFivecard.ico'), '随机5张牌', self) sendFivecardsAct.triggered.connect(self.sendFivecards) clearcardAct = QAction(QIcon('./res/clear.ico'), '清除牌', self) clearcardAct.triggered.connect(self.clearCards) foldcardAct = QAction(QIcon('./res/fold.ico'), '收牌', self) foldcardAct.triggered.connect(self.foldCards) toolbar = self.addToolBar('工具栏') toolbar.addAction(sendOnecardAct) toolbar.addAction(sendFivecardsAct) toolbar.addAction(clearcardAct) toolbar.addAction(foldcardAct) toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) def sendOnecard(self): randomflag = self.randomsend(1) subcard = QMdiSubWindow() subcard.setWidget(Card(randomflag)) self.mid.addSubWindow(subcard) subcard.setWindowFlags(Qt.WindowMinimizeButtonHint) subcard.show() def sendFivecards(self): randomflag = self.randomsend(5) for card in randomflag: subcard = QMdiSubWindow() subcard.setWidget(Card(card)) self.mid.addSubWindow(subcard) subcard.setWindowFlags(Qt.WindowMinimizeButtonHint) subcard.show() def clearCards(self): self.mid.closeAllSubWindows() def foldCards(self): self.mid.cascadeSubWindows() def randomsend(self, num): cardlist = [ "2", "3", "4", "5", "6", "7", "8", "9", "10", "a", "j", "joker", "k", "q" ] if num == 1: return random.choice(cardlist) elif num == 5: return random.sample(cardlist, 5)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.mdiArea = QMdiArea() self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setCentralWidget(self.mdiArea) self.mdiArea.subWindowActivated.connect(self.update_menus) self.windowMapper = QSignalMapper(self) self.windowMapper.mapped.connect(self.set_active_sub_window) self.newAct = QAction(self) self.newAct.setIcon(self.style().standardIcon(QStyle.SP_FileIcon)) # self.newAct.setIcon(QIcon(':/images/new.png')) self.newAct.setIconText('New') self.newAct.setShortcut(QKeySequence.New) self.newAct.setStatusTip('Create a new file') self.newAct.triggered.connect(self.new_file) self.openAct = QAction(self) self.openAct.setIcon(self.style().standardIcon(QStyle.SP_DirOpenIcon)) self.openAct.setIconText('Open...') self.openAct.setShortcut(QKeySequence.Open) self.openAct.setStatusTip('Open an existing file') self.openAct.triggered.connect(self.open) self.saveAct = QAction(self) self.saveAct.setIcon(self.style().standardIcon(QStyle.SP_DialogSaveButton)) self.saveAct.setIconText('Save') self.saveAct.setShortcut(QKeySequence.Save) self.saveAct.setStatusTip('Save the document to disk') self.saveAct.triggered.connect(self.save) self.saveAsAct = QAction(self) self.saveAsAct.setIconText('Save As...') self.saveAsAct.setShortcut(QKeySequence.SaveAs) self.saveAsAct.setStatusTip('Save the document under a new name') self.saveAsAct.triggered.connect(self.save_as) self.exitAct = QAction(self) self.exitAct.setIconText('Exit') self.exitAct.setShortcut(QKeySequence.Quit) self.exitAct.setStatusTip('Exit the application') self.exitAct.triggered.connect(qApp.closeAllWindows) self.cutAct = QAction(self) # self.cutAct.setIcon(QIcon(':/images/cut.png')) self.cutAct.setIconText('Cut') self.cutAct.setShortcut(QKeySequence.Cut) self.cutAct.setStatusTip("Cut the current selection's contents to the clipboard") self.cutAct.triggered.connect(self.cut) self.copyAct = QAction(self) # self.copyAct.setIcon(QIcon(':/images/copy.png')) self.copyAct.setIconText('Copy') self.copyAct.setShortcut(QKeySequence.Copy) self.copyAct.setStatusTip("Copy the current selection's contents to the clipboard") self.copyAct.triggered.connect(self.copy) self.pasteAct = QAction(self) # self.pasteAct.setIcon(QIcon(':/images/paste.png')) self.pasteAct.setIconText('Paste') self.pasteAct.setShortcut(QKeySequence.Paste) self.pasteAct.setStatusTip("Paste the clipboard's contents into the current selection") self.pasteAct.triggered.connect(self.paste) self.closeAct = QAction(self) self.closeAct.setIconText('Close') self.closeAct.setShortcut('Ctrl+W') self.closeAct.setStatusTip("Close the active window") self.closeAct.triggered.connect(self.mdiArea.closeActiveSubWindow) self.closeAllAct = QAction(self) self.closeAllAct.setIconText('Close All') self.closeAllAct.setStatusTip('Close all the windows') self.closeAllAct.triggered.connect(self.mdiArea.closeAllSubWindows) self.tileAct = QAction(self) self.tileAct.setIconText('Tile') self.tileAct.setStatusTip('Tile the windows') self.tileAct.triggered.connect(self.mdiArea.tileSubWindows) self.cascadeAct = QAction(self) self.cascadeAct.setIconText('Cascade') self.cascadeAct.setStatusTip('Cascade the windows') self.cascadeAct.triggered.connect(self.mdiArea.cascadeSubWindows) self.nextAct = QAction(self) self.nextAct.setIconText('Next') self.nextAct.setShortcut(QKeySequence.NextChild) self.nextAct.setStatusTip('Move the focus to the next window') self.nextAct.triggered.connect(self.mdiArea.activateNextSubWindow) self.previousAct = QAction(self) self.previousAct.setIconText('Previous') self.previousAct.setShortcut(QKeySequence.PreviousChild) self.previousAct.setStatusTip('Move the focus to the previous window') self.previousAct.triggered.connect(self.mdiArea.activatePreviousSubWindow) self.separatorAct = QAction(self) self.separatorAct.setSeparator(True) self.aboutAct = QAction(self) self.aboutAct.setIconText('About') self.aboutAct.setStatusTip("Show the application's About box") self.aboutAct.triggered.connect(self.about) self.aboutQtAct = QAction(self) self.aboutQtAct.setIconText('About Qt') self.aboutQtAct.setStatusTip("Show the Qt library's About box") self.aboutQtAct.triggered.connect(qApp.aboutQt) self.fileMenu = self.menuBar().addMenu('File') self.fileMenu.addAction(self.newAct) self.fileMenu.addAction(self.openAct) self.fileMenu.addAction(self.saveAct) self.fileMenu.addAction(self.saveAsAct) self.fileMenu.addSeparator() action = self.fileMenu.addAction('Switch layout direction') action.triggered.connect(self.switch_layout_direction) self.fileMenu.addAction(self.exitAct) self.editMenu = self.menuBar().addMenu('Edit') self.editMenu.addAction(self.cutAct) self.editMenu.addAction(self.copyAct) self.editMenu.addAction(self.pasteAct) self.windowMenu = self.menuBar().addMenu('Window') self.update_window_menu() self.windowMenu.aboutToShow.connect(self.update_window_menu) self.menuBar().addSeparator() self.helpMenu = self.menuBar().addMenu('Help') self.helpMenu.addAction(self.aboutAct) self.helpMenu.addAction(self.aboutQtAct) self.file_tool_bar = self.addToolBar('File') self.file_tool_bar.addAction(self.newAct) self.file_tool_bar.addAction(self.openAct) self.file_tool_bar.addAction(self.saveAct) self.edit_tool_bar = self.addToolBar('Edit') self.edit_tool_bar.addAction(self.cutAct) self.edit_tool_bar.addAction(self.copyAct) self.edit_tool_bar.addAction(self.pasteAct) self.statusBar().showMessage('Ready') self.update_menus() self.settings = QSettings('SavSoft', 'Combiner') self.last_directory: str = '' self.read_settings() self.setWindowTitle('MDI') self.setUnifiedTitleAndToolBarOnMac(True) def closeEvent(self, event): self.mdiArea.closeAllSubWindows() if self.active_mdi_child(): event.ignore() else: self.write_settings() event.accept() def new_file(self): child = self.create_mdi_child() child.new_file() child.show() def open(self): filters = ['IRTECON files (*.grd)', 'Plain text files (*.csv *.tsv *.dat *.txt)'] file_name, _ = QFileDialog.getOpenFileName(self, filter=';;'.join(filters), directory=self.last_directory, options=QFileDialog.DontUseNativeDialog) if file_name: child = self.create_mdi_child() if QFileInfo(file_name).suffix() == 'grd': if child.load_irtecon_file(file_name): self.statusBar().showMessage('File loaded', 2000) self.last_directory = QFileInfo(file_name).dir().absolutePath() child.show() else: child.close() else: print(PlainTextImportDialog(file_name).exec()) raise NotImplementedError def save(self): if self.active_mdi_child() and self.active_mdi_child().save(): self.statusBar().showMessage('File saved', 2000) def save_as(self): if self.active_mdi_child() and self.active_mdi_child().save_as(): self.statusBar().showMessage('File saved', 2000) def cut(self): if self.active_mdi_child(): self.active_mdi_child().cut() def copy(self): if self.active_mdi_child(): self.active_mdi_child().copy() def paste(self): if self.active_mdi_child(): self.active_mdi_child().paste() def about(self): QMessageBox.about(self, 'About MDI', 'The <b>MDI</b> example demonstrates how to write multiple ' 'document interface applications using Qt.') def update_menus(self): has_mdi_child = (self.active_mdi_child() is not None) self.saveAct.setEnabled(has_mdi_child) self.saveAsAct.setEnabled(has_mdi_child) self.pasteAct.setEnabled(has_mdi_child) self.closeAct.setEnabled(has_mdi_child) self.closeAllAct.setEnabled(has_mdi_child) self.tileAct.setEnabled(has_mdi_child) self.cascadeAct.setEnabled(has_mdi_child) self.nextAct.setEnabled(has_mdi_child) self.previousAct.setEnabled(has_mdi_child) self.separatorAct.setVisible(has_mdi_child) def update_window_menu(self): self.windowMenu.clear() self.windowMenu.addAction(self.closeAct) self.windowMenu.addAction(self.closeAllAct) self.windowMenu.addSeparator() self.windowMenu.addAction(self.tileAct) self.windowMenu.addAction(self.cascadeAct) self.windowMenu.addSeparator() self.windowMenu.addAction(self.nextAct) self.windowMenu.addAction(self.previousAct) self.windowMenu.addAction(self.separatorAct) windows = self.mdiArea.subWindowList() self.separatorAct.setVisible(len(windows) != 0) for i, window in enumerate(windows): child = window.widget() text = f'{i + 1:d} {child.user_friendly_current_file()}' if i < 9: text = '' + text action = self.windowMenu.addAction(text) action.setCheckable(True) action.setChecked(child == self.active_mdi_child()) action.triggered.connect(self.windowMapper.map) self.windowMapper.setMapping(action, window) def create_mdi_child(self): child = MDIChildPlot() self.mdiArea.addSubWindow(child) return child def read_settings(self): pos = self.settings.value('pos', QPoint(200, 200)) self.move(pos) size = self.settings.value('size', QSize(400, 400)) self.resize(size) self.last_directory = self.settings.value('directory', '') def write_settings(self): self.settings.setValue('pos', self.pos()) self.settings.setValue('size', self.size()) self.settings.setValue('directory', self.last_directory) def active_mdi_child(self): active_sub_window = self.mdiArea.activeSubWindow() if active_sub_window: return active_sub_window.widget() return None def switch_layout_direction(self): if self.layoutDirection() == Qt.LeftToRight: qApp.setLayoutDirection(Qt.RightToLeft) else: qApp.setLayoutDirection(Qt.LeftToRight) def set_active_sub_window(self, window): if window: self.mdiArea.setActiveSubWindow(window)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.mdiArea = QMdiArea() self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setCentralWidget(self.mdiArea) self.mdiArea.subWindowActivated.connect(self.updateMenus) self.windowMapper = QSignalMapper(self) self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow) self.createActions() self.createMenus() self.createToolBars() self.createStatusBar() self.updateMenus() self.readSettings() self.setWindowTitle("MDI Test") def closeEvent(self, event): self.mdiArea.closeAllSubWindows() if self.mdiArea.currentSubWindow(): event.ignore() else: self.writeSettings() event.accept() def newFile(self): child = self.createMdiChild() child.newFile() child.show() def open(self): fileName, _ = QFileDialog.getOpenFileName(self) if fileName: existing = self.findMdiChild(fileName) if existing: self.mdiArea.setActiveSubWindow(existing) return child = self.createMdiChild() if child.loadFile(fileName): self.statusBar().showMessage("File loaded", 2000) child.show() else: child.close() def save(self): if self.activeMdiChild() and self.activeMdiChild().save(): self.statusBar().showMessage("File saved", 2000) def saveAs(self): if self.activeMdiChild() and self.activeMdiChild().saveAs(): self.statusBar().showMessage("File saved", 2000) def cut(self): if self.activeMdiChild(): self.activeMdiChild().cut() def copy(self): if self.activeMdiChild(): self.activeMdiChild().copy() def paste(self): if self.activeMdiChild(): self.activeMdiChild().paste() def about(self): QMessageBox.about( self, "About MDI", "The <b>MDI</b> example demonstrates how to write multiple " "document interface applications using Qt.") def updateMenus(self): hasMdiChild = (self.activeMdiChild() is not None) #self.saveAct.setEnabled(hasMdiChild) #self.saveAsAct.setEnabled(hasMdiChild) self.pasteAct.setEnabled(hasMdiChild) self.closeAct.setEnabled(hasMdiChild) self.closeAllAct.setEnabled(hasMdiChild) self.tileAct.setEnabled(hasMdiChild) self.cascadeAct.setEnabled(hasMdiChild) self.nextAct.setEnabled(hasMdiChild) self.previousAct.setEnabled(hasMdiChild) self.separatorAct.setVisible(hasMdiChild) hasSelection = (self.activeMdiChild() is not None and self.activeMdiChild().textCursor().hasSelection()) self.cutAct.setEnabled(hasSelection) self.copyAct.setEnabled(hasSelection) def updateWindowMenu(self): self.windowMenu.clear() self.windowMenu.addAction(self.closeAct) self.windowMenu.addAction(self.closeAllAct) self.windowMenu.addSeparator() self.windowMenu.addAction(self.tileAct) self.windowMenu.addAction(self.cascadeAct) self.windowMenu.addSeparator() self.windowMenu.addAction(self.nextAct) self.windowMenu.addAction(self.previousAct) self.windowMenu.addAction(self.separatorAct) windows = self.mdiArea.subWindowList() self.separatorAct.setVisible(len(windows) != 0) for i, window in enumerate(windows): child = window.widget() text = "%d %s" % (i + 1, child.userFriendlyCurrentFile()) if i < 9: text = '&' + text action = self.windowMenu.addAction(text) action.setCheckable(True) action.setChecked(child is self.activeMdiChild()) action.triggered.connect(self.windowMapper.map) self.windowMapper.setMapping(action, window) def createMdiChild(self): child = MdiChild() self.mdiArea.addSubWindow(child) child.copyAvailable.connect(self.cutAct.setEnabled) child.copyAvailable.connect(self.copyAct.setEnabled) return child # showntell def createMdiChild15(self): child = MdiChild_ShowNTell() self.mdiArea.addSubWindow(child) return child #MNIST def show_n_tell(self): print('show_n_tell....') child = self.createMdiChild15() print('self.createMdiChild15') #child.resize(830,480) #print('self.createMdiChild15') child.show print('child.show()') def createActions(self): self.cutAct = QAction( QIcon(':/images/cut.png'), "Cu&t", self, shortcut=QKeySequence.Cut, statusTip="Cut the current selection's contents to the clipboard", triggered=self.cut) self.copyAct = QAction( QIcon(':/images/copy.png'), "&Copy", self, shortcut=QKeySequence.Copy, statusTip="Copy the current selection's contents to the clipboard", triggered=self.copy) self.pasteAct = QAction( QIcon(':/images/paste.png'), "&Paste", self, shortcut=QKeySequence.Paste, statusTip= "Paste the clipboard's contents into the current selection", triggered=self.paste) self.closeAct = QAction("Cl&ose", self, statusTip="Close the active window", triggered=self.mdiArea.closeActiveSubWindow) self.closeAllAct = QAction("Close &All", self, statusTip="Close all the windows", triggered=self.mdiArea.closeAllSubWindows) self.tileAct = QAction("&Tile", self, statusTip="Tile the windows", triggered=self.mdiArea.tileSubWindows) self.cascadeAct = QAction("&Cascade", self, statusTip="Cascade the windows", triggered=self.mdiArea.cascadeSubWindows) self.nextAct = QAction("Ne&xt", self, shortcut=QKeySequence.NextChild, statusTip="Move the focus to the next window", triggered=self.mdiArea.activateNextSubWindow) self.previousAct = QAction( "Pre&vious", self, shortcut=QKeySequence.PreviousChild, statusTip="Move the focus to the previous window", triggered=self.mdiArea.activatePreviousSubWindow) self.separatorAct = QAction(self) self.separatorAct.setSeparator(True) # 메뉴 ACTION을 다이나믹하게 연결해준다 self.MenuActRef = { 'NewFileAct': 0, 'OpnFileAct': 0, 'SavFileAct': 0, 'SavASFileAct': 0, 'AboutAct': 0, 'AboutQTAct': 0, 'ExitAct': 0, 'SwitchLayout': 0, 'ShowNTell': 0 } # ******* Create the File Menu ******* self.NewFileAct = QAction(QIcon(':/images/new.png'), '&New File', self) self.NewFileAct.setShortcut("Ctrl+N") self.NewFileAct.setStatusTip('Create a New File') self.NewFileAct.triggered.connect(self.newFile) self.MenuActRef['NewFileAct'] = self.NewFileAct #self.newAct = QAction(QIcon(':/images/new.png'), "&New", self, # shortcut=QKeySequence.New, statusTip="Create a new file", # triggered=self.newFile) # ******* Open File Menu Items ******* self.OpnFileAct = QAction(QIcon(':/images/open.png'), '&Open File', self) self.OpnFileAct.setShortcut("Ctrl+O") self.OpnFileAct.setStatusTip('Open an Existing File') self.OpnFileAct.triggered.connect(self.open) self.MenuActRef['OpnFileAct'] = self.OpnFileAct #self.openAct = QAction(QIcon(':/images/open.png'), "&Open...", self, # shortcut=QKeySequence.Open, statusTip="Open an existing file", # triggered=self.open) # ******* Save File Menu Items ******* self.SavFileAct = QAction(QIcon(':/images/save.png'), '&Save File', self) self.SavFileAct.setShortcut("Ctrl+S") self.SavFileAct.setStatusTip('Save Current File') self.SavFileAct.triggered.connect(self.save) self.MenuActRef['SavFileAct'] = self.SavFileAct #self.saveAct = QAction(QIcon(':/images/save.png'), "&Save", self, # shortcut=QKeySequence.Save, # statusTip="Save the document to disk", triggered=self.save) # ******* SaveAS File Menu Items ******* self.SavASFileAct = QAction('Save &As File', self) self.SavASFileAct.setShortcut("Ctrl+A") self.SavASFileAct.setStatusTip('Save Current File under a new name ') self.SavASFileAct.triggered.connect(self.saveAs) self.MenuActRef['SavASFileAct'] = self.SavASFileAct #self.saveAsAct = QAction("Save &As...", self, # shortcut=QKeySequence.SaveAs, # statusTip="Save the document under a new name", # triggered=self.saveAs) # ******* About Menu Items ******* self.aboutAct = QAction("&About", self) self.aboutAct.setStatusTip("Show the application's About box") self.aboutAct.triggered.connect(self.about) self.MenuActRef['AboutAct'] = self.aboutAct # ******* About QT Menu Items ******* self.aboutAct = QAction("About &Qt", self) self.aboutAct.setStatusTip("Show the Qt library's About box") self.aboutAct.triggered.connect(QApplication.instance().aboutQt) self.MenuActRef['AboutQTAct'] = self.aboutAct # ******* Exit Menu Items ******* self.exitAct = QAction("E&xit", self) self.exitAct.setStatusTip("Exit the application") self.exitAct.triggered.connect(QApplication.instance().closeAllWindows) self.MenuActRef['ExitAct'] = self.exitAct #self.exitAct = QAction("E&xit", self, shortcut=QKeySequence.Quit, # statusTip="Exit the application", # triggered=QApplication.instance().closeAllWindows) # ******* Switch layout Items ******* self.SwitchLayout = QAction("&Switch layout direction", self) self.SwitchLayout.setStatusTip("Switch layout direction") self.SwitchLayout.triggered.connect(self.switchLayoutDirection) self.MenuActRef['SwitchLayout'] = self.SwitchLayout #self.SwitchLayout = QAction("&Switch layout direction", self, # statusTip="Switch layout direction", # triggered=self.switchLayoutDirection) # ******* Switch layout Items ******* self.ShowNTell = QAction("&ShowNTell", self) self.ShowNTell.setStatusTip("&ShowNTell") self.ShowNTell.triggered.connect(self.show_n_tell) self.MenuActRef['ShowNTell'] = self.ShowNTell #self.ShowNTell = QAction("&show_n_tell", self, # statusTip="show_n_tell", # triggered=self.show_n_tell) def createMenus(self): # 메뉴를 다이나믹하게 생성하고 연결함 self.MenuLayout = { 0: { 'addMenu': '&File', 'addToolMenu': 'File' }, 1: { 'addDynamic': 'NewFileAct', 'addToolbar': 'NewFileAct' }, 2: { 'addDynamic': 'OpnFileAct', 'addToolbar': 'OpnFileAct' }, 3: { 'addDynamic': 'SavFileAct', 'addToolbar': 'SavFileAct' }, 4: { 'addDynamic': 'SavASFileAct' }, 5: { 'addSeparator': '' }, 6: { 'addDynamic': 'SwitchLayout' }, 7: { 'addDynamic': 'ExitAct' }, 8: { 'addMenu': '&Edit' }, 9: { 'addAction': self.cutAct }, 10: { 'addAction': self.copyAct }, 11: { 'addAction': self.pasteAct }, 12: { 'addMenu': '&Window' }, 13: { 'updateMenu': '' }, 14: { 'addSeparator': '' }, 15: { 'addMenu': '&Help' }, 16: { 'addDynamic': 'AboutAct' }, 17: { 'addDynamic': 'AboutQTAct' }, 18: { 'addMenu': '&MNIST' }, 19: { 'addDynamic': 'ShowNTell' } } for idx in self.MenuLayout: item = self.MenuLayout[idx] if 'addMenu' in item.keys(): self.windowMenu = self.menuBar().addMenu(item['addMenu']) elif 'addAction' in item.keys(): self.windowMenu.addAction(item['addAction']) elif 'addSeparator' in item.keys(): self.windowMenu.addSeparator() elif 'updateMenu' in item.keys(): self.updateWindowMenu() self.windowMenu.aboutToShow.connect(self.updateWindowMenu) # 메뉴 ACTION을 다이나믹하게 elif 'addDynamic' in item.keys(): self.windowMenu.addAction(self.MenuActRef[item['addDynamic']]) def createToolBars(self): for idx in self.MenuLayout: item = self.MenuLayout[idx] if 'addToolMenu' in item.keys(): self.fileToolBar = self.addToolBar(item['addToolMenu']) elif 'addToolbar' in item.keys(): self.fileToolBar.addAction(self.MenuActRef[item['addDynamic']]) #self.fileToolBar = self.addToolBar("File") #self.fileToolBar.addAction(self.MenuActRef['NewFileAct']) #self.fileToolBar.addAction(self.MenuActRef['OpnFileAct']) #self.fileToolBar.addAction(self.MenuActRef['SavFileAct']) #self.fileToolBar.addAction(self.newAct) #self.fileToolBar.addAction(self.openAct) #self.fileToolBar.addAction(self.saveAct) self.editToolBar = self.addToolBar("Edit") self.editToolBar.addAction(self.cutAct) self.editToolBar.addAction(self.copyAct) self.editToolBar.addAction(self.pasteAct) def createStatusBar(self): self.statusBar().showMessage("Ready") def readSettings(self): settings = QSettings('NH-Soft', 'MDI Example') pos = settings.value('pos', QPoint(200, 200)) size = settings.value('size', QSize(400, 400)) self.move(pos) self.resize(size) def writeSettings(self): settings = QSettings('NH-Soft', 'MDI Example') settings.setValue('pos', self.pos()) settings.setValue('size', self.size()) def activeMdiChild(self): activeSubWindow = self.mdiArea.activeSubWindow() if activeSubWindow: return activeSubWindow.widget() return None def findMdiChild(self, fileName): canonicalFilePath = QFileInfo(fileName).canonicalFilePath() for window in self.mdiArea.subWindowList(): if window.widget().currentFile() == canonicalFilePath: return window return None def switchLayoutDirection(self): if self.layoutDirection() == Qt.LeftToRight: QApplication.setLayoutDirection(Qt.RightToLeft) else: QApplication.setLayoutDirection(Qt.LeftToRight) def setActiveSubWindow(self, window): if window: self.mdiArea.setActiveSubWindow(window)
class DemoMdi(QMainWindow): def __init__(self, parent=None): super(DemoMdi, self).__init__(parent) # 设置窗口标题 self.setWindowTitle('实战PyQt5: MDI多文档接口程序 演示') # 设置窗口大小 self.resize(480, 360) self.initUi() def initUi(self): self.initMenuBar() self.initToolBar() self.mdiArea = QMdiArea(self) self.setCentralWidget(self.mdiArea) self.newDocIndex = 1 def initMenuBar(self): menuBar = self.menuBar() style = QApplication.style() #==== 文件 ====# fileMenu = menuBar.addMenu('文件') #新建一个文档 aFileNew = QAction('新建文档', self) aFileNew.setIcon(style.standardIcon(QStyle.SP_FileIcon)) aFileNew.triggered.connect(self.onFileNew) fileMenu.addAction(aFileNew) #打开一个文档 aFileOpen = QAction('打开文档', self) aFileOpen.setIcon(style.standardIcon(QStyle.SP_DialogOpenButton)) aFileOpen.triggered.connect(self.onFileOpen) fileMenu.addAction(aFileOpen) #关闭一个文档 aFileCloseAll = QAction('关闭全部', self) aFileCloseAll.setIcon(style.standardIcon(QStyle.SP_DialogCloseButton)) aFileOpen.triggered.connect(self.onFileCloseAll) fileMenu.addAction(aFileCloseAll) #添加分割线 fileMenu.addSeparator() #退出 aFileExit = QAction('退出', self) aFileExit.triggered.connect(self.close) fileMenu.addAction(aFileExit) #==== 编辑 ====# editMenu = menuBar.addMenu('编辑') #剪切 aEditCut = QAction('剪切', self) aEditCut.setIcon(QIcon(':/ico/cut.png')) aEditCut.triggered.connect(self.onEditCut) editMenu.addAction(aEditCut) #复制 aEditCopy = QAction('复制', self) aEditCopy.setIcon(QIcon(':/ico/copy.png')) aEditCopy.triggered.connect(self.onEditCopy) editMenu.addAction(aEditCopy) #粘贴 aEditPaste = QAction('粘贴', self) aEditPaste.setIcon(QIcon(':/ico/paste.png')) aEditPaste.triggered.connect(self.onEditPaste) editMenu.addAction(aEditPaste) #==== 窗口排列方式 ====# windowMenu = menuBar.addMenu('窗口') #子窗口模式 aWndSubView = QAction('子窗口模式', self) aWndSubView.triggered.connect(lambda: self.onWinowdMode(0)) windowMenu.addAction(aWndSubView) #标签页模式 aWndTab = QAction('标签页模式', self) aWndTab.triggered.connect(lambda: self.onWinowdMode(1)) windowMenu.addAction(aWndTab) windowMenu.addSeparator() #平铺模式 aWndTile = QAction('平铺模式', self) aWndTile.triggered.connect(lambda: self.onWinowdMode(2)) windowMenu.addAction(aWndTile) #窗口级联模式 aWndCascade = QAction('窗口级联模式', self) aWndCascade.triggered.connect(lambda: self.onWinowdMode(3)) windowMenu.addAction(aWndCascade) def initToolBar(self): toolBar = self.addToolBar('') style = QApplication.style() min_width = 64 btnFileNew = QToolButton(self) btnFileNew.setText('新建文档') btnFileNew.setMinimumWidth(min_width) btnFileNew.setIcon(style.standardIcon(QStyle.SP_FileIcon)) btnFileNew.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) btnFileNew.clicked.connect(self.onFileNew) toolBar.addWidget(btnFileNew) btnFileOpen = QToolButton(self) btnFileOpen.setText('打开文档') btnFileOpen.setMinimumWidth(min_width) btnFileOpen.setIcon(style.standardIcon(QStyle.SP_DialogOpenButton)) btnFileOpen.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) btnFileOpen.clicked.connect(self.onFileOpen) toolBar.addWidget(btnFileOpen) btnFileCloseAll = QToolButton(self) btnFileCloseAll.setText('关闭全部') btnFileCloseAll.setMinimumWidth(min_width) btnFileCloseAll.setIcon(style.standardIcon( QStyle.SP_DialogCloseButton)) btnFileCloseAll.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) btnFileCloseAll.clicked.connect(self.onFileCloseAll) toolBar.addWidget(btnFileCloseAll) toolBar.addSeparator() btnEditCut = QToolButton(self) btnEditCut.setText('剪切') btnEditCut.setMinimumWidth(64) btnEditCut.setIcon(QIcon(':/ico/cut.png')) btnEditCut.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) btnEditCut.clicked.connect(self.onEditCut) toolBar.addWidget(btnEditCut) btnEditCopy = QToolButton(self) btnEditCopy.setText('复制') btnEditCopy.setMinimumWidth(64) btnEditCopy.setIcon(QIcon(':/ico/copy.png')) btnEditCopy.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) btnEditCopy.clicked.connect(self.onEditCopy) toolBar.addWidget(btnEditCopy) btnEditPaste = QToolButton(self) btnEditPaste.setText('粘贴') btnEditPaste.setMinimumWidth(64) btnEditPaste.setIcon(QIcon(':/ico/paste.png')) btnEditPaste.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) btnEditPaste.clicked.connect(self.onEditPaste) toolBar.addWidget(btnEditPaste) def msgCritical(self, strInfo): dlg = QMessageBox(self) dlg.setIcon(QMessageBox.Critical) dlg.setText(strInfo) dlg.show() def onFileNew(self): newDoc = QMdiSubWindow(self) newDoc.setWindowTitle('新文档 ' + str(self.newDocIndex)) self.newDocIndex += 1 newDoc.setWidget(QPlainTextEdit(newDoc)) self.mdiArea.addSubWindow(newDoc) newDoc.show() def onFileOpen(self): path, _ = QFileDialog.getOpenFileName(self, '打开文件', '', '文本文件 (*.txt)') if path: try: with open(path, 'rU') as f: text = f.read() except Exception as e: self.msgCritical(str(e)) else: openDoc = QMdiSubWindow(self) openDoc.setWindowTitle(path) txtEdit = QPlainTextEdit(openDoc) txtEdit.setPlainText(text) openDoc.setWidget(txtEdit) self.mdiArea.addSubWindow(openDoc) openDoc.show() def onFileCloseAll(self): self.mdiArea.closeAllSubWindows() def onEditCut(self): txtEdit = self.mdiArea.activeSubWindow().widget() txtEdit.cut() def onEditCopy(self): txtEdit = self.mdiArea.activeSubWindow().widget() txtEdit.copy() def onEditPaste(self): txtEdit = self.mdiArea.activeSubWindow().widget() txtEdit.paste() def onWinowdMode(self, index): if index == 3: self.mdiArea.cascadeSubWindows() elif index == 2: self.mdiArea.tileSubWindows() elif index == 1: self.mdiArea.setViewMode(QMdiArea.TabbedView) else: self.mdiArea.setViewMode(QMdiArea.SubWindowView)