def createEditor(self, parent, option, index): dateedit = QDateEdit(parent) #dateedit=QDateTimeEdit(parent) dateedit.setDateRange(self.minimum, self.maximum) dateedit.setAlignment(Qt.AlignRight | Qt.AlignVCenter) dateedit.setDisplayFormat(self.format) dateedit.setCalendarPopup(True) return dateedit
class 시간날짜편집기(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): label = QLabel('QTimeEdit') label.setAlignment(Qt.AlignCenter) time = QTimeEdit(self) time.setTime(QTime.currentTime()) time.setTimeRange(QTime(00, 00, 00), QTime.currentTime()) time.setDisplayFormat('a:hh:mm:ss.zzz') label2 = QLabel('QDateEdit') label2.setAlignment(Qt.AlignCenter) self.date_edit = QDateEdit(self) self.date_edit.setDate(QDate.currentDate()) self.date_edit.setDateRange(QDate(2000, 1, 1), QDate.currentDate()) # self.date_edit.setDisplayFormat('yyyy년 MMMM d일') self.date_edit.dateChanged.connect(self.dateChange) self.label3 = QLabel('이곳에 QDateEdit에서 선택된 값이 나타납니다.') self.label3.setAlignment(Qt.AlignCenter) label4 = QLabel('QDateTimeEdit') label4.setAlignment(Qt.AlignCenter) label5 = QLabel(self) label5.setAlignment(Qt.AlignCenter) label5.setText( f'QDateTime \n 현재 시간은 {QDateTime.currentDateTime().toString("yyyy년 MMMM d일 ap hh시 mm분 ss초.zzz")} 입니다.' ) dt_edit = QDateTimeEdit(self) dt_edit.setDateTimeRange(QDateTime(2020, 1, 1, 00, 00, 00),\ QDateTime(2021, 1, 1, 00, 00, 00)) dt_edit.setDisplayFormat('yyyy.MM.dd hh:mm:ss') vbox = QVBoxLayout() vbox.addWidget(label) vbox.addWidget(time) vbox.addWidget(label2) vbox.addWidget(self.date_edit) vbox.addWidget(self.label3) vbox.addWidget(label4) vbox.addWidget(label5) vbox.addWidget(dt_edit) self.setLayout(vbox) self.setWindowTitle('QTime, QDateEdit, QDateTimeEdit') self.setGeometry(300, 300, 400, 300) self.show() def dateChange(self): self.label3.setText(self.date_edit.date().toString('yyyy년 MMMM d일'))
def createDateTimeEdits(self): self.editsGroup = QGroupBox("Date and time spin boxes") dateLabel = QLabel() dateEdit = QDateEdit(QDate.currentDate()) dateEdit.setDateRange(QDate(2005, 1, 1), QDate(2010, 12, 31)) dateLabel.setText("Appointment date (between %s and %s):" % (dateEdit.minimumDate().toString(Qt.ISODate), dateEdit.maximumDate().toString(Qt.ISODate))) timeLabel = QLabel() timeEdit = QTimeEdit(QTime.currentTime()) timeEdit.setTimeRange(QTime(9, 0, 0, 0), QTime(16, 30, 0, 0)) timeLabel.setText("Appointment time (between %s and %s):" % (timeEdit.minimumTime().toString(Qt.ISODate), timeEdit.maximumTime().toString(Qt.ISODate))) self.meetingLabel = QLabel() self.meetingEdit = QDateTimeEdit(QDateTime.currentDateTime()) formatLabel = QLabel("Format string for the meeting date and time:") formatComboBox = QComboBox() formatComboBox.addItem('yyyy-MM-dd hh:mm:ss (zzz \'ms\')') formatComboBox.addItem('hh:mm:ss MM/dd/yyyy') formatComboBox.addItem('hh:mm:ss dd/MM/yyyy') formatComboBox.addItem('hh:mm:ss') formatComboBox.addItem('hh:mm ap') formatComboBox.activated[str].connect(self.setFormatString) self.setFormatString(formatComboBox.currentText()) editsLayout = QVBoxLayout() editsLayout.addWidget(dateLabel) editsLayout.addWidget(dateEdit) editsLayout.addWidget(timeLabel) editsLayout.addWidget(timeEdit) editsLayout.addWidget(self.meetingLabel) editsLayout.addWidget(self.meetingEdit) editsLayout.addWidget(formatLabel) editsLayout.addWidget(formatComboBox) self.editsGroup.setLayout(editsLayout)
class Window(QWidget): def __init__(self): super(Window, self).__init__() self.createPreviewGroupBox() self.createGeneralOptionsGroupBox() self.createDatesGroupBox() self.createTextFormatsGroupBox() layout = QGridLayout() layout.addWidget(self.previewGroupBox, 0, 0) layout.addWidget(self.generalOptionsGroupBox, 0, 1) layout.addWidget(self.datesGroupBox, 1, 0) layout.addWidget(self.textFormatsGroupBox, 1, 1) layout.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(layout) self.previewLayout.setRowMinimumHeight( 0, self.calendar.sizeHint().height()) self.previewLayout.setColumnMinimumWidth( 0, self.calendar.sizeHint().width()) self.setWindowTitle("Calendar Widget") def localeChanged(self, index): self.calendar.setLocale(self.localeCombo.itemData(index)) def firstDayChanged(self, index): self.calendar.setFirstDayOfWeek( Qt.DayOfWeek(self.firstDayCombo.itemData(index))) def selectionModeChanged(self, index): self.calendar.setSelectionMode( QCalendarWidget.SelectionMode( self.selectionModeCombo.itemData(index))) def horizontalHeaderChanged(self, index): self.calendar.setHorizontalHeaderFormat( QCalendarWidget.HorizontalHeaderFormat( self.horizontalHeaderCombo.itemData(index))) def verticalHeaderChanged(self, index): self.calendar.setVerticalHeaderFormat( QCalendarWidget.VerticalHeaderFormat( self.verticalHeaderCombo.itemData(index))) def selectedDateChanged(self): self.currentDateEdit.setDate(self.calendar.selectedDate()) def minimumDateChanged(self, date): self.calendar.setMinimumDate(date) self.maximumDateEdit.setDate(self.calendar.maximumDate()) def maximumDateChanged(self, date): self.calendar.setMaximumDate(date) self.minimumDateEdit.setDate(self.calendar.minimumDate()) def weekdayFormatChanged(self): format = QTextCharFormat() format.setForeground( Qt.GlobalColor( self.weekdayColorCombo.itemData( self.weekdayColorCombo.currentIndex()))) self.calendar.setWeekdayTextFormat(Qt.Monday, format) self.calendar.setWeekdayTextFormat(Qt.Tuesday, format) self.calendar.setWeekdayTextFormat(Qt.Wednesday, format) self.calendar.setWeekdayTextFormat(Qt.Thursday, format) self.calendar.setWeekdayTextFormat(Qt.Friday, format) def weekendFormatChanged(self): format = QTextCharFormat() format.setForeground( Qt.GlobalColor( self.weekendColorCombo.itemData( self.weekendColorCombo.currentIndex()))) self.calendar.setWeekdayTextFormat(Qt.Saturday, format) self.calendar.setWeekdayTextFormat(Qt.Sunday, format) def reformatHeaders(self): text = self.headerTextFormatCombo.currentText() format = QTextCharFormat() if text == "Bold": format.setFontWeight(QFont.Bold) elif text == "Italic": format.setFontItalic(True) elif text == "Green": format.setForeground(Qt.green) self.calendar.setHeaderTextFormat(format) def reformatCalendarPage(self): if self.firstFridayCheckBox.isChecked(): firstFriday = QDate(self.calendar.yearShown(), self.calendar.monthShown(), 1) while firstFriday.dayOfWeek() != Qt.Friday: firstFriday = firstFriday.addDays(1) firstFridayFormat = QTextCharFormat() firstFridayFormat.setForeground(Qt.blue) self.calendar.setDateTextFormat(firstFriday, firstFridayFormat) # May 1st in Red takes precedence. if self.mayFirstCheckBox.isChecked(): mayFirst = QDate(self.calendar.yearShown(), 5, 1) mayFirstFormat = QTextCharFormat() mayFirstFormat.setForeground(Qt.red) self.calendar.setDateTextFormat(mayFirst, mayFirstFormat) def createPreviewGroupBox(self): self.previewGroupBox = QGroupBox("Preview") self.calendar = QCalendarWidget() self.calendar.setMinimumDate(QDate(1900, 1, 1)) self.calendar.setMaximumDate(QDate(3000, 1, 1)) self.calendar.setGridVisible(True) self.calendar.currentPageChanged.connect(self.reformatCalendarPage) self.previewLayout = QGridLayout() self.previewLayout.addWidget(self.calendar, 0, 0, Qt.AlignCenter) self.previewGroupBox.setLayout(self.previewLayout) def createGeneralOptionsGroupBox(self): self.generalOptionsGroupBox = QGroupBox("General Options") self.localeCombo = QComboBox() curLocaleIndex = -1 index = 0 this_language = self.locale().nativeLanguageName() this_country = self.locale().nativeCountryName() for locale in QLocale.matchingLocales(QLocale.AnyLanguage, QLocale.AnyScript, QLocale.AnyCountry): language = locale.nativeLanguageName() country = locale.nativeCountryName() if language == this_language and country == this_country: curLocaleIndex = index self.localeCombo.addItem('%s/%s' % (language, country), locale) index += 1 if curLocaleIndex != -1: self.localeCombo.setCurrentIndex(curLocaleIndex) self.localeLabel = QLabel("&Locale") self.localeLabel.setBuddy(self.localeCombo) self.firstDayCombo = QComboBox() self.firstDayCombo.addItem("Sunday", Qt.Sunday) self.firstDayCombo.addItem("Monday", Qt.Monday) self.firstDayCombo.addItem("Tuesday", Qt.Tuesday) self.firstDayCombo.addItem("Wednesday", Qt.Wednesday) self.firstDayCombo.addItem("Thursday", Qt.Thursday) self.firstDayCombo.addItem("Friday", Qt.Friday) self.firstDayCombo.addItem("Saturday", Qt.Saturday) self.firstDayLabel = QLabel("Wee&k starts on:") self.firstDayLabel.setBuddy(self.firstDayCombo) self.selectionModeCombo = QComboBox() self.selectionModeCombo.addItem("Single selection", QCalendarWidget.SingleSelection) self.selectionModeCombo.addItem("None", QCalendarWidget.NoSelection) self.selectionModeLabel = QLabel("&Selection mode:") self.selectionModeLabel.setBuddy(self.selectionModeCombo) self.gridCheckBox = QCheckBox("&Grid") self.gridCheckBox.setChecked(self.calendar.isGridVisible()) self.navigationCheckBox = QCheckBox("&Navigation bar") self.navigationCheckBox.setChecked(True) self.horizontalHeaderCombo = QComboBox() self.horizontalHeaderCombo.addItem( "Single letter day names", QCalendarWidget.SingleLetterDayNames) self.horizontalHeaderCombo.addItem("Short day names", QCalendarWidget.ShortDayNames) self.horizontalHeaderCombo.addItem("Long day names", QCalendarWidget.LongDayNames) self.horizontalHeaderCombo.addItem("None", QCalendarWidget.NoHorizontalHeader) self.horizontalHeaderCombo.setCurrentIndex(1) self.horizontalHeaderLabel = QLabel("&Horizontal header:") self.horizontalHeaderLabel.setBuddy(self.horizontalHeaderCombo) self.verticalHeaderCombo = QComboBox() self.verticalHeaderCombo.addItem("ISO week numbers", QCalendarWidget.ISOWeekNumbers) self.verticalHeaderCombo.addItem("None", QCalendarWidget.NoVerticalHeader) self.verticalHeaderLabel = QLabel("&Vertical header:") self.verticalHeaderLabel.setBuddy(self.verticalHeaderCombo) self.localeCombo.currentIndexChanged.connect(self.localeChanged) self.firstDayCombo.currentIndexChanged.connect(self.firstDayChanged) self.selectionModeCombo.currentIndexChanged.connect( self.selectionModeChanged) self.gridCheckBox.toggled.connect(self.calendar.setGridVisible) self.navigationCheckBox.toggled.connect( self.calendar.setNavigationBarVisible) self.horizontalHeaderCombo.currentIndexChanged.connect( self.horizontalHeaderChanged) self.verticalHeaderCombo.currentIndexChanged.connect( self.verticalHeaderChanged) checkBoxLayout = QHBoxLayout() checkBoxLayout.addWidget(self.gridCheckBox) checkBoxLayout.addStretch() checkBoxLayout.addWidget(self.navigationCheckBox) outerLayout = QGridLayout() outerLayout.addWidget(self.localeLabel, 0, 0) outerLayout.addWidget(self.localeCombo, 0, 1) outerLayout.addWidget(self.firstDayLabel, 1, 0) outerLayout.addWidget(self.firstDayCombo, 1, 1) outerLayout.addWidget(self.selectionModeLabel, 2, 0) outerLayout.addWidget(self.selectionModeCombo, 2, 1) outerLayout.addLayout(checkBoxLayout, 3, 0, 1, 2) outerLayout.addWidget(self.horizontalHeaderLabel, 4, 0) outerLayout.addWidget(self.horizontalHeaderCombo, 4, 1) outerLayout.addWidget(self.verticalHeaderLabel, 5, 0) outerLayout.addWidget(self.verticalHeaderCombo, 5, 1) self.generalOptionsGroupBox.setLayout(outerLayout) self.firstDayChanged(self.firstDayCombo.currentIndex()) self.selectionModeChanged(self.selectionModeCombo.currentIndex()) self.horizontalHeaderChanged(self.horizontalHeaderCombo.currentIndex()) self.verticalHeaderChanged(self.verticalHeaderCombo.currentIndex()) def createDatesGroupBox(self): self.datesGroupBox = QGroupBox(self.tr("Dates")) self.minimumDateEdit = QDateEdit() self.minimumDateEdit.setDisplayFormat('MMM d yyyy') self.minimumDateEdit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.minimumDateEdit.setDate(self.calendar.minimumDate()) self.minimumDateLabel = QLabel("&Minimum Date:") self.minimumDateLabel.setBuddy(self.minimumDateEdit) self.currentDateEdit = QDateEdit() self.currentDateEdit.setDisplayFormat('MMM d yyyy') self.currentDateEdit.setDate(self.calendar.selectedDate()) self.currentDateEdit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.currentDateLabel = QLabel("&Current Date:") self.currentDateLabel.setBuddy(self.currentDateEdit) self.maximumDateEdit = QDateEdit() self.maximumDateEdit.setDisplayFormat('MMM d yyyy') self.maximumDateEdit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.maximumDateEdit.setDate(self.calendar.maximumDate()) self.maximumDateLabel = QLabel("Ma&ximum Date:") self.maximumDateLabel.setBuddy(self.maximumDateEdit) self.currentDateEdit.dateChanged.connect(self.calendar.setSelectedDate) self.calendar.selectionChanged.connect(self.selectedDateChanged) self.minimumDateEdit.dateChanged.connect(self.minimumDateChanged) self.maximumDateEdit.dateChanged.connect(self.maximumDateChanged) dateBoxLayout = QGridLayout() dateBoxLayout.addWidget(self.currentDateLabel, 1, 0) dateBoxLayout.addWidget(self.currentDateEdit, 1, 1) dateBoxLayout.addWidget(self.minimumDateLabel, 0, 0) dateBoxLayout.addWidget(self.minimumDateEdit, 0, 1) dateBoxLayout.addWidget(self.maximumDateLabel, 2, 0) dateBoxLayout.addWidget(self.maximumDateEdit, 2, 1) dateBoxLayout.setRowStretch(3, 1) self.datesGroupBox.setLayout(dateBoxLayout) def createTextFormatsGroupBox(self): self.textFormatsGroupBox = QGroupBox("Text Formats") self.weekdayColorCombo = self.createColorComboBox() self.weekdayColorCombo.setCurrentIndex( self.weekdayColorCombo.findText("Black")) self.weekdayColorLabel = QLabel("&Weekday color:") self.weekdayColorLabel.setBuddy(self.weekdayColorCombo) self.weekendColorCombo = self.createColorComboBox() self.weekendColorCombo.setCurrentIndex( self.weekendColorCombo.findText("Red")) self.weekendColorLabel = QLabel("Week&end color:") self.weekendColorLabel.setBuddy(self.weekendColorCombo) self.headerTextFormatCombo = QComboBox() self.headerTextFormatCombo.addItem("Bold") self.headerTextFormatCombo.addItem("Italic") self.headerTextFormatCombo.addItem("Plain") self.headerTextFormatLabel = QLabel("&Header text:") self.headerTextFormatLabel.setBuddy(self.headerTextFormatCombo) self.firstFridayCheckBox = QCheckBox("&First Friday in blue") self.mayFirstCheckBox = QCheckBox("May &1 in red") self.weekdayColorCombo.currentIndexChanged.connect( self.weekdayFormatChanged) self.weekendColorCombo.currentIndexChanged.connect( self.weekendFormatChanged) self.headerTextFormatCombo.currentIndexChanged.connect( self.reformatHeaders) self.firstFridayCheckBox.toggled.connect(self.reformatCalendarPage) self.mayFirstCheckBox.toggled.connect(self.reformatCalendarPage) checkBoxLayout = QHBoxLayout() checkBoxLayout.addWidget(self.firstFridayCheckBox) checkBoxLayout.addStretch() checkBoxLayout.addWidget(self.mayFirstCheckBox) outerLayout = QGridLayout() outerLayout.addWidget(self.weekdayColorLabel, 0, 0) outerLayout.addWidget(self.weekdayColorCombo, 0, 1) outerLayout.addWidget(self.weekendColorLabel, 1, 0) outerLayout.addWidget(self.weekendColorCombo, 1, 1) outerLayout.addWidget(self.headerTextFormatLabel, 2, 0) outerLayout.addWidget(self.headerTextFormatCombo, 2, 1) outerLayout.addLayout(checkBoxLayout, 3, 0, 1, 2) self.textFormatsGroupBox.setLayout(outerLayout) self.weekdayFormatChanged() self.weekendFormatChanged() self.reformatHeaders() self.reformatCalendarPage() def createColorComboBox(self): comboBox = QComboBox() comboBox.addItem("Red", Qt.red) comboBox.addItem("Blue", Qt.blue) comboBox.addItem("Black", Qt.black) comboBox.addItem("Magenta", Qt.magenta) return comboBox
class ViewDataWindow(QDialog): formSubmitted = pyqtSignal() closeSignal = pyqtSignal() def __init__(self, LOGIN, parent=None): #super(ViewDataWindow, self).__init__(parent) super().__init__(parent) self.LOGIN = LOGIN self.db = db(self.LOGIN, "Brewing") self.displayNo = 0 self.displayedBrewsH = [] self.displayedBrewsVMash = [] self.displayedBrewsVBoil = [] self.displayedBrewsVFerment = [] self.create_layout_viewData() self.setWindowTitle('Past Brew Viewer') self.activeColours = [] self.colours = ["red", "green", "blue", "black",\ "cyan", "magenta", "yellow", "gray"] # Function to create layout of New Brew window def create_layout_viewData(self): # Create scroll boxes for filtering data filterGroupBox = QGroupBox("Filter by:") # Date edit box lab_date = QLabel("Date:") self.dateEdit = QDateEdit() # Set range of possible dates, current date is max date self.maxDate = QDate().currentDate() self.minDate = QDate(2019, 1, 1) self.dateEdit.setDate(self.maxDate) self.dateEdit.setDateRange(self.minDate, self.maxDate) self.dateEdit.setCalendarPopup(1) self.dateEdit.setDisplayFormat("dd/MM/yy") #self.dateEdit2 = QLineEdit() self.dateEdit.dateChanged.connect(self.filter_date) dateHLayout = QHBoxLayout() dateHLayout.addWidget(lab_date) dateHLayout.addWidget(self.dateEdit) ### Text edit filters ### # Batch ID search lab_batch = QLabel("Batch ID:") self.edit_batchID = QLineEdit() self.edit_batchID.setPlaceholderText("Enter Batch ID") self.but_IDsearch = QPushButton("Go") self.but_IDsearch.setAutoDefault(0) self.but_IDsearch.clicked.connect(self.filter_batchID) self.edit_batchID.returnPressed.connect(self.filter_batchID) batchHLayout = QHBoxLayout() batchHLayout.addWidget(lab_batch) batchHLayout.addWidget(self.edit_batchID) batchHLayout.addWidget(self.but_IDsearch) # Recipe search lab_recipe = QLabel("Recipe:") self.lineEdit_recipe = QLineEdit() self.lineEdit_recipe.setPlaceholderText("Enter Recipe") self.lineEdit_recipe.textChanged.connect(self.filter_recipe) self.lineEdit_recipe.returnPressed.connect(self.filter_recipe) recipeHLayout = QHBoxLayout() recipeHLayout.addWidget(lab_recipe) recipeHLayout.addWidget(self.lineEdit_recipe) # Clear filters button self.but_clearFilter = QPushButton("Clear Filters") self.but_clearFilter.setAutoDefault(0) clearHLayout = QHBoxLayout() clearHLayout.addStretch(1) clearHLayout.addWidget(self.but_clearFilter) clearHLayout.addStretch(0) self.but_clearFilter.clicked.connect(self.clearFilters) # Filter groupbox layout #recipeHLayout.addWidget(self.recipeEdit) #recipeVLayout = QVBoxLayout() #recipeVLayout.addLayout(recipeHLayout) #recipeVLayout.addWidget(self.lineEdit_recipe) filterHLayout = QHBoxLayout() filterHLayout.addStretch(1) filterHLayout.addWidget(lab_date) filterHLayout.addWidget(self.dateEdit) filterHLayout.addStretch(1) #filterHLayout.addLayout(recipeVLayout) filterHLayout.addStretch(1) filterHLayout.addWidget(self.edit_batchID) filterHLayout.addWidget(self.but_IDsearch) filterHLayout.addStretch(1) #filterGroupBox.setLayout(filterHLayout) # Alternate - Filter vertical layout filterVLayout = QVBoxLayout() filterVLayout.addLayout(batchHLayout) filterVLayout.addLayout(recipeHLayout) filterVLayout.addLayout(dateHLayout) filterVLayout.addLayout(clearHLayout) filterGroupBox.setLayout(filterVLayout) # scrollHLayout = QHBoxLayout() # scrollHLayout.addWidget(filterGroupBox) # scrollHLayout.addStretch(1) # Create QTableView of brew data header = ['Brew ID', 'Recipe', 'Date'] self.model = MyTableModel( self.db.readFromTable("Brews", "id, Recipe, Date"), header, self) self.proxyModel = QSortFilterProxyModel(self) self.proxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive) self.proxyModel.setSourceModel(self.model) self.dataTable = QTableView() self.dataTable.setModel(self.proxyModel) self.dataTable.setSortingEnabled(True) self.dataTable.setSelectionBehavior(1) # Create bottom buttons self.but_quit = QPushButton("Close") self.but_quit.setAutoDefault(0) self.but_view = QPushButton("Display Brew") self.but_view.setAutoDefault(0) quitHLayout = QHBoxLayout() quitHLayout.addStretch(0) quitHLayout.addWidget(self.but_quit) quitHLayout.addStretch(3) quitHLayout.addWidget(self.but_view) quitHLayout.addStretch(0) # Main vertical layout for left area lWidget = QWidget() vLayoutL = QVBoxLayout(lWidget) vLayoutL.addWidget(filterGroupBox) vLayoutL.addWidget(self.dataTable) vLayoutL.addLayout(quitHLayout) # Widget for displayed brews - Widget allows fixed height to be set displayedWidget = QWidget() #displayedWidget.setFixedHeight(180) # h Layout to add groupboxes of displayed brews - added to in viewButtonClicked slot self.hLayoutDisplayed = QHBoxLayout() self.hLayoutDisplayed.addStretch(1) self.hLayoutDisplayed.setSizeConstraint(5) displayedWidget.setLayout(self.hLayoutDisplayed) # Scroll area for horizontal displayed brews hScrollArea = QScrollArea() hScrollArea.setWidget(displayedWidget) hScrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) hScrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) #hScrollArea.setFixedHeight(120) hScrollArea.setMinimumHeight(20) # Main v layout for displayed brews widget displayTitle = QLabel("Displayed Brews:") displayTitle.setMaximumHeight(20) hDisplayedWidget = QWidget() self.vLayoutDisplayed = QVBoxLayout(hDisplayedWidget) self.vLayoutDisplayed.addWidget(displayTitle) self.vLayoutDisplayed.addWidget(hScrollArea) # Main vertical layout for right area rWidget = QWidget() rSplitter = QSplitter() rSplitter.setOrientation(Qt.Orientation(2)) #vLayoutR = QVBoxLayout(rWidget) self.tabs = QTabWidget() self.tabMash = MashTab() self.tabBoil = BoilTab() self.tabFerment = FermentTab() self.tabs.resize(100, 1000) self.tabs.setMinimumSize(400, 100) self.tabs.addTab(self.tabMash, "Mash") self.tabs.addTab(self.tabBoil, "Boil") self.tabs.addTab(self.tabFerment, "Ferment") #vLayoutR.addLayout(self.vLayoutDisplayed) #vLayoutR.addWidget(self.tabs) rSplitter.addWidget(hDisplayedWidget) rSplitter.addWidget(self.tabs) # Main layout for whole window - splitter so widget sizes are adjustable mainLayout = QHBoxLayout() mainSplitter = QSplitter() mainSplitter.addWidget(lWidget) mainSplitter.addWidget(rSplitter) mainLayout.addWidget(mainSplitter) mainSplitter.setSizes([260, 740]) self.setLayout(mainLayout) #self.showFullScreen() self.setGeometry(0, 0, 1500, 1000) self.but_view.clicked.connect(self.viewButtonClicked) self.but_view.clicked.connect(self.viewButtonClickedTabs) self.but_quit.clicked.connect(self.quitButtonClicked) def quitButtonClicked(self): self.close() self.closeSignal.emit() # Slot for adding selected brew to widget def viewButtonClicked(self): self.brewInfo = [] # array to place brew info: ID, Recipe, Date self.displayNo = self.displayNo + 1 # Add brew info to array based on selected row index = (self.dataTable.selectionModel().currentIndex()) for i in range(3): self.brewInfo.append( QLabel(str(index.sibling(index.row(), i).data()))) # Choose colour to use for this displayed brew self.colourToUse = self.chooseColour() # Create group box with all brew info displayed and Remove button brewGroupBox = QGroupBox(str(self.displayNo)) brewGroupBox.setObjectName("ColouredGroupBox") brewGroupBox.setStyleSheet( "QGroupBox#ColouredGroupBox { border: 2px solid %s;}" % self.colourToUse) brewForm = QFormLayout() brewForm.addRow(QLabel('Brew ID:'), self.brewInfo[0]) brewForm.addRow(QLabel('Recipe:'), self.brewInfo[1]) brewForm.addRow(QLabel('Date:'), self.brewInfo[2]) removeButHLayout = QHBoxLayout() removeButHLayout.addStretch(1) self.but_Remove = QPushButton("Remove") removeButHLayout.addWidget(self.but_Remove) brewForm.addRow(removeButHLayout) brewGroupBox.setLayout(brewForm) # Add group box to layout - use insert so that stretch stays on right side self.hLayoutDisplayed.insertWidget(self.displayNo - 1, brewGroupBox) self.displayedBrewsH.append( brewGroupBox) # Add groupbox to array of displayed brews # Signal to connect remove brew button. Lambda function used to pass argument of specific # brew to be removed self.but_Remove.clicked.connect( lambda: self.removeBrewClickedMash(brewGroupBox)) self.but_Remove.clicked.connect( lambda: self.removeBrewClickedBoil(brewGroupBox)) self.but_Remove.clicked.connect( lambda: self.removeBrewClickedFerment(brewGroupBox)) self.but_Remove.clicked.connect( lambda: self.removeBrewClicked(brewGroupBox)) # Slot for adding brew info to each of the process tabs def viewButtonClickedTabs(self): batchID = self.brewInfo[0].text() # Query database to get recipe data for the brew selected to view # brewInfo[0].text() gives brew ID for selected brew from table sql = f"SELECT * FROM Brews WHERE id = '{self.brewInfo[0].text()}'" query = self.db.custom(sql) self.recipedata = {} self.recipedata['batchID'] = query[0][0] self.recipedata['recipeName'] = query[0][1] self.recipedata['recipeDate'] = query[0][2] self.recipedata['mashTemp'] = query[0][3] self.recipedata['mashTime'] = query[0][4] self.recipedata['boilTemp'] = query[0][5] self.recipedata['boilTime'] = query[0][6] self.recipedata['hop1'] = (query[0][7], query[0][8]) self.recipedata['hop2'] = (query[0][9], query[0][10]) self.recipedata['hop3'] = (query[0][11], query[0][12]) self.recipedata['hop4'] = (query[0][13], query[0][14]) self.recipedata['fermenttemp'] = query[0][15] # Create groupboxes for each of the process tabs to fill with brew info mashGroupBox = QGroupBox(str(self.displayNo)) mashGroupBox.setObjectName("MashColouredGroupBox") mashGroupBox.setStyleSheet( "QGroupBox#MashColouredGroupBox { border: 2px solid %s;}" % self.colourToUse) mashFormLayout = QFormLayout() mashFormLayout.addRow( QLabel(f"Temp ({DEGREES}C): {self.recipedata['mashTemp']}")) mashFormLayout.addRow( QLabel(f"Time (mins): {self.recipedata['mashTime']}")) mashGroupBox.setLayout(mashFormLayout) self.tabMash.mashVLayout.insertWidget(self.displayNo - 1, mashGroupBox) self.displayedBrewsVMash.append(mashGroupBox) boilGroupBox = QGroupBox(str(self.displayNo)) boilGroupBox.setObjectName("BoilColouredGroupBox") boilGroupBox.setStyleSheet( "QGroupBox#BoilColouredGroupBox { border: 2px solid %s;}" % self.colourToUse) boilFormLayout = QFormLayout() boilFormLayout.addRow( QLabel(f"Temp ({DEGREES}C):{self.recipedata['boilTemp']}")) boilFormLayout.addRow( QLabel(f"Time (mins): {self.recipedata['boilTime']}")) boilFormLayout.addRow(QLabel(f"Hop 1: {self.recipedata['hop1'][0]}")) boilFormLayout.addRow( QLabel(f"Time (mins): {self.recipedata['hop1'][1]}")) boilFormLayout.addRow(QLabel(f"Hop 2: {self.recipedata['hop2'][0]}")) boilFormLayout.addRow( QLabel(f"Time (mins): {self.recipedata['hop2'][1]}")) boilFormLayout.addRow(QLabel(f"Hop 3: {self.recipedata['hop3'][0]}")) boilFormLayout.addRow( QLabel(f"Time (mins): {self.recipedata['hop3'][1]}")) boilFormLayout.addRow(QLabel(f"Hop 4: {self.recipedata['hop4'][0]}")) boilFormLayout.addRow( QLabel(f"Time (mins): {self.recipedata['hop4'][1]}")) boilGroupBox.setLayout(boilFormLayout) self.tabBoil.boilVLayout.insertWidget(self.displayNo - 1, boilGroupBox) self.displayedBrewsVBoil.append(boilGroupBox) fermentGroupBox = QGroupBox(str(self.displayNo)) fermentGroupBox.setObjectName("FermentColouredGroupBox") fermentGroupBox.setStyleSheet( "QGroupBox#FermentColouredGroupBox { border: 2px solid %s;}" % self.colourToUse) fermentFormLayout = QFormLayout() fermentFormLayout.addRow( QLabel(f"Temp ({DEGREES}C): {self.recipedata['fermenttemp']}")) #fermentFormLayout.addRow(QLabel('Time (mins):')) fermentGroupBox.setLayout(fermentFormLayout) self.tabFerment.fermentVLayout.insertWidget(self.displayNo - 1, fermentGroupBox) self.displayedBrewsVFerment.append(fermentGroupBox) ### PUTTING DATA ONTO GRAPHS ### # Query database to get data to plot on graphs sqlMash = f"SELECT TimeStamp, Temp FROM Mash WHERE BatchID = '{batchID}'" sqlBoil = f"SELECT TimeStamp, Temp FROM BoilMonitor WHERE BatchID = '{batchID}'" sqlFermentTemp = f"SELECT TimeStamp, Temp FROM Ferment WHERE BatchID = '{batchID}'" sqlFermentSG = f"SELECT TimeStamp, Sg FROM Ferment WHERE BatchID = '{batchID}'" mashDataX, mashDataY = self.createData(sqlMash) boilDataX, boilDataY = self.createData(sqlBoil) fermentTempDataX, fermentTempDataY = self.createData(sqlFermentTemp) fermentSGDataX, fermentSGDataY = self.createData(sqlFermentSG) # Create and add curves to each of the plots self.tabMash.graph.createCurve(mashDataX, mashDataY, self.colourToUse) self.tabBoil.graph.createCurve(boilDataX, boilDataY, self.colourToUse) self.tabFerment.tempGraph.createCurve(fermentTempDataX[1:], fermentTempDataY[1:], self.colourToUse) self.tabFerment.gravGraph.createCurve(fermentSGDataX[1:], fermentSGDataY[1:], self.colourToUse) # Function to choose first available colour def chooseColour(self): # Loop through dictionary, checking if self.colours[j] appear for colours in self.colours: # If it does appear, continue to next colour if colours not in self.activeColours: # If it doesn't appear, add colour to dictionary and return colour self.activeColours.append(colours) return colours # Get data from database using sql query def createData(self, sql): timestamps = [] tempdat = [] try: for data in self.db.custom(sql): timestamps.append(data[0]) tempdat.append(data[1]) startTime = timestamps[0] for i in range(len(timestamps)): timestamps[i] = (timestamps[i] - startTime).seconds except IndexError: return [0], [0] return timestamps, tempdat # Slot for removing group boxes from horizontal tab def removeBrewClicked(self, brewToRemove): brewArrayPos = self.displayedBrewsH.index(brewToRemove) self.hLayoutDisplayed.removeWidget( brewToRemove) # remove widget from layout brewToRemove.setParent(None) # remove parent so widget dissappears self.displayNo = self.displayNo - 1 self.displayedBrewsH.remove( brewToRemove) # remove brew from array of displayed brews i = 0 # Loop to renumber the remaining displayed groupboxes using the array for i in range(len(self.displayedBrewsH)): self.displayedBrewsH[i].setTitle(str(i + 1)) del self.activeColours[brewArrayPos] # Slot for removing group boxes of brew info in mash tab def removeBrewClickedMash(self, brewToRemove): # Obtain position in array of displayed brews of brew to remove brewArrayPos = self.displayedBrewsH.index(brewToRemove) # Use position to remove widget from layout self.tabMash.mashVLayout.takeAt(brewArrayPos) # Use position to remove parent self.displayedBrewsVMash[brewArrayPos].setParent(None) # Use position to delete from vertical array del self.displayedBrewsVMash[brewArrayPos] # Renumber groupboxes in vertical display for i in range(len(self.displayedBrewsVMash)): self.displayedBrewsVMash[i].setTitle(str(i + 1)) # Remove curve from graph self.tabMash.graph.removeCurve(brewArrayPos) # Slot for removing group boxes of brew info in boil tab def removeBrewClickedBoil(self, brewToRemove): # Obtain position in array of displayed brews of brew to remove brewArrayPos = self.displayedBrewsH.index(brewToRemove) # Use position to remove widget from layout self.tabBoil.boilVLayout.takeAt(brewArrayPos) # Use position to remove parent self.displayedBrewsVBoil[brewArrayPos].setParent(None) # Use position to delete from vertical array del self.displayedBrewsVBoil[brewArrayPos] # Renumber groupboxes in vertical display for i in range(len(self.displayedBrewsVBoil)): self.displayedBrewsVBoil[i].setTitle(str(i + 1)) self.tabBoil.graph.removeCurve(brewArrayPos) # Slot for removing group boxes of brew info in ferment tab def removeBrewClickedFerment(self, brewToRemove): # Obtain position in array of displayed brews of brew to remove brewArrayPos = self.displayedBrewsH.index(brewToRemove) # Use position to remove widget from layout self.tabFerment.fermentVLayout.takeAt(brewArrayPos) # Use position to remove parent self.displayedBrewsVFerment[brewArrayPos].setParent(None) # Use position to delete from vertical array del self.displayedBrewsVFerment[brewArrayPos] # Renumber groupboxes in vertical display for i in range(len(self.displayedBrewsVFerment)): self.displayedBrewsVFerment[i].setTitle(str(i + 1)) self.tabFerment.tempGraph.removeCurve(brewArrayPos) self.tabFerment.gravGraph.removeCurve(brewArrayPos) # Slot for filtering by Batch IDdisplayed def filter_batchID(self): self.lineEdit_recipe.clear() self.proxyModel.setFilterRegExp(self.edit_batchID.text()) self.proxyModel.setFilterKeyColumn(0) # Slot for filtering by Recipe def filter_recipe(self): self.edit_batchID.clear() self.proxyModel.setFilterRegExp(self.lineEdit_recipe.text()) self.proxyModel.setFilterKeyColumn(1) # Slot for filtering by date def filter_date(self): self.lineEdit_recipe.clear() self.edit_batchID.clear() self.proxyModel.setFilterRegExp( self.dateEdit.date().toString("dd/MM/yy")) self.proxyModel.setFilterKeyColumn(2) # Slot for clearing all filters def clearFilters(self): self.dateEdit.setDate(self.maxDate) self.proxyModel.setFilterRegExp('') self.proxyModel.setFilterKeyColumn(0) self.proxyModel.setFilterKeyColumn(1) self.proxyModel.setFilterKeyColumn(2) self.lineEdit_recipe.clear() self.edit_batchID.clear()
class SetChartDetailPopup(QDialog): def __init__(self, table_id, *args, **kwargs): super(SetChartDetailPopup, self).__init__(*args, **kwargs) layout = QHBoxLayout(margin=2) # left_layout = QVBoxLayout() self.table_id = table_id self.table_data_frame = None # 表格数据的pandas Data Frame对象 # 图表参数设置的控件 self.chart_parameter = QWidget(parent=self) parameter_layout = QVBoxLayout(margin=0) parameter_layout.addWidget(QLabel('参数设置', objectName='widgetTip')) # 图表名称 chart_name_layout = QHBoxLayout() chart_name_layout.addWidget(QLabel('图表名称:', objectName='headTip')) self.chart_name = QLineEdit() chart_name_layout.addWidget(self.chart_name) parameter_layout.addLayout(chart_name_layout) # 图表类型 chart_category_layout = QHBoxLayout() chart_category_layout.addWidget(QLabel('图表类型:', objectName='headTip')) self.chart_category_combo = QComboBox() self.chart_category_combo.addItems([u'折线图', u'柱形图']) chart_category_layout.addWidget(self.chart_category_combo) chart_category_layout.addStretch() parameter_layout.addLayout(chart_category_layout) # 选择X轴 chart_xaxis_layout = QHBoxLayout() chart_xaxis_layout.addWidget(QLabel('X 轴列名:', objectName='headTip')) self.x_axis_combo = QComboBox(currentTextChanged=self.x_axis_changed) chart_xaxis_layout.addWidget(self.x_axis_combo) chart_xaxis_layout.addStretch() parameter_layout.addLayout(chart_xaxis_layout) # Y轴设置 parameter_layout.addWidget(QLabel('Y 轴列名:', objectName='headTip')) yaxis_layout = QHBoxLayout() left_yaxis_layout = QVBoxLayout() self.column_header_list = QListWidget() self.column_header_list.setMaximumWidth(180) left_yaxis_layout.addWidget(self.column_header_list) yaxis_layout.addLayout(left_yaxis_layout) # 中间按钮 middle_yasis_layout = QVBoxLayout() middle_yasis_layout.addWidget( QPushButton('左轴→', objectName='addAxis', clicked=self.add_y_left)) middle_yasis_layout.addWidget( QPushButton('右轴→', objectName='addAxis', clicked=self.add_y_right)) yaxis_layout.addLayout(middle_yasis_layout) # 右侧列头显示 right_yaxis_layout = QVBoxLayout() self.right_top_list = QListWidget( doubleClicked=self.remove_toplist_item) self.right_top_list.setMaximumWidth(180) right_yaxis_layout.addWidget(self.right_top_list) self.right_bottom_list = QListWidget( doubleClicked=self.remove_bottomlist_item) self.right_bottom_list.setMaximumWidth(180) right_yaxis_layout.addWidget(self.right_bottom_list) yaxis_layout.addLayout(right_yaxis_layout) parameter_layout.addLayout(yaxis_layout) # 轴名称设置 parameter_layout.addWidget(QLabel('轴名称设置:', objectName='headTip'), alignment=Qt.AlignLeft) # x轴 bottom_xaxis_name_layout = QHBoxLayout() bottom_xaxis_name_layout.addWidget(QLabel('X 轴:')) self.bottom_x_label_edit = QLineEdit(placeholderText='请输入轴名称') bottom_xaxis_name_layout.addWidget(self.bottom_x_label_edit) parameter_layout.addLayout(bottom_xaxis_name_layout) # Y轴 yaxis_name_layout = QHBoxLayout() yaxis_name_layout.addWidget(QLabel('左轴:')) self.left_y_label_edit = QLineEdit(placeholderText='请输入左轴名称') yaxis_name_layout.addWidget(self.left_y_label_edit) yaxis_name_layout.addWidget(QLabel('右轴:')) self.right_y_label_edit = QLineEdit(placeholderText='请输入右轴名称') yaxis_name_layout.addWidget(self.right_y_label_edit) parameter_layout.addLayout(yaxis_name_layout) # 数据范围 parameter_layout.addWidget(QLabel('数据范围设置:', objectName='headTip'), alignment=Qt.AlignLeft) chart_scope_layout1 = QHBoxLayout() chart_scope_layout1.addWidget(QLabel('起始日期:')) self.scope_start_date = QDateEdit() self.scope_start_date.setCalendarPopup(True) self.scope_start_date.setEnabled(False) chart_scope_layout1.addWidget(self.scope_start_date) chart_scope_layout1.addWidget(QLabel('截止日期:')) self.scope_end_date = QDateEdit() self.scope_end_date.setCalendarPopup(True) self.scope_end_date.setEnabled(False) chart_scope_layout1.addWidget(self.scope_end_date) parameter_layout.addLayout(chart_scope_layout1) parameter_layout.addWidget(QPushButton( '画图预览', clicked=self.review_chart_clicked), alignment=Qt.AlignRight) self.chart_parameter.setMaximumWidth(350) self.chart_parameter.setLayout(parameter_layout) # 参数设置控件加入布局 layout.addWidget(self.chart_parameter) # 预览控件 self.review_widget = QWidget(parent=self) review_layout = QVBoxLayout(margin=0) review_layout.addWidget(QLabel('图表预览', objectName='widgetTip')) self.review_chart = QChartView() self.review_chart.setRenderHint(QPainter.Antialiasing) review_layout.addWidget(self.review_chart) # # 图例显示区 # self.legend_view = QWidget(parent=self.review_widget) # legend_layout = QGridLayout() # self.legend_view.setLayout(legend_layout) # review_layout.addWidget(self.legend_view) # 确认设置 commit_layout = QHBoxLayout() commit_layout.addStretch() self.current_start = QCheckBox('当前起始') commit_layout.addWidget(self.current_start) self.current_end = QCheckBox('当前截止') commit_layout.addWidget(self.current_end) commit_layout.addWidget( QPushButton('确认设置', clicked=self.commit_add_chart)) review_layout.addLayout(commit_layout) # 表详情数据显示 self.detail_trend_table = QTableWidget() self.detail_trend_table.setMaximumHeight(200) review_layout.addWidget(self.detail_trend_table) self.review_widget.setLayout(review_layout) layout.addWidget(self.review_widget) self.setLayout(layout) self.setMinimumWidth(950) self.setMaximumHeight(550) self.has_review_chart = False self.setStyleSheet(""" #widgetTip{ color: rgb(50,80,180); font-weight:bold } #headTip{ font-weight:bold } #addAxis{ max-width:40px } """) # x轴选择改变 def x_axis_changed(self): self.column_header_list.clear() for header_index in range( self.detail_trend_table.horizontalHeader().count()): text = self.detail_trend_table.horizontalHeaderItem( header_index).text() if text == self.x_axis_combo.currentText(): continue self.column_header_list.addItem(text) # 清空左轴和右轴的设置 self.right_top_list.clear() self.right_bottom_list.clear() # 移除当前列表中的item def remove_toplist_item(self, index): row = self.right_top_list.currentRow() self.right_top_list.takeItem(row) def remove_bottomlist_item(self, index): row = self.right_bottom_list.currentRow() self.right_bottom_list.takeItem(row) # 加入左轴 def add_y_left(self): text_in = list() for i in range(self.right_top_list.count()): text_in.append(self.right_top_list.item(i).text()) item = self.column_header_list.currentItem() # 获取item if item is not None: if item.text() not in text_in: self.right_top_list.addItem(item.text()) # 加入右轴 def add_y_right(self): text_in = list() for i in range(self.right_bottom_list.count()): text_in.append(self.right_bottom_list.item(i).text()) item = self.column_header_list.currentItem() # 获取item if item is not None: if item.text() not in text_in: self.right_bottom_list.addItem(item.text()) # 预览数据 def review_chart_clicked(self): try: chart_name = self.chart_name.text() chart_category = self.chart_category_combo.currentText() # 根据设置从表格中获取画图源数据 x_axis = self.x_axis_combo.currentText() # x轴 left_y_axis = [ self.right_top_list.item(i).text() for i in range(self.right_top_list.count()) ] right_y_axis = [ self.right_bottom_list.item(i).text() for i in range(self.right_bottom_list.count()) ] # 根据表头将这些列名称换为索引 x_axis_col = list() left_y_cols = list() right_y_cols = list() header_data = list() for header_index in range( self.detail_trend_table.horizontalHeader().count()): text = self.detail_trend_table.horizontalHeaderItem( header_index).text() header_data.append(text) if text == x_axis: x_axis_col.append(header_index) for y_left in left_y_axis: if y_left == text: left_y_cols.append(header_index) for y_right in right_y_axis: if y_right == text: right_y_cols.append(header_index) # 判断是否选择了左轴 if not left_y_cols: popup = InformationPopup(message='请至少选择一列左轴数据。', parent=self) if not popup.exec_(): popup.deleteLater() del popup return # 根据设置画图 start_date = self.scope_start_date.date().toString('yyyy-MM-dd') start_date = pd.to_datetime(start_date) end_date = self.scope_end_date.date().toString('yyyy-MM-dd') end_date = pd.to_datetime(end_date) df = self.table_data_frame.copy() final_df = df.loc[(df[0] >= start_date) & (df[0] <= end_date)].copy() # 根据时间范围取数 # 根据类型进行画图 if chart_category == u'折线图': # 折线图 chart = lines_stacked(name=chart_name, table_df=final_df, x_bottom_cols=x_axis_col, y_left_cols=left_y_cols, y_right_cols=right_y_cols, legend_labels=header_data, tick_count=12) # 设置图例 # chart.legend().hide() # markers = chart.legend().markers() # print(markers) # row_index = 0 # col_index = 0 # for marker in chart.legend().markers(): # print(marker.series().name()) # # from PyQt5.QtChart import QLineSeries # # QLineSeries.name() # # 每条线设置一个label # legend_label = QLabel(marker.series().name()) # self.legend_view.layout().addWidget(legend_label, row_index, col_index) # col_index += 1 # if col_index >= 3: # row_index += 1 # col_index = 0 elif chart_category == u'柱形图': chart = bars_stacked(name=chart_name, table_df=final_df, x_bottom_cols=x_axis_col, y_left_cols=left_y_cols, y_right_cols=right_y_cols, legend_labels=header_data, tick_count=12) else: popup = InformationPopup(message='当前设置不适合作图或系统暂不支持作图。', parent=self) if not popup.exec_(): popup.deleteLater() del popup return self.review_chart.setChart(chart) self.has_review_chart = True except Exception as e: popup = InformationPopup(message=str(e), parent=self) if not popup.exec_(): popup.deleteLater() del popup # 确认添加本张图表 def commit_add_chart(self): if not self.has_review_chart: info = InformationPopup(message='请先预览图表,再进行设置!', parent=self) if not info.exec_(): info.deleteLater() del info return category_dict = { '折线图': 'line', '柱形图': 'bar', } chart_name = re.sub(r'\s+', '', self.chart_name.text()) category = category_dict.get(self.chart_category_combo.currentText(), None) if not all([chart_name, category]): info = InformationPopup(message='请设置图表名称和图表类型!', parent=self) if not info.exec_(): info.deleteLater() del info return # 根据设置从表格中获取数据把选择的列头变为索引 x_axis = self.x_axis_combo.currentText() # x轴 left_y_axis = [ self.right_top_list.item(i).text() for i in range(self.right_top_list.count()) ] right_y_axis = [ self.right_bottom_list.item(i).text() for i in range(self.right_bottom_list.count()) ] # 根据表头将这些列名称换为索引 x_axis_cols = list() left_y_cols = list() right_y_cols = list() for header_index in range( self.detail_trend_table.horizontalHeader().count()): text = self.detail_trend_table.horizontalHeaderItem( header_index).text() if text == x_axis: x_axis_cols.append(header_index) for y_left in left_y_axis: if y_left == text: left_y_cols.append(header_index) for y_right in right_y_axis: if y_right == text: right_y_cols.append(header_index) if not x_axis_cols: info = InformationPopup(message='请设置图表X轴!', parent=self) if not info.exec_(): info.deleteLater() del info return if not left_y_cols: info = InformationPopup(message='至少左轴要有一列数据!', parent=self) if not info.exec_(): info.deleteLater() del info return # 获取轴名称 x_bottom_labels = re.split(r';', self.bottom_x_label_edit.text()) y_left_labels = re.split(r';', self.left_y_label_edit.text()) y_right_labels = re.split(r';', self.right_y_label_edit.text()) chart_params = dict() chart_params['table_id'] = self.table_id chart_params['name'] = chart_name chart_params['category'] = category chart_params['x_bottom'] = x_axis_cols chart_params['x_bottom_label'] = x_bottom_labels chart_params['x_top'] = [] chart_params['x_top_label'] = [] chart_params['y_left'] = left_y_cols chart_params['y_left_label'] = y_left_labels chart_params['y_right'] = right_y_cols chart_params['y_right_label'] = y_right_labels chart_params['is_top'] = False if self.current_start.isChecked(): # print('设置当前起始范围') chart_params['start'] = self.scope_start_date.date().toString( 'yyyy-MM-dd') if self.current_end.isChecked(): # print('设置当前截止') chart_params['end'] = self.scope_end_date.date().toString( 'yyyy-MM-dd') # print(chart_params) # 上传数据 try: r = requests.post(url=settings.SERVER_ADDR + 'trend/chart/?mc=' + settings.app_dawn.value('machine'), headers={ 'AUTHORIZATION': settings.app_dawn.value('AUTHORIZATION') }, data=json.dumps(chart_params)) response = json.loads(r.content.decode('utf-8')) if r.status_code != 201: raise ValueError(response['message']) message = response['message'] except Exception as e: message = str(e) info = InformationPopup(message=message, parent=self) if not info.exec_(): info.deleteLater() del info # 获取当前表的数据(预用来设置显示图的数据) def getCurrentTrendTable(self): try: r = requests.get(url=settings.SERVER_ADDR + 'trend/table/' + str(self.table_id) + '/?look=1&mc=' + settings.app_dawn.value('machine')) response = json.loads(r.content.decode('utf-8')) if r.status_code != 200: raise ValueError(response['message']) except Exception: pass else: column_headers = response['data']['header_data'] column_headers.pop(0) self.x_axis_combo.addItems(column_headers) # X轴选择 for text in column_headers: if text in self.x_axis_combo.currentText(): continue self.column_header_list.addItem(text) # 列头待选表 # pandas处理数据 self.table_data_frame = self.pd_handler_data( response['data']['table_data']) # 填充表格 self.showTableData(column_headers, self.table_data_frame) # pandas 处理数据 def pd_handler_data(self, table_data): # 转为DF table_df = pd.DataFrame(table_data) table_df.drop(columns=[0], inplace=True) # 删除id列 table_df.columns = [i for i in range(table_df.shape[1])] # 重置列索引 table_df[0] = pd.to_datetime(table_df[0]) # 第一列转为时间类型 table_df.sort_values(by=0, inplace=True) # 根据时间排序数据 # 计算数据时间跨度大小显示在范围上 min_x, max_x = table_df[0].min(), table_df[0].max( ) # 第一列时间数据(x轴)的最大值和最小值 self.scope_start_date.setDateRange(QDate(min_x), QDate(max_x)) self.scope_end_date.setDateRange(QDate(min_x), QDate(max_x)) self.scope_start_date.setEnabled(True) self.scope_end_date.setEnabled(True) self.scope_end_date.setDate(self.scope_end_date.maximumDate()) return table_df # 设置表格显示表数据内容 def showTableData(self, headers, table_df): # 设置行列 self.detail_trend_table.setRowCount(table_df.shape[0]) col_count = len(headers) self.detail_trend_table.setColumnCount(col_count) self.detail_trend_table.setHorizontalHeaderLabels(headers) self.detail_trend_table.horizontalHeader().setSectionResizeMode( QHeaderView.ResizeToContents) for row, row_content in enumerate(table_df.values.tolist()): for col, value in enumerate(row_content): if col == 0: # 时间类 value = value.strftime('%Y-%m-%d') item = QTableWidgetItem(value) item.setTextAlignment(Qt.AlignCenter) self.detail_trend_table.setItem(row, col, item)
class DateCreatorWindow(QDialog): """ Dialog window for creation / editing date. """ def __init__(self, parent: QWidget = None): super().__init__(parent) self._date = None self._date_delta = 7 self._date_start_temp = QDate.currentDate() # window settings self.setWindowTitle(self.tr("Date creator")) # toggle and status self.check_box = QCheckBox(self.tr("Range date")) # date layout self.layout_date_edit = QFormLayout() # simple date layout self.label_simple_date = QLabel(self.tr("Date")) self.layout_date_edit.setWidget(0, QFormLayout.LabelRole, self.label_simple_date) self.date_edit_simple = QDateEdit() self.layout_date_edit.setWidget(0, QFormLayout.FieldRole, self.date_edit_simple) self.date_edit_simple.setCalendarPopup(True) self.date_edit_simple.setDisplayFormat("dd.MM.yyyy") self.date_edit_simple.setDate(QDate.currentDate()) self.date_edit_simple.setDateRange(QDate.currentDate().addDays(-365), QDate.currentDate().addDays(365)) # range date layout self.label_date_start = QLabel(self.tr("Start")) self.layout_date_edit.setWidget(1, QFormLayout.LabelRole, self.label_date_start) self.date_edit_start = QDateEdit() self.layout_date_edit.setWidget(1, QFormLayout.FieldRole, self.date_edit_start) self.label_date_end = QLabel(self.tr("End")) self.layout_date_edit.setWidget(2, QFormLayout.LabelRole, self.label_date_end) self.date_edit_end = QDateEdit() self.layout_date_edit.setWidget(2, QFormLayout.FieldRole, self.date_edit_end) self.label_date_frequency = QLabel(self.tr("Frequency")) self.layout_date_edit.setWidget(3, QFormLayout.LabelRole, self.label_date_frequency) self.combo_box_frequency = QComboBox() self.layout_date_edit.setWidget(3, QFormLayout.FieldRole, self.combo_box_frequency) self.date_edit_start.setCalendarPopup(True) self.date_edit_start.setDisplayFormat("dd.MM.yyyy") self.date_edit_start.setDate(QDate.currentDate()) self.date_edit_start.setDateRange(QDate.currentDate().addDays(-365), QDate.currentDate().addDays(365)) self.date_edit_end.setCalendarPopup(True) self.date_edit_end.setDisplayFormat("dd.MM.yyyy") self.date_edit_end.setDate(QDate.currentDate().addDays( self._date_delta)) self.date_edit_end.setDateRange( QDate.currentDate().addDays(self._date_delta), QDate.currentDate().addDays(365)) self.combo_box_frequency.addItem(str(FrequencyDate.Every), FrequencyDate.Every) self.combo_box_frequency.addItem(str(FrequencyDate.Throughout), FrequencyDate.Throughout) # navigate self.layout_navigate = QHBoxLayout() self.layout_navigate.addStretch(1) self.push_button_ok = QPushButton(self.tr("OK")) self.layout_navigate.addWidget(self.push_button_ok) self.push_button_apply = QPushButton(self.tr("Apply")) self.layout_navigate.addWidget(self.push_button_apply) self.push_button_cancel = QPushButton(self.tr("Cancel")) self.layout_navigate.addWidget(self.push_button_cancel) # layout setup self.layout_main = QVBoxLayout() self.layout_main.setAlignment(Qt.AlignCenter) self.layout_main.addWidget(self.check_box) self.layout_main.addLayout(self.layout_date_edit) self.layout_main.addStretch(1) self.layout_main.addLayout(self.layout_navigate) self.setLayout(self.layout_main) # connection self.check_box.clicked.connect(self.check_box_clicked) self.date_edit_start.dateChanged.connect(self.date_edit_start_change) self.date_edit_end.dateChanged.connect(self.date_range_validation) self.combo_box_frequency.currentIndexChanged.connect( self.combo_box_frequency_changed) self.push_button_ok.clicked.connect(self.push_button_ok_clicked) self.push_button_apply.clicked.connect(self.push_button_apply_clicked) self.push_button_cancel.clicked.connect( self.push_button_cancel_clicked) self.show_simple_date() def set_date(self, date_item) -> None: """ Sets the date for editing. :param date_item: Set date """ if isinstance(date_item, DateItem): self.show_simple_date() self.date_edit_simple.setDate( QDate.fromString(date_item.date, "yyyy.MM.dd")) self._date = date_item if isinstance(date_item, DateRange): self.check_box.setChecked(True) self.show_range_date() self.date_edit_start.setDate( QDate.fromString(date_item.date_from, "yyyy.MM.dd")) self.date_edit_end.setDate( QDate.fromString(date_item.date_to, "yyyy.MM.dd")) self.combo_box_frequency.setCurrentText(str(date_item.frequency)) self._date = date_item def get_date(self) -> (DateItem, DateRange, None): """ Returns the created date. """ return self._date def show_simple_date(self) -> None: """ Switches the window to simple date editing mode. """ self.label_simple_date.setVisible(True) self.date_edit_simple.setVisible(True) self.label_date_start.setVisible(False) self.date_edit_start.setVisible(False) self.label_date_end.setVisible(False) self.date_edit_end.setVisible(False) self.label_date_frequency.setVisible(False) self.combo_box_frequency.setVisible(False) def show_range_date(self) -> None: """ Switches the window to range date editing mode. """ self.label_date_start.setVisible(True) self.date_edit_start.setVisible(True) self.label_date_end.setVisible(True) self.date_edit_end.setVisible(True) self.label_date_frequency.setVisible(True) self.combo_box_frequency.setVisible(True) self.label_simple_date.setVisible(False) self.date_edit_simple.setVisible(False) def date_edit_start_change(self, date: QDate) -> None: """ Slot for changing the end of a range of dates. :param date: Start of the date range """ end_date = self.date_edit_end.date().addDays( self._date_start_temp.daysTo(date)) self.date_edit_end.setDateRange(date.addDays(self._date_delta), date.addDays(365)) self.date_edit_end.setDate(end_date) self._date_start_temp = QDate(date) def combo_box_frequency_changed(self, index: int) -> None: """ Slot for frequency combo box. :param index: Current index """ if index == 0: self._date_delta = 7 else: self._date_delta = 14 self.date_edit_end.setDateRange( self.date_edit_start.date().addDays(self._date_delta), self.date_edit_start.date().addDays(365)) self.date_range_validation() def date_range_validation(self) -> None: """ Checks the correctness of the entered dates. """ if self.date_edit_start.date().dayOfWeek() == self.date_edit_end.date( ).dayOfWeek(): if self.date_edit_start.date().daysTo( self.date_edit_end.date()) % self._date_delta == 0: msg = "" else: msg = self.tr("The number of days between " "dates is not a multiple of {}").format( self._date_delta) else: msg = self.tr("Different days of the week at dates") if msg == "": self.push_button_ok.setEnabled(True) self.push_button_apply.setEnabled(True) else: self.push_button_ok.setEnabled(False) self.push_button_apply.setEnabled(False) self.date_edit_start.setToolTip(msg) self.date_edit_end.setToolTip(msg) def check_box_clicked(self, value: bool) -> None: """ Slot for check box. :param value: Check box status """ if value is False: # simple date self.show_simple_date() else: # range date self.show_range_date() def push_button_ok_clicked(self) -> None: """ Slot for ok button. """ if self.push_button_apply_clicked(): self.close() def push_button_apply_clicked(self) -> bool: """ Slot for apply button. """ try: if self.check_box.isChecked() is False: # simple date self._date = DateItem( self.date_edit_simple.date().toString("yyyy.MM.dd")) else: # range date self._date = DateRange( self.date_edit_start.date().toString("yyyy.MM.dd"), self.date_edit_end.date().toString("yyyy.MM.dd"), self.combo_box_frequency.currentData(Qt.UserRole)) return True except InvalidDatePair as pair_ex: QMessageBox.warning(self, self.tr("Date error"), str(pair_ex)) except Exception as ex: QMessageBox.critical(self, self.tr("Unknown error"), str(ex)) return False def push_button_cancel_clicked(self) -> None: """ Slot for cancel button. """ self._date = None self.close()
class Window(QWidget): def __init__(self): super(Window, self).__init__() self.createPreviewGroupBox() self.createGeneralOptionsGroupBox() self.createDatesGroupBox() self.createTextFormatsGroupBox() layout = QGridLayout() layout.addWidget(self.previewGroupBox, 0, 0) layout.addWidget(self.generalOptionsGroupBox, 0, 1) layout.addWidget(self.datesGroupBox, 1, 0) layout.addWidget(self.textFormatsGroupBox, 1, 1) layout.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(layout) self.previewLayout.setRowMinimumHeight(0, self.calendar.sizeHint().height()) self.previewLayout.setColumnMinimumWidth(0, self.calendar.sizeHint().width()) self.setWindowTitle("Calendar Widget") def localeChanged(self, index): self.calendar.setLocale(self.localeCombo.itemData(index)) def firstDayChanged(self, index): self.calendar.setFirstDayOfWeek( Qt.DayOfWeek(self.firstDayCombo.itemData(index))) def selectionModeChanged(self, index): self.calendar.setSelectionMode( QCalendarWidget.SelectionMode( self.selectionModeCombo.itemData(index))) def horizontalHeaderChanged(self, index): self.calendar.setHorizontalHeaderFormat( QCalendarWidget.HorizontalHeaderFormat( self.horizontalHeaderCombo.itemData(index))) def verticalHeaderChanged(self, index): self.calendar.setVerticalHeaderFormat( QCalendarWidget.VerticalHeaderFormat( self.verticalHeaderCombo.itemData(index))) def selectedDateChanged(self): self.currentDateEdit.setDate(self.calendar.selectedDate()) def minimumDateChanged(self, date): self.calendar.setMinimumDate(date) self.maximumDateEdit.setDate(self.calendar.maximumDate()) def maximumDateChanged(self, date): self.calendar.setMaximumDate(date) self.minimumDateEdit.setDate(self.calendar.minimumDate()) def weekdayFormatChanged(self): format = QTextCharFormat() format.setForeground( Qt.GlobalColor( self.weekdayColorCombo.itemData( self.weekdayColorCombo.currentIndex()))) self.calendar.setWeekdayTextFormat(Qt.Monday, format) self.calendar.setWeekdayTextFormat(Qt.Tuesday, format) self.calendar.setWeekdayTextFormat(Qt.Wednesday, format) self.calendar.setWeekdayTextFormat(Qt.Thursday, format) self.calendar.setWeekdayTextFormat(Qt.Friday, format) def weekendFormatChanged(self): format = QTextCharFormat() format.setForeground( Qt.GlobalColor( self.weekendColorCombo.itemData( self.weekendColorCombo.currentIndex()))) self.calendar.setWeekdayTextFormat(Qt.Saturday, format) self.calendar.setWeekdayTextFormat(Qt.Sunday, format) def reformatHeaders(self): text = self.headerTextFormatCombo.currentText() format = QTextCharFormat() if text == "Bold": format.setFontWeight(QFont.Bold) elif text == "Italic": format.setFontItalic(True) elif text == "Green": format.setForeground(Qt.green) self.calendar.setHeaderTextFormat(format) def reformatCalendarPage(self): if self.firstFridayCheckBox.isChecked(): firstFriday = QDate(self.calendar.yearShown(), self.calendar.monthShown(), 1) while firstFriday.dayOfWeek() != Qt.Friday: firstFriday = firstFriday.addDays(1) firstFridayFormat = QTextCharFormat() firstFridayFormat.setForeground(Qt.blue) self.calendar.setDateTextFormat(firstFriday, firstFridayFormat) # May 1st in Red takes precedence. if self.mayFirstCheckBox.isChecked(): mayFirst = QDate(self.calendar.yearShown(), 5, 1) mayFirstFormat = QTextCharFormat() mayFirstFormat.setForeground(Qt.red) self.calendar.setDateTextFormat(mayFirst, mayFirstFormat) def createPreviewGroupBox(self): self.previewGroupBox = QGroupBox("Preview") self.calendar = QCalendarWidget() self.calendar.setMinimumDate(QDate(1900, 1, 1)) self.calendar.setMaximumDate(QDate(3000, 1, 1)) self.calendar.setGridVisible(True) self.calendar.currentPageChanged.connect(self.reformatCalendarPage) self.previewLayout = QGridLayout() self.previewLayout.addWidget(self.calendar, 0, 0, Qt.AlignCenter) self.previewGroupBox.setLayout(self.previewLayout) def createGeneralOptionsGroupBox(self): self.generalOptionsGroupBox = QGroupBox("General Options") self.localeCombo = QComboBox() curLocaleIndex = -1 index = 0 this_language = self.locale().nativeLanguageName() this_country = self.locale().nativeCountryName() for locale in QLocale.matchingLocales(QLocale.AnyLanguage, QLocale.AnyScript, QLocale.AnyCountry): language = locale.nativeLanguageName() country = locale.nativeCountryName() if language == this_language and country == this_country: curLocaleIndex = index self.localeCombo.addItem('%s/%s' % (language, country), locale) index += 1 if curLocaleIndex != -1: self.localeCombo.setCurrentIndex(curLocaleIndex) self.localeLabel = QLabel("&Locale") self.localeLabel.setBuddy(self.localeCombo) self.firstDayCombo = QComboBox() self.firstDayCombo.addItem("Sunday", Qt.Sunday) self.firstDayCombo.addItem("Monday", Qt.Monday) self.firstDayCombo.addItem("Tuesday", Qt.Tuesday) self.firstDayCombo.addItem("Wednesday", Qt.Wednesday) self.firstDayCombo.addItem("Thursday", Qt.Thursday) self.firstDayCombo.addItem("Friday", Qt.Friday) self.firstDayCombo.addItem("Saturday", Qt.Saturday) self.firstDayLabel = QLabel("Wee&k starts on:") self.firstDayLabel.setBuddy(self.firstDayCombo) self.selectionModeCombo = QComboBox() self.selectionModeCombo.addItem("Single selection", QCalendarWidget.SingleSelection) self.selectionModeCombo.addItem("None", QCalendarWidget.NoSelection) self.selectionModeLabel = QLabel("&Selection mode:") self.selectionModeLabel.setBuddy(self.selectionModeCombo) self.gridCheckBox = QCheckBox("&Grid") self.gridCheckBox.setChecked(self.calendar.isGridVisible()) self.navigationCheckBox = QCheckBox("&Navigation bar") self.navigationCheckBox.setChecked(True) self.horizontalHeaderCombo = QComboBox() self.horizontalHeaderCombo.addItem("Single letter day names", QCalendarWidget.SingleLetterDayNames) self.horizontalHeaderCombo.addItem("Short day names", QCalendarWidget.ShortDayNames) self.horizontalHeaderCombo.addItem("Long day names", QCalendarWidget.LongDayNames) self.horizontalHeaderCombo.addItem("None", QCalendarWidget.NoHorizontalHeader) self.horizontalHeaderCombo.setCurrentIndex(1) self.horizontalHeaderLabel = QLabel("&Horizontal header:") self.horizontalHeaderLabel.setBuddy(self.horizontalHeaderCombo) self.verticalHeaderCombo = QComboBox() self.verticalHeaderCombo.addItem("ISO week numbers", QCalendarWidget.ISOWeekNumbers) self.verticalHeaderCombo.addItem("None", QCalendarWidget.NoVerticalHeader) self.verticalHeaderLabel = QLabel("&Vertical header:") self.verticalHeaderLabel.setBuddy(self.verticalHeaderCombo) self.localeCombo.currentIndexChanged.connect(self.localeChanged) self.firstDayCombo.currentIndexChanged.connect(self.firstDayChanged) self.selectionModeCombo.currentIndexChanged.connect( self.selectionModeChanged) self.gridCheckBox.toggled.connect(self.calendar.setGridVisible) self.navigationCheckBox.toggled.connect( self.calendar.setNavigationBarVisible) self.horizontalHeaderCombo.currentIndexChanged.connect( self.horizontalHeaderChanged) self.verticalHeaderCombo.currentIndexChanged.connect( self.verticalHeaderChanged) checkBoxLayout = QHBoxLayout() checkBoxLayout.addWidget(self.gridCheckBox) checkBoxLayout.addStretch() checkBoxLayout.addWidget(self.navigationCheckBox) outerLayout = QGridLayout() outerLayout.addWidget(self.localeLabel, 0, 0) outerLayout.addWidget(self.localeCombo, 0, 1) outerLayout.addWidget(self.firstDayLabel, 1, 0) outerLayout.addWidget(self.firstDayCombo, 1, 1) outerLayout.addWidget(self.selectionModeLabel, 2, 0) outerLayout.addWidget(self.selectionModeCombo, 2, 1) outerLayout.addLayout(checkBoxLayout, 3, 0, 1, 2) outerLayout.addWidget(self.horizontalHeaderLabel, 4, 0) outerLayout.addWidget(self.horizontalHeaderCombo, 4, 1) outerLayout.addWidget(self.verticalHeaderLabel, 5, 0) outerLayout.addWidget(self.verticalHeaderCombo, 5, 1) self.generalOptionsGroupBox.setLayout(outerLayout) self.firstDayChanged(self.firstDayCombo.currentIndex()) self.selectionModeChanged(self.selectionModeCombo.currentIndex()) self.horizontalHeaderChanged(self.horizontalHeaderCombo.currentIndex()) self.verticalHeaderChanged(self.verticalHeaderCombo.currentIndex()) def createDatesGroupBox(self): self.datesGroupBox = QGroupBox(self.tr("Dates")) self.minimumDateEdit = QDateEdit() self.minimumDateEdit.setDisplayFormat('MMM d yyyy') self.minimumDateEdit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.minimumDateEdit.setDate(self.calendar.minimumDate()) self.minimumDateLabel = QLabel("&Minimum Date:") self.minimumDateLabel.setBuddy(self.minimumDateEdit) self.currentDateEdit = QDateEdit() self.currentDateEdit.setDisplayFormat('MMM d yyyy') self.currentDateEdit.setDate(self.calendar.selectedDate()) self.currentDateEdit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.currentDateLabel = QLabel("&Current Date:") self.currentDateLabel.setBuddy(self.currentDateEdit) self.maximumDateEdit = QDateEdit() self.maximumDateEdit.setDisplayFormat('MMM d yyyy') self.maximumDateEdit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.maximumDateEdit.setDate(self.calendar.maximumDate()) self.maximumDateLabel = QLabel("Ma&ximum Date:") self.maximumDateLabel.setBuddy(self.maximumDateEdit) self.currentDateEdit.dateChanged.connect(self.calendar.setSelectedDate) self.calendar.selectionChanged.connect(self.selectedDateChanged) self.minimumDateEdit.dateChanged.connect(self.minimumDateChanged) self.maximumDateEdit.dateChanged.connect(self.maximumDateChanged) dateBoxLayout = QGridLayout() dateBoxLayout.addWidget(self.currentDateLabel, 1, 0) dateBoxLayout.addWidget(self.currentDateEdit, 1, 1) dateBoxLayout.addWidget(self.minimumDateLabel, 0, 0) dateBoxLayout.addWidget(self.minimumDateEdit, 0, 1) dateBoxLayout.addWidget(self.maximumDateLabel, 2, 0) dateBoxLayout.addWidget(self.maximumDateEdit, 2, 1) dateBoxLayout.setRowStretch(3, 1) self.datesGroupBox.setLayout(dateBoxLayout) def createTextFormatsGroupBox(self): self.textFormatsGroupBox = QGroupBox("Text Formats") self.weekdayColorCombo = self.createColorComboBox() self.weekdayColorCombo.setCurrentIndex( self.weekdayColorCombo.findText("Black")) self.weekdayColorLabel = QLabel("&Weekday color:") self.weekdayColorLabel.setBuddy(self.weekdayColorCombo) self.weekendColorCombo = self.createColorComboBox() self.weekendColorCombo.setCurrentIndex( self.weekendColorCombo.findText("Red")) self.weekendColorLabel = QLabel("Week&end color:") self.weekendColorLabel.setBuddy(self.weekendColorCombo) self.headerTextFormatCombo = QComboBox() self.headerTextFormatCombo.addItem("Bold") self.headerTextFormatCombo.addItem("Italic") self.headerTextFormatCombo.addItem("Plain") self.headerTextFormatLabel = QLabel("&Header text:") self.headerTextFormatLabel.setBuddy(self.headerTextFormatCombo) self.firstFridayCheckBox = QCheckBox("&First Friday in blue") self.mayFirstCheckBox = QCheckBox("May &1 in red") self.weekdayColorCombo.currentIndexChanged.connect( self.weekdayFormatChanged) self.weekendColorCombo.currentIndexChanged.connect( self.weekendFormatChanged) self.headerTextFormatCombo.currentIndexChanged.connect( self.reformatHeaders) self.firstFridayCheckBox.toggled.connect(self.reformatCalendarPage) self.mayFirstCheckBox.toggled.connect(self.reformatCalendarPage) checkBoxLayout = QHBoxLayout() checkBoxLayout.addWidget(self.firstFridayCheckBox) checkBoxLayout.addStretch() checkBoxLayout.addWidget(self.mayFirstCheckBox) outerLayout = QGridLayout() outerLayout.addWidget(self.weekdayColorLabel, 0, 0) outerLayout.addWidget(self.weekdayColorCombo, 0, 1) outerLayout.addWidget(self.weekendColorLabel, 1, 0) outerLayout.addWidget(self.weekendColorCombo, 1, 1) outerLayout.addWidget(self.headerTextFormatLabel, 2, 0) outerLayout.addWidget(self.headerTextFormatCombo, 2, 1) outerLayout.addLayout(checkBoxLayout, 3, 0, 1, 2) self.textFormatsGroupBox.setLayout(outerLayout) self.weekdayFormatChanged() self.weekendFormatChanged() self.reformatHeaders() self.reformatCalendarPage() def createColorComboBox(self): comboBox = QComboBox() comboBox.addItem("Red", Qt.red) comboBox.addItem("Blue", Qt.blue) comboBox.addItem("Black", Qt.black) comboBox.addItem("Magenta", Qt.magenta) return comboBox
class Window(QWidget): def __init__(self): super(Window, self).__init__() self.setWindowTitle("Query Cocorahs") self.initUI() def initUI(self): self.createPreviewGroupBox() self.createDatesGroupBox() self.infoPanel() layout = QGridLayout() # layout.addWidget(self.previewGroupBox, 0, 0) layout.addWidget(self.datesGroupBox, 0, 1) layout.addWidget(self.infoPanelBox, 0, 2, 0, 1) layout.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(layout) self.previewLayout.setRowMinimumHeight(0, self.calendar.sizeHint().height()) self.previewLayout.setColumnMinimumWidth(0, self.calendar.sizeHint().width()) def createPreviewGroupBox(self): self.previewGroupBox = QGroupBox("Calendar") self.calendar = QCalendarWidget() self.calendar.setMaximumDate(QDate(3000, 1, 1)) self.calendar.setGridVisible(True) self.previewLayout = QGridLayout() self.previewLayout.addWidget(self.calendar, 0, 0) self.previewGroupBox.setLayout(self.previewLayout) def createDatesGroupBox(self): self.datesGroupBox = QGroupBox(self.tr("Selections")) # QUERY self.queryButton = QPushButton("Query Cocorahs Database") self.queryButton.clicked.connect(self.query_on_click) # START DATES self.currentDateEdit = QDateEdit() self.currentDateEdit.setDisplayFormat('dd MMM yyyy') self.currentDateEdit.setDate(self.calendar.selectedDate()) self.currentDateEdit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.currentDateLabel = QLabel("&Date:") self.currentDateLabel.setBuddy(self.currentDateEdit) # END DATES self.maximumDateEdit = QDateEdit() self.maximumDateEdit.setDisplayFormat('dd MMM yyyy') self.maximumDateEdit.setDate(self.calendar.selectedDate()) self.maximumDateEdit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.maximumDateLabel = QLabel("&End Date:") self.maximumDateLabel.setBuddy(self.maximumDateEdit) # LONGITUDE self.textboxLong = QLineEdit(self) self.textboxLongLabel = QLabel("Target Longitude:") # LATITUDE self.textboxLat = QLineEdit(self) self.textboxLatLabel = QLabel("Target Latitude:") # STATES self.textboxStates = QLineEdit(self) self.textboxStatesLabel = QLabel("State(s): e.g., 'CO,NE,WY'") dateBoxLayout = QGridLayout() dateBoxLayout.addWidget(self.currentDateLabel, 1, 0) dateBoxLayout.addWidget(self.currentDateEdit, 1, 1, 1, 2) # dateBoxLayout.addWidget(self.maximumDateLabel, 2, 0) # dateBoxLayout.addWidget(self.maximumDateEdit, 2, 1, 1, 2) dateBoxLayout.addWidget(self.textboxLatLabel, 3, 0) dateBoxLayout.addWidget(self.textboxLat, 3, 1, 1, 2) dateBoxLayout.addWidget(self.textboxLongLabel, 4, 0) dateBoxLayout.addWidget(self.textboxLong, 4, 1, 1, 2) dateBoxLayout.addWidget(self.textboxStatesLabel, 5, 0) dateBoxLayout.addWidget(self.textboxStates, 5, 1, 1, 2) dateBoxLayout.addWidget(self.queryButton, 6, 0,1,3) dateBoxLayout.setRowStretch(5, 1) self.datesGroupBox.setLayout(dateBoxLayout) def infoPanel(self): self.infoPanelBox = QGroupBox(self.tr("Info Console")) self.infoConsole = QTextEdit(self) infoPanelBoxLayout = QGridLayout() infoPanelBoxLayout.addWidget(self.infoConsole, 0, 0, 1, 1) self.infoPanelBox.setLayout(infoPanelBoxLayout) def query_on_click(self): long = self.textboxLong.text() lat = self.textboxLat.text() startDate = self.currentDateEdit.date() endDate = self.maximumDateEdit.date() states = self.textboxStates.text() date_range = list(range(startDate.month(), endDate.month() + 1)) dateString = startDate.toString('MM/dd/yyyy') query(long=long, lat=lat, dateString=dateString, states=states)
class CalendarGUI(QWidget): def __init__(self): super().__init__() self.initializeUI() def initializeUI(self): """ Initialize the window and display its contents to the screen. """ self.setMinimumSize(500, 400) self.setWindowTitle('12.4 – Calendar GUI') self.createCalendar() self.show() def createCalendar(self): """ Set up calendar, others widgets and layouts for main window. """ self.calendar = QCalendarWidget() self.calendar.setGridVisible(True) self.calendar.setMinimumDate(QDate(1900, 1, 1)) self.calendar.setMaximumDate(QDate(2200, 1, 1)) # Connect to newDateSelection slot when currently selected date is changed self.calendar.selectionChanged.connect(self.newDateSelection) current = QDate.currentDate().toString(Qt.DefaultLocaleLongDate) self.current_label = QLabel(current) self.current_label.setObjectName("DateSelected") # Create current, minimum and maximum QDateEdit widgets min_date_label = QLabel("Minimum Date:") self.min_date_edit = QDateEdit() self.min_date_edit.setDisplayFormat("MMM d yyyy") self.min_date_edit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.min_date_edit.setDate(self.calendar.minimumDate()) self.min_date_edit.dateChanged.connect(self.minDatedChanged) current_date_label = QLabel("Current Date:") self.current_date_edit = QDateEdit() self.current_date_edit.setDisplayFormat("MMM d yyyy") self.current_date_edit.setDate(self.calendar.selectedDate()) self.current_date_edit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.current_date_edit.dateChanged.connect(self.selectionDateChanged) max_date_label = QLabel("Maximum Date:") self.max_date_edit = QDateEdit() self.max_date_edit.setDisplayFormat("MMM d yyyy") self.max_date_edit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.max_date_edit.setDate(self.calendar.maximumDate()) self.max_date_edit.dateChanged.connect(self.maxDatedChanged) # Add widgets to group box and add to grid layout dates_gb = QGroupBox("Set Dates") dates_grid = QGridLayout() dates_grid.addWidget(self.current_label, 0, 0, 1, 2, Qt.AlignAbsolute) dates_grid.addWidget(min_date_label, 1, 0) dates_grid.addWidget(self.min_date_edit, 1, 1) dates_grid.addWidget(current_date_label, 2, 0) dates_grid.addWidget(self.current_date_edit, 2, 1) dates_grid.addWidget(max_date_label, 3, 0) dates_grid.addWidget(self.max_date_edit, 3, 1) dates_gb.setLayout(dates_grid) # Create and set main window's layout main_h_box = QHBoxLayout() main_h_box.addWidget(self.calendar) main_h_box.addWidget(dates_gb) self.setLayout(main_h_box) def selectionDateChanged(self, date): """ Update the current_date_edit when the calendar's selected date changes. """ self.calendar.setSelectedDate(date) def minDatedChanged(self, date): """ Update the calendar's minimum date. Update max_date_edit to avoid conflicts with maximum and minimum dates. """ self.calendar.setMinimumDate(date) self.max_date_edit.setDate(self.calendar.maximumDate()) def maxDatedChanged(self, date): """ Update the calendar's maximum date. Update min_date_edit to avoid conflicts with minimum and maximum dates. """ self.calendar.setMaximumDate(date) self.min_date_edit.setDate(self.calendar.minimumDate()) def newDateSelection(self): """ Update date in current_label and current_date_edit widgets when user selects a new date. """ date = self.calendar.selectedDate().toString(Qt.DefaultLocaleLongDate) self.current_date_edit.setDate(self.calendar.selectedDate()) self.current_label.setText(date)
class Calendar(QWidget): key = 'calendar' showLayout = pyqtSignal(str, str) def __init__(self, parent=None): super(Calendar, self).__init__(parent) self.setWindowIcon(IconPth(32, 'Calendar')) self.layout = QGridLayout() self.buildUI() self.setLayout(self.layout) def buildUI(self): self.createPreviewGroupBox() self.createGeneralOptionsGroupBox() self.createDatesGroupBox() self.createTextFormatsGroupBox() self.layout.addWidget(self.previewGroupBox, 0, 0) self.layout.addWidget(self.generalOptionsGroupBox, 0, 1) self.layout.addWidget(self.datesGroupBox, 1, 0) self.layout.addWidget(self.textFormatsGroupBox, 1, 1) self.applySetting() def localeChanged(self, index): self.calendar.setLocale(self.localeCombo.itemData(index)) def firstDayChanged(self, index): self.calendar.setFirstDayOfWeek( Qt.DayOfWeek(self.firstDayCombo.itemData(index))) def selectionModeChanged(self, index): self.calendar.setSelectionMode( QCalendarWidget.SelectionMode( self.selectionModeCombo.itemData(index))) def horizontalHeaderChanged(self, index): self.calendar.setHorizontalHeaderFormat( QCalendarWidget.HorizontalHeaderFormat( self.horizontalHeaderCombo.itemData(index))) def verticalHeaderChanged(self, index): self.calendar.setVerticalHeaderFormat( QCalendarWidget.VerticalHeaderFormat( self.verticalHeaderCombo.itemData(index))) def selectedDateChanged(self): self.currentDateEdit.setDate(self.calendar.selectedDate()) def minimumDateChanged(self, date): self.calendar.setMinimumDate(date) self.maximumDateEdit.setDate(self.calendar.maximumDate()) def maximumDateChanged(self, date): self.calendar.setMaximumDate(date) self.minimumDateEdit.setDate(self.calendar.minimumDate()) def weekdayFormatChanged(self): format = QTextCharFormat() format.setForeground( Qt.GlobalColor( self.weekdayColorCombo.itemData( self.weekdayColorCombo.currentIndex()))) self.calendar.setWeekdayTextFormat(Qt.Monday, format) self.calendar.setWeekdayTextFormat(Qt.Tuesday, format) self.calendar.setWeekdayTextFormat(Qt.Wednesday, format) self.calendar.setWeekdayTextFormat(Qt.Thursday, format) self.calendar.setWeekdayTextFormat(Qt.Friday, format) def weekendFormatChanged(self): format = QTextCharFormat() format.setForeground( Qt.GlobalColor( self.weekendColorCombo.itemData( self.weekendColorCombo.currentIndex()))) self.calendar.setWeekdayTextFormat(Qt.Saturday, format) self.calendar.setWeekdayTextFormat(Qt.Sunday, format) def reformatHeaders(self): text = self.headerTextFormatCombo.currentText() format = QTextCharFormat() if text == "Bold": format.setFontWeight(QFont.Bold) elif text == "Italic": format.setFontItalic(True) elif text == "Green": format.setForeground(Qt.green) self.calendar.setHeaderTextFormat(format) def reformatCalendarPage(self): if self.firstFridayCheckBox.isChecked(): firstFriday = QDate(self.calendar.yearShown(), self.calendar.monthShown(), 1) while firstFriday.dayOfWeek() != Qt.Friday: firstFriday = firstFriday.addDays(1) firstFridayFormat = QTextCharFormat() firstFridayFormat.setForeground(Qt.blue) self.calendar.setDateTextFormat(firstFriday, firstFridayFormat) # May 1st in Red takes precedence. if self.mayFirstCheckBox.isChecked(): mayFirst = QDate(self.calendar.yearShown(), 5, 1) mayFirstFormat = QTextCharFormat() mayFirstFormat.setForeground(Qt.red) self.calendar.setDateTextFormat(mayFirst, mayFirstFormat) def createPreviewGroupBox(self): self.previewGroupBox = QGroupBox("Preview") self.calendar = QCalendarWidget() self.calendar.setMinimumDate(QDate(1900, 1, 1)) self.calendar.setMaximumDate(QDate(3000, 1, 1)) self.calendar.setGridVisible(True) self.calendar.currentPageChanged.connect(self.reformatCalendarPage) self.previewLayout = QGridLayout() self.previewLayout.addWidget(self.calendar, 0, 0, Qt.AlignCenter) self.previewGroupBox.setLayout(self.previewLayout) def createGeneralOptionsGroupBox(self): self.generalOptionsGroupBox = QGroupBox("General Options") self.localeCombo = QComboBox() curLocaleIndex = -1 lang_country = {} for lid in range(QLocale.C, QLocale.LastLanguage + 1): lang = (QLocale(lid).nativeLanguageName()) country = u' '.join( QLocale(lid).nativeCountryName()).encode('utf-8').strip() lang_country[country] = [lang, lid] lid += 1 countries = sorted(list(set([c for c in lang_country]))) countries.remove(countries[0]) for country in countries: lang = lang_country[country][0] label = "%s - %s" % ( (u' '.join(lang).encode('Utf-8').strip()), country) locale = QLocale(lang_country[country][1]) if self.locale().language() == lang and self.locale().country( ) == country: curLocaleIndex = lang_country[country][1] self.localeCombo.addItem(label, locale) if curLocaleIndex != -1: self.localeCombo.setCurrentIndex(curLocaleIndex) self.localeLabel = QLabel("&Locale") self.localeLabel.setBuddy(self.localeCombo) self.firstDayCombo = QComboBox() self.firstDayCombo.addItem("Sunday", Qt.Sunday) self.firstDayCombo.addItem("Monday", Qt.Monday) self.firstDayCombo.addItem("Tuesday", Qt.Tuesday) self.firstDayCombo.addItem("Wednesday", Qt.Wednesday) self.firstDayCombo.addItem("Thursday", Qt.Thursday) self.firstDayCombo.addItem("Friday", Qt.Friday) self.firstDayCombo.addItem("Saturday", Qt.Saturday) self.firstDayLabel = QLabel("Wee&k starts on:") self.firstDayLabel.setBuddy(self.firstDayCombo) self.selectionModeCombo = QComboBox() self.selectionModeCombo.addItem("Single selection", QCalendarWidget.SingleSelection) self.selectionModeCombo.addItem("None", QCalendarWidget.NoSelection) self.selectionModeLabel = QLabel("&Selection fm:") self.selectionModeLabel.setBuddy(self.selectionModeCombo) self.gridCheckBox = QCheckBox("&Grid") self.gridCheckBox.setChecked(self.calendar.isGridVisible()) self.navigationCheckBox = QCheckBox("&Navigation bar") self.navigationCheckBox.setChecked(True) self.horizontalHeaderCombo = QComboBox() self.horizontalHeaderCombo.addItem( "Single letter day names", QCalendarWidget.SingleLetterDayNames) self.horizontalHeaderCombo.addItem("Short day names", QCalendarWidget.ShortDayNames) self.horizontalHeaderCombo.addItem("Long day names", QCalendarWidget.LongDayNames) self.horizontalHeaderCombo.addItem("None", QCalendarWidget.NoHorizontalHeader) self.horizontalHeaderCombo.setCurrentIndex(1) self.horizontalHeaderLabel = QLabel("&Horizontal header:") self.horizontalHeaderLabel.setBuddy(self.horizontalHeaderCombo) self.verticalHeaderCombo = QComboBox() self.verticalHeaderCombo.addItem("ISO week numbers", QCalendarWidget.ISOWeekNumbers) self.verticalHeaderCombo.addItem("None", QCalendarWidget.NoVerticalHeader) self.verticalHeaderLabel = QLabel("&Vertical header:") self.verticalHeaderLabel.setBuddy(self.verticalHeaderCombo) self.localeCombo.currentIndexChanged.connect(self.localeChanged) self.firstDayCombo.currentIndexChanged.connect(self.firstDayChanged) self.selectionModeCombo.currentIndexChanged.connect( self.selectionModeChanged) self.gridCheckBox.toggled.connect(self.calendar.setGridVisible) self.navigationCheckBox.toggled.connect( self.calendar.setNavigationBarVisible) self.horizontalHeaderCombo.currentIndexChanged.connect( self.horizontalHeaderChanged) self.verticalHeaderCombo.currentIndexChanged.connect( self.verticalHeaderChanged) checkBoxLayout = QHBoxLayout() checkBoxLayout.addWidget(self.gridCheckBox) checkBoxLayout.addStretch() checkBoxLayout.addWidget(self.navigationCheckBox) outerLayout = QGridLayout() outerLayout.addWidget(self.localeLabel, 0, 0, 1, 1) outerLayout.addWidget(self.localeCombo, 0, 1, 1, 1) outerLayout.addWidget(self.firstDayLabel, 1, 0, 1, 1) outerLayout.addWidget(self.firstDayCombo, 1, 1, 1, 1) outerLayout.addWidget(self.selectionModeLabel, 2, 0, 1, 1) outerLayout.addWidget(self.selectionModeCombo, 2, 1, 1, 1) outerLayout.addLayout(checkBoxLayout, 3, 0, 1, 2) outerLayout.addWidget(self.horizontalHeaderLabel, 5, 0, 1, 1) outerLayout.addWidget(self.horizontalHeaderCombo, 5, 1, 1, 1) outerLayout.addWidget(self.verticalHeaderLabel, 6, 0, 1, 1) outerLayout.addWidget(self.verticalHeaderCombo, 6, 1, 1, 1) self.generalOptionsGroupBox.setLayout(outerLayout) self.firstDayChanged(self.firstDayCombo.currentIndex()) self.selectionModeChanged(self.selectionModeCombo.currentIndex()) self.horizontalHeaderChanged(self.horizontalHeaderCombo.currentIndex()) self.verticalHeaderChanged(self.verticalHeaderCombo.currentIndex()) def createDatesGroupBox(self): self.datesGroupBox = QGroupBox(self.tr("Dates")) self.minimumDateEdit = QDateEdit() self.minimumDateEdit.setDisplayFormat('MMM d yyyy') self.minimumDateEdit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.minimumDateEdit.setDate(self.calendar.minimumDate()) self.minimumDateLabel = QLabel("&Minimum Date:") self.minimumDateLabel.setBuddy(self.minimumDateEdit) self.currentDateEdit = QDateEdit() self.currentDateEdit.setDisplayFormat('MMM d yyyy') self.currentDateEdit.setDate(self.calendar.selectedDate()) self.currentDateEdit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.currentDateLabel = QLabel("&Current Date:") self.currentDateLabel.setBuddy(self.currentDateEdit) self.maximumDateEdit = QDateEdit() self.maximumDateEdit.setDisplayFormat('MMM d yyyy') self.maximumDateEdit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.maximumDateEdit.setDate(self.calendar.maximumDate()) self.maximumDateLabel = QLabel("Ma&ximum Date:") self.maximumDateLabel.setBuddy(self.maximumDateEdit) self.currentDateEdit.dateChanged.connect(self.calendar.setSelectedDate) self.calendar.selectionChanged.connect(self.selectedDateChanged) self.minimumDateEdit.dateChanged.connect(self.minimumDateChanged) self.maximumDateEdit.dateChanged.connect(self.maximumDateChanged) dateBoxLayout = QGridLayout() dateBoxLayout.addWidget(self.currentDateLabel, 1, 0) dateBoxLayout.addWidget(self.currentDateEdit, 1, 1) dateBoxLayout.addWidget(self.minimumDateLabel, 0, 0) dateBoxLayout.addWidget(self.minimumDateEdit, 0, 1) dateBoxLayout.addWidget(self.maximumDateLabel, 2, 0) dateBoxLayout.addWidget(self.maximumDateEdit, 2, 1) dateBoxLayout.setRowStretch(3, 1) self.datesGroupBox.setLayout(dateBoxLayout) def createTextFormatsGroupBox(self): self.textFormatsGroupBox = QGroupBox("Text Formats") self.weekdayColorCombo = self.createColorComboBox() self.weekdayColorCombo.setCurrentIndex( self.weekdayColorCombo.findText("Black")) self.weekdayColorLabel = QLabel("&Weekday color:") self.weekdayColorLabel.setBuddy(self.weekdayColorCombo) self.weekendColorCombo = self.createColorComboBox() self.weekendColorCombo.setCurrentIndex( self.weekendColorCombo.findText("Red")) self.weekendColorLabel = QLabel("Week&end color:") self.weekendColorLabel.setBuddy(self.weekendColorCombo) self.headerTextFormatCombo = QComboBox() self.headerTextFormatCombo.addItem("Bold") self.headerTextFormatCombo.addItem("Italic") self.headerTextFormatCombo.addItem("Plain") self.headerTextFormatLabel = QLabel("&Header text:") self.headerTextFormatLabel.setBuddy(self.headerTextFormatCombo) self.firstFridayCheckBox = QCheckBox("&First Friday in blue") self.mayFirstCheckBox = QCheckBox("May &1 in red") self.weekdayColorCombo.currentIndexChanged.connect( self.weekdayFormatChanged) self.weekendColorCombo.currentIndexChanged.connect( self.weekendFormatChanged) self.headerTextFormatCombo.currentIndexChanged.connect( self.reformatHeaders) self.firstFridayCheckBox.toggled.connect(self.reformatCalendarPage) self.mayFirstCheckBox.toggled.connect(self.reformatCalendarPage) checkBoxLayout = QHBoxLayout() checkBoxLayout.addWidget(self.firstFridayCheckBox) checkBoxLayout.addStretch() checkBoxLayout.addWidget(self.mayFirstCheckBox) outerLayout = QGridLayout() outerLayout.addWidget(self.weekdayColorLabel, 0, 0, 1, 1) outerLayout.addWidget(self.weekdayColorCombo, 0, 1, 1, 1) outerLayout.addWidget(self.weekendColorLabel, 1, 0, 1, 1) outerLayout.addWidget(self.weekendColorCombo, 1, 1, 1, 1) outerLayout.addWidget(self.headerTextFormatLabel, 2, 0, 1, 1) outerLayout.addWidget(self.headerTextFormatCombo, 2, 1, 1, 1) outerLayout.addLayout(checkBoxLayout, 3, 0, 1, 2) self.textFormatsGroupBox.setLayout(outerLayout) self.weekdayFormatChanged() self.weekendFormatChanged() self.reformatHeaders() self.reformatCalendarPage() def createColorComboBox(self): comboBox = QComboBox() comboBox.addItem("Red", Qt.red) comboBox.addItem("Blue", Qt.blue) comboBox.addItem("Black", Qt.black) comboBox.addItem("Magenta", Qt.magenta) return comboBox def applySetting(self): self.layout.setSpacing(2) self.layout.setSizeConstraint(QLayout.SetFixedSize) self.setSizePolicy(SiPoMin, SiPoMin) def hideEvent(self, event): # self.specs.showState.emit(False) pass def closeEvent(self, event): self.showLayout.emit(self.key, 'hide') event.ignore()
class PricePositionWin(QWidget): """ 价格净持仓窗口 """ def __init__(self, *args, **kwargs): super(PricePositionWin, self).__init__(*args, **kwargs) """ UI部分 """ layout = QVBoxLayout() layout.setContentsMargins(QMargins(0, 0, 0, 0)) # 操作头 title_layout = QHBoxLayout() title_layout.setAlignment(Qt.AlignLeft) title_layout.addWidget(QLabel("交易所:", self)) self.exchange_combobox = QComboBox(self) title_layout.addWidget(self.exchange_combobox) title_layout.addWidget(QLabel("期货品种:", self)) self.variety_combobox = QComboBox(self) self.variety_combobox.setMinimumWidth(100) title_layout.addWidget(self.variety_combobox) title_layout.addWidget(QLabel("合约:", self)) self.contract_combobox = QComboBox(self) title_layout.addWidget(self.contract_combobox) title_layout.addWidget(QLabel("起始日期:")) self.start_date = QDateEdit(self) self.start_date.setDisplayFormat('yyyy-MM-dd') self.start_date.setCalendarPopup(True) title_layout.addWidget(self.start_date) title_layout.addWidget(QLabel("终止日期:")) self.end_date = QDateEdit(self) self.end_date.setDisplayFormat('yyyy-MM-dd') self.end_date.setCalendarPopup(True) title_layout.addWidget(self.end_date) self.analysis_button = QPushButton("开始分析", self) self.analysis_button.setEnabled(False) title_layout.addWidget(self.analysis_button) self.option_widget = TitleOptionWidget(self) self.option_widget.setLayout(title_layout) layout.addWidget(self.option_widget) # 图形表格拖动区 splitter = QSplitter(Qt.Vertical, self) splitter.setContentsMargins(QMargins(10, 5, 10, 5)) # 请求数据遮罩层(需放在splitter之后才能显示,不然估计是被splitter覆盖) self.loading_cover = LoadingCover() self.loading_cover.setParent(self) self.loading_cover.resize(self.parent().width(), self.parent().height()) # 图形区 self.loading_cover.show(text='正在加载资源') self.chart_container = ChartContainWidget(ChartSourceChannel(), 'file:/templates/price_position.html', self) self.chart_container.page().loadFinished.connect(self.page_load_finished) splitter.addWidget(self.chart_container) # 表格区 self.table_widget = QWidget(self) table_layout = QVBoxLayout() table_layout.setContentsMargins(QMargins(0, 0, 0, 0)) opt_widget = QWidget(self.table_widget) opt_lt = QHBoxLayout(opt_widget) opt_lt.setContentsMargins(0,0,0,0) opt_widget.setLayout(opt_lt) # 日期选择,全品种净持率查看 self.all_date_edit = QDateEdit(self) self.all_date_edit.setCalendarPopup(True) self.all_date_edit.setDisplayFormat('yyyy-MM-dd') self.all_date_edit.setDate(QDate.currentDate()) opt_lt.addWidget(self.all_date_edit) self.all_query_button = QPushButton('查询全净持率', self) opt_lt.addWidget(self.all_query_button) # 增加净持率 self.add_net_rate = QPushButton('增加列', self) opt_lt.addWidget(self.add_net_rate) opt_lt.addStretch() # 导出数据按钮 self.export_button = QPushButton('导出EXCEL', self) self.export_button.setEnabled(False) opt_lt.addWidget(self.export_button) opt_widget.setFixedHeight(30) table_layout.addWidget(opt_widget) self.data_table = QTableWidget(self) self.data_table.verticalHeader().hide() self.data_table.setFocusPolicy(Qt.NoFocus) self.data_table.setColumnCount(7) self.data_table.setHorizontalHeaderLabels(['日期', '收盘价', '总持仓', '多头', '空头', '净持仓', '净持仓率%']) self.data_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.data_table.setSelectionBehavior(QAbstractItemView.SelectRows) self.data_table.setSelectionMode(QAbstractItemView.SingleSelection) table_layout.addWidget(self.data_table) # 全品种净持仓率显示表 self.all_table = QTableWidget(self) self.all_table.hide() table_layout.addWidget(self.all_table) self.table_widget.setLayout(table_layout) splitter.addWidget(self.table_widget) splitter.setSizes([self.parent().height() * 0.6, self.parent().height() * 0.4]) layout.addWidget(splitter) # 设置表行高,各行颜色 self.data_table.verticalHeader().setDefaultSectionSize(18) # 设置行高(与下行代码同时才生效) self.data_table.verticalHeader().setMinimumSectionSize(18) self.data_table.setAlternatingRowColors(True) self.data_table.setObjectName('dataTable') self.setStyleSheet( "#dataTable{selection-color:rgb(80,100,200);selection-background-color:rgb(220,220,220);" "alternate-background-color:rgb(230,254,238);gridline-color:rgb(60,60,60)}" ) # 设置表头,表滚动条样式 self.data_table.horizontalHeader().setStyleSheet(HORIZONTAL_HEADER_STYLE) self.data_table.horizontalScrollBar().setStyleSheet(HORIZONTAL_SCROLL_STYLE) self.data_table.verticalScrollBar().setStyleSheet(VERTICAL_SCROLL_STYLE) self.setLayout(layout) """ 业务逻辑部分 """ self.query_type = 'contract' # 当前查询的数据类型 # 网管器 self.network_manager = getattr(qApp, 'network') # 关联交易所变化信号 self.exchange_combobox.currentTextChanged.connect(self.get_variety_with_exchange) # 关联品种变化信号 self.variety_combobox.currentTextChanged.connect(self.get_contract_with_variety) # 关联合约变化的信号 self.contract_combobox.currentTextChanged.connect(self.get_min_max_date_with_contract) # 添加交易所 for exchange_item in EXCHANGES: self.exchange_combobox.addItem(exchange_item['name'], exchange_item['id']) # 关联开始计算按钮信号 self.analysis_button.clicked.connect(self.get_analysis_data) # 关联导出数据信息 self.export_button.clicked.connect(self.export_table_to_excel) # 查询全品种净持仓率的信号 self.all_query_button.clicked.connect(self.to_query_all_position) # 增加净持率列的信号 self.add_net_rate.setEnabled(False) self.add_net_rate.clicked.connect(self.to_add_new_column_rate) # 点击表头排序 self.all_table.horizontalHeader().sectionClicked.connect(self.all_table_horizontal_clicked) self.current_table = 'single_contract' def all_table_horizontal_clicked(self, col): if col < 7: return self.all_table.sortItems(col) # 重新设置一下颜色 for row in range(self.all_table.rowCount()): for col in range(self.all_table.columnCount()): item = self.all_table.item(row, col) if row % 2 == 0: item.setBackground(QBrush(QColor(230, 254, 238))) else: item.setBackground(QBrush(QColor(255, 255, 255))) def to_add_new_column_rate(self): # 新增净持率列 new_column_date = self.all_date_edit.text() self.show_loading("正在获取数据") url = SERVER_2_0 + 'dsas/price-position/?ds={}&de={}'.format(new_column_date, new_column_date) reply = self.network_manager.get(QNetworkRequest(QUrl(url))) reply.finished.connect(self.new_column_data_reply) def new_column_data_reply(self): reply = self.sender() self.loading_finished() if reply.error(): logger.error('GET NEW COLUMN NET POSTION ERROR. STATUS:{}'.format(reply.error())) else: data = json.loads(reply.readAll().data().decode('utf8')) variety_data = data.get('data', None) if not variety_data: return current_columns = self.all_table.columnCount() self.all_table.insertColumn(current_columns) self.all_table.setHorizontalHeaderItem(current_columns, QTableWidgetItem(self.all_date_edit.text())) self.insert_column_data(variety_data) reply.deleteLater() def insert_column_data(self, data): # 添加列数据 # 过滤data数据 data = list(filter(lambda x: x['variety_en'] == x['contract'], data)) # 数据转为dict形式 rate_data = {item['variety_en']: item for item in data} current_column = self.all_table.columnCount() - 1 for row in range(self.all_table.rowCount()): row_item = self.all_table.item(row, 0) variety_en = row_item.data(Qt.UserRole)['variety_en'] data_item = rate_data.get(variety_en) if not data_item: continue # 计算净持率 a = float(data_item['net_position'].replace(',', '')) b = float(data_item['position_volume'].replace(',', '')) rate = f'{round(a * 100 / b, 2)}%' if b > 0 else '-' display = round(a * 100 / b, 2) if b > 0 else '-' new_item = QTableWidgetItem(rate) new_item.setTextAlignment(Qt.AlignCenter) new_item.setData(Qt.DisplayRole, display) self.all_table.setItem(row, current_column, new_item) if row % 2 == 0: new_item.setBackground(QBrush(QColor(230, 254, 238))) def to_query_all_position(self): self.show_loading("正在获取数据") current_date = self.all_date_edit.text() url = SERVER_2_0 + 'dsas/price-position/?ds={}&de={}'.format(current_date, current_date) reply = self.network_manager.get(QNetworkRequest(QUrl(url))) reply.finished.connect(self.all_variety_position_reply) def all_variety_position_reply(self): reply = self.sender() self.loading_finished() if reply.error(): logger.error('GET ALL VARIETY NET POSTION ERROR. STATUS:{}'.format(reply.error())) else: data = json.loads(reply.readAll().data().decode('utf8')) self.show_all_variety_net_position(data.get('data', [])) reply.deleteLater() def show_all_variety_net_position(self, data): # 过滤data数据 show_list = list(filter(lambda x: x['variety_en'] == x['contract'], data)) self.all_table.clear() titles = ['日期', '品种', '主力收盘价', '总持仓量', '前20多单量', '前20空单量', '前20净持仓', '净持率%'] columns = ['quotes_date', 'variety_name', 'close_price', 'position_volume', 'long_position', 'short_position', 'net_position', 'net_rate'] self.all_table.setRowCount(len(show_list)) self.all_table.setColumnCount(len(columns)) self.all_table.setHorizontalHeaderLabels(titles) for row, p_item in enumerate(show_list): print(p_item) for col, key in enumerate(columns): if key == 'net_rate': a = float(p_item['net_position'].replace(',', '')) b = float(p_item['position_volume'].replace(',', '')) rate = f'{round(a * 100 / b, 2)}%' if b > 0 else '-' item = QTableWidgetItem(rate) display = round(a * 100 / b, 2) if b > 0 else '-' item.setData(Qt.DisplayRole, display) else: item = QTableWidgetItem(str(p_item[key])) item.setTextAlignment(Qt.AlignCenter) if row % 2 == 0: item.setBackground(QBrush(QColor(230, 254, 238))) if col == 0: item.setData(Qt.UserRole, {'variety_en': p_item['variety_en']}) self.all_table.setItem(row, col, item) self.data_table.hide() self.all_table.show() self.current_table = 'all_variety' if len(show_list) > 0: self.export_button.setEnabled(True) self.add_net_rate.setEnabled(True) def resizeEvent(self, event): super(PricePositionWin, self).resizeEvent(event) self.loading_cover.resize(self.parent().width(), self.parent().height()) def clear_contents(self): """ 清除图形和表格 """ self.chart_container.clear_chart() self.data_table.clearContents() self.data_table.setRowCount(0) def show_loading(self, show_text): """ 显示正在请求数据 """ # 请求数据 self.loading_cover.show(text=show_text) self.analysis_button.setEnabled(False) self.export_button.setEnabled(False) self.clear_contents() def loading_finished(self): """ 请求数据结束 """ self.loading_cover.hide() self.analysis_button.setEnabled(True) def page_load_finished(self): """ 页面加载完成 """ # self.loading_cover.hide() pass def get_variety_with_exchange(self): """ 获取交易所下的所有品种 """ self.show_loading("正在获取品种") url = SERVER_API + 'exchange-variety/?is_real=1&exchange={}'.format(self.exchange_combobox.currentData()) reply = self.network_manager.get(QNetworkRequest(QUrl(url))) reply.finished.connect(self.exchange_variety_reply) def exchange_variety_reply(self): # 交易所品种返回 reply = self.sender() if reply.error(): logger.error('GET EXCHANGE VARIETY ERROR. STATUS:{}'.format(reply.error())) else: data = json.loads(reply.readAll().data().decode('utf8')) self.set_current_variety(data['varieties']) reply.deleteLater() def set_current_variety(self, varieties: list): """ 设置当前的品种 """ self.variety_combobox.clear() for variety_item in varieties: self.variety_combobox.addItem(variety_item['variety_name'], variety_item['variety_en']) def get_contract_with_variety(self): """ 根据品种获取全部合约 """ if not self.variety_combobox.currentData(): return self.show_loading('正在获取合约') url = SERVER_API + 'price-position-contracts/?variety_en={}'.format(self.variety_combobox.currentData()) reply = self.network_manager.get(QNetworkRequest(QUrl(url))) reply.finished.connect(self.variety_contracts_reply) def variety_contracts_reply(self): """ 品种的所有合约返回 """ reply = self.sender() if reply.error(): logger.error("GET CONTRACTS OF VARIETY ERROR. STATUS:{}".format(reply.error())) else: data = json.loads(reply.readAll().data().decode('utf8')) self.set_current_contract(data['contracts']) reply.deleteLater() def set_current_contract(self, contracts: list): self.contract_combobox.clear() # 将第一个合约进行英文与数字的分离 if len(contracts) > 0: variety = [''.join(list(g)) for k, g in groupby(contracts[0]['contract'], key=lambda x: x.isdigit())] v = variety[0] if len(variety[0]) <= 2 else variety[0][:2] self.contract_combobox.addItem(v) for contract_item in contracts: self.contract_combobox.addItem(contract_item['contract']) def get_min_max_date_with_contract(self): """ 根据合约获取时间范围 """ if not self.contract_combobox.currentText(): return current_contract = self.contract_combobox.currentText() split_list = [''.join(list(g)) for k, g in groupby(current_contract, key=lambda x: x.isdigit())] if len(split_list) > 1: # 查询的是合约 self.query_type = 'contract' self.show_loading('正在获取日期范围') url = SERVER_API + 'price-position-dates/?contract={}'.format(self.contract_combobox.currentText()) reply = self.network_manager.get(QNetworkRequest(QUrl(url))) reply.finished.connect(self.min_max_date_reply) else: # 查询的是品种 max_date = int(datetime.datetime.strptime(datetime.datetime.today().strftime('%Y-%m-%d'), '%Y-%m-%d').timestamp()) min_date = int(datetime.datetime.strptime(str(datetime.datetime.today().year - 3), '%Y').timestamp()) self.set_min_and_max_date(min_date, max_date) self.query_type = 'variety' self.loading_finished() # 加载数据结束 def min_max_date_reply(self): """ 日期值返回 """ reply = self.sender() if reply.error(): logger.error("GET MIN & MAX DATE WITH CONTRACT ERROR. STATUS:{}".format(reply.error())) else: data = json.loads(reply.readAll().data().decode('utf8')) min_max_date = data["dates"] self.set_min_and_max_date(min_max_date['min_date'], min_max_date['max_date']) reply.deleteLater() self.loading_finished() # 加载数据结束 def set_min_and_max_date(self, min_date: int, max_date: int): """ 设置最大最小日期 """ if not min_date or not max_date: self.analysis_button.setEnabled(False) return min_date = datetime.datetime.fromtimestamp(min_date) max_date = datetime.datetime.fromtimestamp(max_date) q_min_date = QDate(min_date.year, min_date.month, min_date.day) q_max_date = QDate(max_date.year, max_date.month, max_date.day) self.start_date.setDateRange(q_min_date, q_max_date) self.start_date.setDate(q_min_date) self.end_date.setDateRange(q_min_date, q_max_date) self.end_date.setDate(q_max_date) self.analysis_button.setEnabled(True) def get_analysis_data(self): """ 获取结果数据 """ if not self.contract_combobox.currentText(): QMessageBox.information(self, '错误', '请先选择合约后再操作.') return self.show_loading('正在获取资源数据') min_date = int(datetime.datetime.strptime(self.start_date.text(), '%Y-%m-%d').timestamp()) max_date = int(datetime.datetime.strptime(self.end_date.text(), '%Y-%m-%d').timestamp()) if self.query_type == 'contract': url = SERVER_API + 'price-position/?contract={}&min_date={}&max_date={}'.format( self.contract_combobox.currentText(), min_date, max_date ) elif self.query_type == 'variety': url = SERVER_2_0 + 'dsas/price-position/?ds={}&de={}&c={}'.format( self.start_date.text(), self.end_date.text(), self.contract_combobox.currentText() ) else: return reply = self.network_manager.get(QNetworkRequest(QUrl(url))) reply.finished.connect(self.price_position_reply) def price_position_reply(self): """ 获取数据返回 """ reply = self.sender() if reply.error(): logger.error("GET PRICE-POSITION DATA ERROR. STATUS:{}".format(reply.error())) else: data = json.loads(reply.readAll().data().decode('utf8')) if self.query_type == 'variety': # 处理数据,由于新版接口与旧版不一致 for item in data['data']: item['date'] = item['quotes_date'].replace('-', '') item['contract'] = item['variety_en'] item['empty_volume'] = float(item['position_volume'].replace(',', '')) item['long_position'] = float(item['long_position'].replace(',', '')) item['short_position'] = float(item['short_position'].replace(',', '')) del item['quotes_ts'] del item['position_volume'] del item['net_position'] del item['quotes_date'] self.set_current_data_to_table(data['data'].copy()) # 数据在表格展示 self.export_button.setEnabled(True) # 组合基本配置信息和源数据传递到页面 base_option = { 'title': '{}价格与净持率趋势图'.format(self.contract_combobox.currentText()) } self.set_current_chart_to_page(json.dumps(data['data']), json.dumps(base_option)) reply.deleteLater() self.loading_finished() def set_current_data_to_table(self, data_items: list): """ 将数据在表格显示 """ self.data_table.clearContents() self.data_table.setRowCount(len(data_items)) data_items.reverse() for row, row_item in enumerate(data_items): t_item0 = QTableWidgetItem(row_item['date']) t_item0.setTextAlignment(Qt.AlignCenter) self.data_table.setItem(row, 0, t_item0) t_item1 = QTableWidgetItem(str(row_item['close_price'])) t_item1.setTextAlignment(Qt.AlignCenter) self.data_table.setItem(row, 1, t_item1) t_item2 = QTableWidgetItem(str(row_item['empty_volume'])) t_item2.setTextAlignment(Qt.AlignCenter) self.data_table.setItem(row, 2, t_item2) t_item3 = QTableWidgetItem(str(row_item['long_position'])) t_item3.setTextAlignment(Qt.AlignCenter) self.data_table.setItem(row, 3, t_item3) t_item4 = QTableWidgetItem(str(row_item['short_position'])) t_item4.setTextAlignment(Qt.AlignCenter) self.data_table.setItem(row, 4, t_item4) t_item5 = QTableWidgetItem(str(row_item['long_position'] - row_item['short_position'])) t_item5.setTextAlignment(Qt.AlignCenter) self.data_table.setItem(row, 5, t_item5) rate = '-' if row_item['empty_volume'] == 0 else str( round((row_item['long_position'] - row_item['short_position']) * 100 / row_item['empty_volume'], 2)) t_item6 = QTableWidgetItem(rate) t_item6.setTextAlignment(Qt.AlignCenter) self.data_table.setItem(row, 6, t_item6) self.current_table = 'single_contract' self.data_table.show() self.all_table.hide() def set_current_chart_to_page(self, source_data: str, base_option: str): """ 设置数据到图形区域 """ self.chart_container.set_chart_option(source_data, base_option) def export_table_to_excel(self): """ 导出表格数据到excel""" if self.current_table == 'single_contract': # 1 读取表格数据: table_df = self.read_table_data() # 2 选定保存的位置 # 保存的文件名称 filename = '{}价格-净持率数据'.format(self.contract_combobox.currentText()) filepath, _ = QFileDialog.getSaveFileName(self, '保存文件', filename, 'EXCEL文件(*.xlsx *.xls)') if filepath: # 3 导出数据 writer = pd.ExcelWriter(filepath, engine='xlsxwriter', datetime_format='YYYY-MM-DD') table_df.to_excel(writer, sheet_name='价格-净持率', index=False, encoding='utf8') writer.save() if self.current_table == 'all_variety': df = self.read_all_table_data() # 读取全品种表格的数据 # 2 选定保存的位置 # 保存的文件名称 filename = '{}全品种价格-净持率数据'.format(self.all_date_edit.text()) filepath, _ = QFileDialog.getSaveFileName(self, '保存文件', filename, 'EXCEL文件(*.xlsx *.xls)') if filepath: # 3 导出数据 writer = pd.ExcelWriter(filepath, engine='xlsxwriter', datetime_format='YYYY-MM-DD') df.to_excel(writer, sheet_name='全品种价格-净持率', index=False, encoding='utf8') writer.save() def read_all_table_data(self): header_list = [] value_list = [] for header_col in range(self.all_table.columnCount()): header_list.append( self.all_table.horizontalHeaderItem(header_col).text() ) for row in range(self.all_table.rowCount()): row_list = [] for col in range(self.all_table.columnCount()): item_value = self.all_table.item(row, col).text() try: value = datetime.datetime.strptime(item_value, '%Y%m%d') if col == 0 else float( self.all_table.item(row, col).text()) except ValueError: value = item_value row_list.append(value) value_list.append(row_list) return pd.DataFrame(value_list, columns=header_list) def read_table_data(self): """ 读取表格数据 """ header_list = [] value_list = [] for header_col in range(self.data_table.columnCount()): header_list.append( self.data_table.horizontalHeaderItem(header_col).text() ) for row in range(self.data_table.rowCount()): row_list = [] for col in range(self.data_table.columnCount()): item_value = self.data_table.item(row, col).text() try: value = datetime.datetime.strptime(item_value, '%Y%m%d') if col == 0 else float( self.data_table.item(row, col).text()) except ValueError: value = item_value row_list.append(value) value_list.append(row_list) return pd.DataFrame(value_list, columns=header_list)